Skip to content

Instantly share code, notes, and snippets.

@machty
Last active February 7, 2017 17:45
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save machty/68afad4c03109f36d4f4cffaae3c170b to your computer and use it in GitHub Desktop.
Save machty/68afad4c03109f36d4f4cffaae3c170b to your computer and use it in GitHub Desktop.
embercommunity.slack.com #topic-forms discussion
joined #topic-forms, and invited @machty
locks [11:05 AM]
thar you go
machty [11:06 AM]
thank you!
[11:07]
@samselikoff @cowboyd
samselikoff [11:07 AM]
joined #topic-forms by invitation from @machty, along with @cowboyd. Also, @willrax joined.
machty [11:08 AM]
set the channel purpose: Best practices for building forms
machty [11:09 AM]
i'm interested in this topic because i had to build my first basic crud admin panel in like 3 years
samselikoff [11:09 AM]
boom
[11:09]
thanks dude
machty [11:09 AM]
and the amount of boilerplate and lack of conventions is outlandish
[11:09]
i'm gonna put together a gist of where i landed
samselikoff [11:09 AM]
ya. nice
[11:10]
every time I go back to rails and make a form it's incredible how simple and fast it is. I mean there's _so_ much you don't have to do
machty [11:10 AM]
yeah
samselikoff [11:10 AM]
form-for, integration with validations
locks [11:11 AM]
lack of crud scaffolding is a common complaint (edited)
willrax [11:11 AM]
nearly every form across our app has been built differently until we recently sat down and tried to work out some more conventions around it
locks [11:11 AM]
specifically from Rails devs
samselikoff [11:11 AM]
oof. ya will
[11:12]
and every team is basically doing this on their own
[11:12]
differently
willrax [11:12 AM]
yep
samselikoff [11:15 AM]
So the series we're making is not focused on solving problems of boilerplate, it's more in response to the "rise of ddau" we've seen in the community
[11:15]
I will wait for Charles
[11:15]
(however - the boilerplate/conventions problem is real and important and needs to be solved too)
[11:15]
they are related, I guess
fivetanley [11:18 AM]
joined #topic-forms. Also, @climbingnarc joined.
samselikoff [11:21 AM]
everybody use your brainpowers to ~ summon charles ~ (edited)
machty [11:22 AM]
or @fivetanley can just drive over and poke him
fivetanley [11:23 AM]
i’m sorry i have standup and then a very important bbq meeting
samselikoff [11:24 AM]
priorities
ryanto [11:40 AM]
joined #topic-forms. Also, @mmun joined.
machty [11:49 AM]
added this Markdown (raw) snippet: machty show and tell
# Code machty recently wrote
for a CRUD section of an admin app.
## Routing
this.route('platform-users', function() {
this.route('edit', { path: 'edit/:user_id' });
this.route('new');
});
this.route('employee-logins', function() {
this.route('edit', { path: 'edit/:employee_login_id' });
this.route('new');
});
## Dir structure
FYI Each route template renders a component. We don't use controllers
in any way. (This is kinda just a side point but sharing in case of
confusion.)
▾ employee-logins/
▾ edit/
template.hbs
▾ form/
component.js
template.hbs
▾ index/
component.js
template.hbs
▾ new/
component.js
template.hbs
## Code
Here are relevant snippets from the form component we use:
onSubmit: task(function*(data) {
let user = this.get('user')
user.setProperties(data)
let [ error ] = yield this.get('notify').try(user.save());
let newUser = this.get('newUser');
let notify = this.get('notify');
if (!error) {
if (newUser) {
notify.info("Successfully Created PIN", {
closeAfter: 5000
});
this.get('routing').transitionTo('employee-logins');
} else {
notify.info("Changes Saved", {
closeAfter: 5000
});
}
}
}).drop(),
goBack: task(function*() {
this.get('user').rollbackAttributes();
this.get('routing').transitionTo('employee-logins')
}),
We use `ember-notify` and overrode the default service as follows:
```js
import Notify from 'ember-notify';
import { task } from 'ember-concurrency';
import { InvalidError } from 'ember-ajax/errors';
export default Notify.extend({
try(promise) {
return this.get('_tryTask').perform(promise);
},
_tryTask: task(function * (promise) {
try {
return [null, yield promise];
} catch(e) {
this.reportError(e);
return [e];
}
}),
reportError(e) {
if (e instanceof InvalidError) {
this.error(e.errors[0].detail);
} else {
this.error("Something went wrong, try again soon.");
}
},
});
```
Here's what the above accomplishes:
1. We delegate to our overridden `notify` service to display an error banner
(via the `try` method). This is our hacky way of displaying
server-side validations. In a future iteration we'll do the work of
inlining the server-side validation errors in the form (would be nice
to have conventions surrounding this).
2. I use the Node/Go style approach for error handling, such that rather
than throwing exceptions, I just return a tuple of `[error, result]`
so I don't have to litter my code with try-catches, which sucks to
have to write and I feel doesn't compose well.
3. onSubmit is an EC task so that 1) I can drive loading state in the template
with `onSubmit.isRunning` and prevent multiple submits via `.drop()`
Here's what sucks about the above that I hope to improve in the future:
1. `NotifyService#try` is an OK pattern but it's weird to teach a
notification service about form submissions. I could probably move
that to a `services/forms` service or something. (This is a problem
specific to my code and not to the general discussion about lack of
conventions)
2. I haven't shown code for this, but I/we use a homegrown form
generator based on a json schema, e.g. describe all the fields and
expected validations via json/pojo and a component will render them
and do client-side validation. But now we have to retrofit it with
server-side error handling if we want to inline the errors
3. The rollbackAttributes cleanup that we have to do in our `goBack`
task (`goBack` itself is a break from conventions that I don't want to
go into right now) **MEGA SUCKS**. This is more an issue with Ember
Data conventions, which may some day be solved with store forking or
differentiating between in-progress / canonical records or something,
but it's all part of the presently crappy experience with forms.
## General conclusions/musings
Whatever solution/conventions we land on should assume the following:
1. Internet connection is crappy
2. There are both client-side and server-side validations
3. It should be easy to display both client-side/server-side errors
inline (next to the offending field), or aggregated with all errors,
or in some `ember-notify`ish banner, or all of the above, and it
should be trivial to switch between any above approach.
4. Data-down actions up
5. The user is erratic and likes to double click stuff
6. It should be easy to drive button state with as in
[this
twiddle](https://ember-twiddle.com/#/f7a2c3b60502420a9e48a8c0edd9b279?fileTreeShown=false&numColumns=2&openFiles=templates.application.hbs%2Clocales.en.translations.js)
Add Comment Collapse This snippet was truncated for display: see it in full.
machty [11:50 AM]
not sure if it's possible to render markdown snippets
[11:50]
plz don't use my brokeass code to hijack my startup
stevenwu [11:52 AM]
joined #topic-forms
mmun [11:53 AM]
the ▾ are a nice touch
[11:53]
i thought my editor was inserting some code folds haha
ryanto [11:58 AM]
machty our forms are pretty close to yours. we dont have a notify service / Either pattern, but the rest is similar
cowboyd [11:58 AM]
Oh hey yall
[11:58]
Started a twitter ball rolling and then ran off :slightly_smiling_face:
samselikoff [12:00 PM]
ya!
[12:01]
so charles - initial thoughts? what have you been thinking about
cowboyd [12:03 PM]
just reading read @machty’s gist
mmun [12:06 PM]
@machty: I will add to your musings… a lot of my boilerplate comes from making form objects because I only want to “commit" changes locally once they have been sent to and approved by the server.
ryanto [12:08 PM]
@mmun yup, likewise. a lot of boiler plate for us ends up being how to apply changes - two way bound, optimistic (before calling `.save()`), or pessimistic
samselikoff [12:09 PM]
mmun i think this should be configurable at the ember data layer. There's a nice pattern kris selden showed me where you can make a draftable subclass of a model
[12:09]
global Ember Data config, as well as `model.save({ pessimistic: true })`
cowboyd [12:09 PM]
So in terms of high level architecture patterns rather than code / libraries, we try to abide by the following.
1. form values only ever see a snapshot. If you’re using ember-data, this means you make a complete copy
2. updates happen transactionally in a single method. I think this echoes @mmun’s statement. If your update (or create) succeeds the snapshot is updated
willrax [12:09 PM]
we’ve been using ember-changeset to get something like this
samselikoff [12:10 PM]
charles how are you making copies of ember data models? have you done it with relationship graphs
mmun [12:10 PM]
this issue I find with ember-data is that you have to actually mutate a model in order to save it. so while the request is in-flight, your app can be in a confusing looking state. Of course there are ways to work around this but they are cumbersome. (edited)
cowboyd [12:10 PM]
This is getting into implementation details, but we have a “pull” model.
[12:11]
basically, we have form and field components
locks [12:12 PM]
Don't look at poupapp.com's forms
[12:12]
So, this might be too early but, fastboot enabled forms?
cowboyd [12:12 PM]
if you have a field like `{{x-field attr="foo"}}`
[12:12]
then you know to “pull” the `foo` attribute from the source object onto the snapshot
[12:12]
otherwise, if there’s no field for it, you don’t care
cherewaty [12:13 PM]
joined #topic-forms by invitation from @cowboyd
mmun [12:13 PM]
what is `model.save({ pessimistic: true })`? a custom adapter thing? (edited)
samselikoff [12:14 PM]
just a suggestion
mmun [12:14 PM]
o
samselikoff [12:14 PM]
no suggested api, that would only push changes into model after confirm from server
[12:14]
sorry. Only mark it as saved
[12:15]
not sure how it would work. Anyway
[12:15]
Interesting charles. I like the idea of snapshots/draft models, I think they solve a lot of problems
[12:15]
(in the past i've used draft models)
[12:16]
As far as the EmberMap series we're making, it's tackling a bit of a different aspect of the problem
mmun [12:17 PM]
I think @runspired is interested in supporting forking at the individual model level (edited)
samselikoff [12:17 PM]
would be great. I've basically hacked this in
[12:17]
DraftPost = Post.extend
[12:17]
then customize the adapter to still point to `/posts`. But your drafts have all the methods/CPs your model does
mmun [12:17 PM]
do you change the adapter type to be `post`?
[12:17]
yeah
[12:17]
that makes a lot of sense
samselikoff [12:18 PM]
exactly. Then if you save a `DraftPost` and, in adapter you say, if its successful `store.push('post', draft_post_id, draft_post_attrs)`
[12:18]
it works really well, relationships are hard.
mmun [12:19 PM]
do you have an example of the adapter code for that?
samselikoff [12:19 PM]
ya, sec
mmun [12:19 PM]
seems like a good workaround for most of my cases
samselikoff [12:20 PM]
wanted to extract it but didn't so it might be specific
[12:20]
yah its really nice
mmun [12:20 PM]
I think it’s too complicated to expect beginners to be able to do this
samselikoff [12:22 PM]
definitely. need to make an addon
[12:26]
@mmun https://gist.github.com/samselikoff/87cdf2db35ca8002cf38c4b7cf7df92d
mmun [12:27 PM]
ah, more than i expected
[12:27]
thanks
machty [12:27 PM]
it megasucks that this convo is going to be archived
locks [12:27 PM]
discuss thread? ;x
[12:27]
we want turn on the discourse slack integration, but I can't
samselikoff [12:27 PM]
To use, say you have a `lesson` from a route's `model` hook. Then you could pass `lesson` into a `{{lesson-form}}`. The form could then `lesson.createDraft()` and pass that around to all the inputs. When the form calls `draft.save()`, upon completion the adapter layer rolls the successfully-persisted changes back into the original `lesson` model.
runspired [12:28 PM]
joined #topic-forms by invitation from @mmun
locks [12:28 PM]
(I think it enables you to say "make a thread starting with X")
cowboyd [12:28 PM]
@samselikoff with the pull approach, you don’t need to proactively create a draft, and it works for all object types
[12:29]
that said, the draft api is still super useful inside the actual update transaction since you can contain the effects of the update from the rest of your application until you’re sure the transaction fully succeeded or failed.
samselikoff [12:29 PM]
right
[12:29]
I would love to go through details of your implementation some time
[12:30]
So back to the video series we're making. Again I think a lot of what we're talking about here is beyond the scope of what we're making
[12:30]
But we've seen some patterns come up in consulting clients and on slack so we wanted to talk about, data down actions up across different types of forms/components in an app
mmun [12:31 PM]
that’s exactly why the draft pattern is appealing to me. it just sucks that it requires so much boilerplate in the adapter. you also probably need a Lesson -> DraftLesson cloner.
samselikoff [12:31 PM]
Basically have seen something like this or a varient of it in a lot of places:
```{{blog-post-form
title=post.title
content=post.content
on-save=(action 'handleSave')
on-cancel=(action 'handleCancel')}}
```
[12:31]
mmun check out the gist. The cloner is super simple in this case
[12:32]
and I had other methods to clone different models & set up some relationships sometimes
[12:32]
So, about the ^ snippet. I think some folks learned about DDAU and have been using it almost ritualistically across their entire application
[12:33]
but DDAU came about to help make data flow easier to reason about
[12:33]
The problem with the interface above is, a `blog-post-form` isn't a dumb reusable component, like a datepicker is
[12:34]
you would never write
```{{blog-post-form
title=post1.title
content=post2.content}}
```
cowboyd [12:34 PM]
We tend to use pure-data components to model forms, that way they can be layered onto anything.
samselikoff [12:35 PM]
I think in some cases, the pendulum has swung too far, and people are too focused on not violating data down actions up that leads them to overabstract
mmun [12:35 PM]
@samselikoff: to be precise, `post` there would need to be a draft post, right?
samselikoff [12:35 PM]
(@mmun yes - but again i'm kinda tlaking about something different/more simpler than the draft case)
[12:35]
i'm making a more general point
[12:36]
or arguing a general point anyway.
mmun [12:36 PM]
towards a generic form builder?
samselikoff [12:36 PM]
For example, one-way bound `{{input value=val on-change=(mut val)}}`
[12:36]
(no - even simpler)
[12:36]
versus `{{input value=val}}` two-way bound
[12:37]
Ive worked with devs/teams that have basically lost hte ability to think through these situations, because they are so focused on not violating DDAU with every line of code
mmun [12:37 PM]
ah, you’re saying 2wb is fine if its effects are constrained?
samselikoff [12:37 PM]
yes
[12:38]
I think form debt comes in a lot of flavors
mmun [12:38 PM]
yeah, the whole core team agrees with you there. that’s the motivation for the `mut` “experiment” :stuck_out_tongue: (edited)
samselikoff [12:38 PM]
There's a class of hard problems like the ones we've been talking about so far
[12:38]
drafts, saving relationship graphs, optimistic vs. pessimistic saves
[12:38]
I think this is really hard and all the libs (changesets) and dif approaches (charles pull, draftable) are good and we need to move fwd on
[12:39]
But another class of form debt I've seen with consulting clients & beginners, is
[12:39]
folks that use ddau to make their forms pure and side-effect free. Which leads to passing models or attrs layers and layers down, only to send the action from the form layers and layers up
[12:39]
They try to decouple their form from its side effects in the name of ddau
[12:40]
But ddau was created because, some controls (like datepicker) have unpredictable side effects
[12:40]
In the case of a `blog-post-form`, you're making that form _precisely for_ its side effects (edited)
[12:40]
and your attempts to make it decoupled, end up spilling over layers of your application
cowboyd [12:40 PM]
I’m not seeing why those side effects can’t be contained inside actions.
samselikoff [12:40 PM]
So i think this is a misunderstanding of the role of services/ model layer in an ember app
mmun [12:41 PM]
i think i’m gonna need an example
[12:41]
:dizzy_face:
samselikoff [12:41 PM]
I think the simplest example is `{{input value=val on-change=(mut val)}}` vs `{{input value=val}}`
[12:41]
that's the absolute simplest example
mmun [12:42 PM]
but that doesn’t leak outside of the template layer, so i don’t think there is an important difference there. (edited)
ryanlabouve [12:42 PM]
joined #topic-forms
samselikoff [12:42 PM]
(assume first input is one-way bound
locks [12:42 PM]
you know what is one-way bound? native inputs :X
samselikoff [12:42 PM]
doesn't leak outside template, ok. But point is
[12:43]
But it is different in the sense that the latter violates ddau
[12:43]
In some form
[12:43]
(from perspective of many people)
[12:43]
and therefore basically disqualifies it from use
[12:43]
(just run with me for a sec)
[12:43]
So, people see `{{input val=val}}`, and their reaction is, "two-way bindings, side effects, bad"
[12:44]
so they `<input value={{val}} on-change={{action (mut val)}}>`
[12:44]
Ok so what would you say to that
[12:44]
if you were teaching someone, and they said that and then replaced the `{{input` helper with ^ that line
[12:45]
Anyone? :stuck_out_tongue:
cowboyd [12:46 PM]
At first blush, I’d actually prefer the long form, because it identifies work that you need to do.
[12:46]
`{{input val=val}}` sweeps that work under the rug
locks [12:46 PM]
I have an answer, deprecate `{{input}}` :P
samselikoff [12:47 PM]
woof. Ok maybe we have genuine disagreement here
[12:47]
> it identifies work that you need to do
could you elaborate?
cowboyd [12:47 PM]
Not sure if I disagree yet, but I think you’ve hit on a very interesting question here.
locks [12:47 PM]
I semi-agree with @cowboyd
[12:48]
another phrasing of it is "use the platform"
samselikoff [12:48 PM]
ok so, let me explain my thinking here
[12:48]
So if I was working with a beginner
[12:48]
or mentoring a team
[12:49]
and they submitted PR with ^ that change, bc they had read about ddau and wanted to use one-way data flow
[12:49]
I would say something like: one-way data flow does help us reason about our app, when data is moving all over the place
[12:49]
But here, what's the expected side effect of this input? What is hte purpose
[12:50]
`on-change` is an open door that we can configure, when we cnanot predict what should happen when an input field changes
[12:50]
But a super common use case of using `<inputs>` is to modify data
[12:50]
This is why `{{input}}` helper exists. It's common enough that it's included in Ember ot make you more productive
cowboyd [12:51 PM]
> it identifies work that you need to do
It is my experience that using actions with one-way binding scales with forms as they become more complex, two-way binding does not. So if you start with the scalable approach, you can well, scale it. Start with the dead end and you’re bound to crash into it.
abuiles [12:51 PM]
joined #topic-forms
samselikoff [12:51 PM]
When I'm reading a template, `<input value={{val}} on-change={{action (mut val)}}>` tells me I should not make assumptions about what's happening, I need to look at the value and the side effect
locks [12:52 PM]
I think that's what @cowboyd means.
samselikoff
`on-change` is an open door that we can configure, when we cnanot predict what should happen when an input field changes
Posted in #topic-formsToday at 12:50 PM
[12:52]
right, because it's explicit
samselikoff [12:52 PM]
Right but, I would counter with YAGNI
[12:52]
so say you start with `{{input value=value}}`
[12:52]
You use that for 9 fields on your form
locks [12:52 PM]
is actually serious about deprecating `{{input}}` (edited)
mmun [12:52 PM]
so what’d like to see is something like
```<input value={{val}}>
<input value={{bind val}}>
<input value={{val}} oninput={{updateValWithDebounce}}>
```
samselikoff [12:52 PM]
then you add a 10th that needs to do an autocomplete AJAX fetch
[12:53]
ok so, noobie/2-way-binding only person here would do something like
[12:53]
make an observer, trigger side effect, etc...
[12:53]
Which we all agree is the wrong approach
[12:53]
At this point, `{{input}}` is not appropriate because your input helper is no longer "just mutating" the data
[12:54]
at this point you have more complex data flow, and so you'd want to switch to `<input on-change={{action 'fetchResultsAndSet'}}>`
ryanto [12:54 PM]
@mmun i like this, {{bind val}} would be current {{input}} helper today?
locks [12:54 PM]
except people then do `{{input value=value on-change={{action 'fetchResultsAndSet'}}` and then complain that Ember sucks :X
mmun [12:55 PM]
yes, it’s just a terser form of what sam wrote above (edited)
locks [12:55 PM]
@samselikoff my problem with this is my problem with most nuance
samselikoff [12:55 PM]
(i like that api too mmun)
mmun [12:55 PM]
I would be embarrassed to ever write `<input value={{val}} oninput={{action (mut val)}}>`. I think it is fine in spirit. Just syntactically gnarly. (edited)
locks [12:55 PM]
it's that people don't do nuance
samselikoff [12:55 PM]
@mmun me too - but people do that
locks [12:56 PM]
I don't see a problem
samselikoff [12:56 PM]
@locks in my experience working with teams cargo-culting ddau will get you into just as much trouble. People need to learn to use the primtives that Ember provides
[12:56]
dhh has said similar things about rails
[12:56]
that people need to learn how to use it.
igort [12:56 PM]
joined #topic-forms
locks [12:57 PM]
@mmun that won't actually work, will it ;P
samselikoff [12:57 PM]
An app I saw, you had to open 7 templates to change something. There's so much indirection and it was completely overwhelming for the engineer working on it
mmun [12:58 PM]
that really makes me sad.
samselikoff [12:58 PM]
Forms are fundamental to web apps and simple forms should not be overwhelming. Ember has a job here and `{{input}}` is a good abstraction. I think there's plenty of room for more good abstractions
mmun [12:58 PM]
I dislike when people create multiple one-off components to split up a template (like partials)
[12:59]
but then end up passing each component many attributes
samselikoff [12:59 PM]
So I think when it comes to things like implementing charles' pull method, or drafts, etc. ddau is perfect for those details. Make those abstractions much easier to build
[12:59]
yes mmun this is exactly it
mmun [12:59 PM]
I can see why people do it. There’s a trade off.
locks [1:00 PM]
I want to remember folk that the working version is `<input value={{appName}} oninput={{action (mut appName) value="target.value"}}>`, and it's beautiful
mmun [1:00 PM]
I just prefer locality over compartmentalization
samselikoff [1:00 PM]
right - but sometimes people split up components and pass in models thinking they're "ddau"
[1:00]
when all the models are referencing the same singleton instance from teh store
[1:00]
and end up creating lots of indirection. I've seen this a lot
cowboyd [1:01 PM]
runs off to grab some lunch.
samselikoff [1:01 PM]
lol locks. It is not
mmun [1:01 PM]
I try to keep my contexts as shallow as I can. This usually involves {{yield}}ing heavily. (edited)
machty [1:01 PM]
@locks that is beautiful only so much as some other higher level abstraction/syntax decomposes into that
[1:02]
if all of Ember higher level APIs decomposed in that way i'd be a much happier person
locks [1:02 PM]
you all need to #usetheplatform
samselikoff [1:02 PM]
no. Ember is about making us productive and happy
[1:02]
Ember should use the platform, not me
mmun [1:03 PM]
I agree that nice primitives are beautiful. so is sugar
locks [1:03 PM]
we just need sugar for `{{action (mut appName) value="target.value"}}`, like @mmun suggested
mmun [1:04 PM]
y not target.checked?
[1:04]
it’s tricky
[1:04]
each component would need to describe it’s default mutating mechanism
locks [1:04 PM]
@mmun not following
[1:05]
I'm talking about `<input>`
mmun [1:05 PM]
yes
[1:05]
```<input type="text" value={{val}} oninput={{action (mut val) value="target.value"}}>
<input type="checkbox" checked={{val}} onchange={{action (mut val) value="target.checked"}}>
```
locks [1:06 PM]
we can sugar that
mmun [1:06 PM]
it’s not really possible to have a one-size-fits-all strategy because different properties trigger different events
[1:06]
but we can do it on a case-by-case basis.
locks [1:06 PM]
we get the event in the event handler
mmun [1:07 PM]
ideally when you write `checked={{bind val}}` it would ask the component… hey, what does it mean to bind to checked?
[1:07]
and we can provide a set of defaults for <input> (edited)
samselikoff [1:08 PM]
oh. that sounds really nice
ryanto [1:09 PM]
something that i think about with my forms is reusability. with `{{date-picker}}` i want DDAU because it gets used it so many difference scenarios, so side effects need to be decoupled for the component and defined by the caller with actions. but with `{{blog-post-form}}` its not really reusable. im only writing this component to update a blog post, so internally the component can make more assumptions since its side effects are focused. im ok with if `{{blog-post-form}}` is doing things internally like creating drafts, model mutations, and saves.
mmun [1:09 PM]
but if you wanted something non-default you could go back to:
```<input type="text" value={{val}} onkeydown={{action (mut val) value="target.value"}}>
```
(edited)
locks [1:09 PM]
@mmun :ok_hand:
mmun [1:10 PM]
this was literally the design of {{mut}}. it just didn’t quite end up there.
locks [1:10 PM]
seeing people extending input classes is no bueno
mmun [1:11 PM]
@locks: Do you know why we don’t deprecate {{input}}? There is a blocker to even beginning to consider it. It is event delegation. (edited)
locks [1:12 PM]
I don't but I'm sure I'll learn when I start to write the rfc ;P
[1:12]
ttm
mmun [1:12 PM]
tbh I don’t fully understand but there are several people that do.
[1:13]
I just thought you should know before you push it too hard :slightly_smiling_face: the tl;dr is that if you use `element.onclick = function() { … }` naively the way we are you lose some of the determinism that we have with today’s event system (edited)
locks [1:13 PM]
gotcha
mmun [1:13 PM]
kris, stef, maybe rob, yehuda, maybe runspired
samselikoff [1:14 PM]
you guys have taken us off the :railway_track:
[1:14]
:stuck_out_tongue:
mmun [1:14 PM]
sorry, i’m done
samselikoff [1:14 PM]
go hang out in ember-dev why dontya
mmun [1:14 PM]
and sorry @ryanto
[1:14]
https://embercommunity.slack.com/archives/topic-forms/p1484330946000260
ryanto
something that i think about with my forms is reusability. with `{{date-picker}}` i want DDAU because it gets used it so many difference scenarios, so side effects need to be decoupled for the component and defined by the caller with actions. but with `{{blog-post-form}}` its not really reusable. im only writing this component to update a blog post, so internally the component can make more assumptions since its side effects are focused. im ok with if `{{blog-post-form}}` is doing things internally Show more…
Posted in #topic-formsToday at 1:09 PM
locks [1:14 PM]
I don't know this mmun person.
runspired [1:14 PM]
I understand :stuck_out_tongue:
samselikoff [1:14 PM]
i kid :stuck_out_tongue: anyways, {{bind val}} is the same as {{input}} from my perspective
[1:14]
and it is good (edited)
[1:14]
basically it's ryans point ^
runspired [1:15 PM]
I want to RFC a new event system (to replace my existing RFC as that one was incomplete)
samselikoff [1:15 PM]
I think this is lost on lots of people who hear/learn ddau and run with it to the extreme
locks [1:16 PM]
cargo culting is weird
[1:16]
like, Ember is inherently 2wb
ryanto [1:19 PM]
i guess my argument about `{{date-picker}}` and `{{blog-post-form}}` is that when we learn `{{date-picker}}` we learn that DDAU is the right way to do things, which leads to an incorrect design of `{{blog-post-form}}`. For example when I see `{{blog-post-form on-attribute-change=(action "…") on-save=(action "…") on-reset=(action "…")}}` it makes me think DDAU has gone too far since these types of side effects should be defined inside of the form components.... since you know, they’re form related. im not sure everyone agrees with this statement though.
locks [1:20 PM]
hhmm
[1:20]
this discussion is kinda hard without more code in front of us
[1:20]
I agree that it's a code smell
[1:22]
having too many bindings is usually a warning to look at your architecture
ryanto [1:23 PM]
ok let me try to come up with an example, i would say `{{date-picker model=model}}` is bad. we dont know the models date attribute, we make too many assumptions, and this leads to pure pain. so we get to `{{date-picker date=model.date on-change=(action (mut model.date))}}`
samselikoff [1:23 PM]
yep, agree. The way i’ve heard it said is “two-way bindings aren’t bad. using two-way bindings as a message bus is bad."
locks [1:23 PM]
for future reference, assume I'm mostly taking the perspective of a newbie as I envision
samselikoff [1:24 PM]
yep
ryanto [1:24 PM]
but with `{{blog-post-form model=model}}` is fine. because blog-post-form is specific to our application, its working in our domain, we can make a ton of assumptions.
samselikoff [1:26 PM]
yes. There’s a relationship between DDAU and what you can assume about the side effects of a component or form
ryanto [1:30 PM]
i think ddau makes blog-post-form worse off, because when you have `{{blog-post-form model=model on-save=(action "savePost")}}` you now have to know about two components in order to understand this form. you need to look at `blog-post-form` component and the parent where the `savePost` action is defined. i think this indirection makes it harder to understand. so i like to question if we need the explicit action for the side effect… for `{{date-picker}}` the answer is 100% yes, but for the blog-post-form im not sure we do. (edited)
locks [1:35 PM]
@ryanto I feel like there's a bigger discussion here, wrt `on-save`
[1:36]
mainly because you're passing `model` in
[1:36]
so I'm assuming this comes from `model()`
ryanto [1:36 PM]
well lets say we didnt pass model in
locks [1:36 PM]
unlike say a self-contained search box
[1:37]
:thinking_face:
ryanto [1:37 PM]
what if we had `{{blog-post-form title=model.title on-save=(action "savePost")}}`
locks [1:37 PM]
I'm assuming save + transition inside the component?
ryanto [1:38 PM]
i would say this component is pure ddau, but poor interface since blog-post-form should know how to do both those things (get title and perform save) (edited)
[1:40]
i would say… yes save, transitions, or whatever a developer expects when you click the save button would live inside of the component. they would only move outside of the component if they needed to be configurable (in other words different use cases).
locks [1:43 PM]
hm
[1:43]
I'm not too fond of the transition inside
samselikoff [1:44 PM]
But at least you’re arguing on the margin. Main thing we want our video series to communicate is, folks should approach building forms the same way they build other pieces of their application: build it to the specific use-case first, and only abstract/expose new APIs as they are needed (YAGNI).
ryanto [1:44 PM]
sure - me too, but its not about the transition, its about expectation
samselikoff [1:45 PM]
The thing is with reusable components or addons, you want to use pure ddau, because you’re by definition building for a general use case. But a `blog-post-form` is an application feature
ryanto [1:45 PM]
if every time i save a blog post i transition to that posts route, why bother doing `{{blog-post-form model=model after-save=(transition-to "post" model)}}`
[1:47]
im trying to think of ways to phrase this argument, its the idea that theres a tradeoff between DDAU and increased api/configurability.
locks [1:48 PM]
I'm also trying to find the words for what I want to say xD
samselikoff [1:48 PM]
say “I love the {{input}} helper"
[1:48]
:stuck_out_tongue: i kid
ryanto [1:49 PM]
i think with components we can ask what their reusability is, and if its “a lot!” then ddau makes a ton of sense. so `{{date-picker}}` you want a nice api/configurability via actions and props
[1:50]
but {{edit-customer-profile-form}} isnt likely to be reused, this component isnt going to be an addon, and good luck using it outside my application. so we can sacrifice ddua for concise api, only passing in a model
locks [1:51 PM]
`blog-post-form` is both for creating and updating a blog?
samselikoff [1:51 PM]
and its not just losing ddau for no gain. Now when you make a change, you look in one place instead of everywhere
new messages
locks [1:52 PM]
I think I know were our disagreement is, if only I were going to emberconf :sob:
ryanto [1:52 PM]
locks, sure- lets say yes. in that case i think we can say since it does both create and update it should have an `after-save=(action "…")` since the after save for create would be different from update. but we only add this feature at this point, not when were creating the component (edited)
ryanto [1:54 PM]
ok i think this gets at my argument. i would say maybe, but for most forms create and update are something like `validate()` and `save()`. so it can be built into the form, not an outside action
[1:54]
and of course, if you have different create/save logic then you can make it an outside action, or different component actions, but the point is you dont do that until you need it.
[1:56]
btw im talking a lot of ideas/concepts here… i think my argument for all this comes off seeing real world ember apps that have form components that take 12 properties and 6 actions in order to not allow the component to have any side effects. often seeing these passed down 2-3 template layers too (edited)
[1:58]
the refactor we always do is turning that side effect free form into a “smart component”. this is the term we’ve been using for a component that “does it all”. often leads to easier component (from both the callers perspective and the internal component itself).
[2:00]
usually it goes something like… blog-post-form component with side effects and that component uses a bunch of side effect free addons (date pickers, etc). nice balance of reusable smaller pieces but a specific place (blog-post-form) for the developer to put application and expected side effects. rather than bubbles these all up to the route/controller. (edited)
[2:02]
ok im done :slightly_smiling_face: but would love to hear if people generally agree/disagree with this (edited)
machty [2:03 PM]
parsing
locks [2:04 PM]
@ryanto did you mean easier composition
[2:05]
what I'm hearing is that blog-post-form is your route template :joy:
[2:05]
sounds like a container component (react literature)
ryanto [2:07 PM]
im not familiar with container components, but the form components can be at any level. sometimes nested 2-3 levels deep
locks [2:08 PM]
https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0
Medium
Presentational and Container Components
You’ll find your components much easier to reuse and reason about if you divide them into two categories.
Reading time
----------------
5 min read
(180KB)
March 23rd, 2015 at 7:23 AM
[2:08]
container -> self-contained
presentational -> ddau
ryanto [2:09 PM]
exactly
[2:10]
yes- agree. so similar to a container component having access to flux actions, i think a form component should have access to `model.save()` or `model.set()`
[2:11]
and not be looked at as this violates ddau
locks [2:11 PM]
semantically there's nothing above it to get dd from and au to :P
josh.hollinshead [2:24 PM]
joined #topic-forms
ryanto [2:26 PM]
btw forms are hard :slightly_smiling_face: i feel like i steered the topic to component design/api, but theres so much more in terms of drafts+ saving strategies, client/server validations, slow internet… (edited)
samselikoff [2:29 PM]
i think I would say that ddau came about to address complex and unpredictable side effects (bindings that trigger multiple things simultaneously). but when side effects are well-understood and predictable (like they tend to be for many domain-specific application components) some aspects of ddau become premature abstraction
[2:30]
and in those situations 2wb and Ember primitives like {{input}} should be embraced, because they are familiar to ember devs and keep you productive
machty [2:59 PM]
man i've been so backed up w prod issues today
[2:59]
i blame forms
[2:59]
but i promise to chime in shortly
kyle [3:37 PM]
joined #topic-forms
machty [3:46 PM]
more important than strict DDAU is clear ownership of data that doesn't sneakily / subtly / destructively bleed out into the rest of the app
machty [3:56 PM]
i think i just echoed @samselikoff
kyle [4:22 PM]
So why {{blog-post-form}} and not reusable form component(s) that yield out? This works pretty well for us - we keep as much as we can at route template level.
samselikoff [4:24 PM]
@machty exactly. proper separation of concerns. How easy is it to change your forms and components that deal with your primary application data? If you add a field to a model, do you have ot change components and templates in 7 places?
[4:25]
@kyle I would say if you have a route that is basically just a form, then yes you could start by not even using a form component, and doing everything in the route/controller/template. After all, those three objects already exist, and if thats their only job, start with that. If you don’t need a separate component, don’t make it. Yagni
[4:26]
But what if you’re making an app like Trello? Homepage route has quite a lot going on. So you’ll probably end making a {{trello-card-form}}, an {{add-members-form}}, a {{side-bar}} component and so on
samselikoff [4:36 PM]
Also what I’ve found working with teams is, its really nice to establish some conventions. So if every app you have, every time you have a form where your editing data, its always a `{{some-model-name-form}}`, the `tagName` is always form, and component does validations and saving, and delegates to the outer template only when its behavior needs to be customized
[4:37]
Establishing these patterns is really nice
[4:37]
And I think a component like that, most ember developers could jump in and understand it quite easily. The form’s `<input type="submit">` calls a local action that performs `model.save()`. Bread-and-butter stuff
kyle [4:46 PM]
@samselikoff yeah if you have a complex route with multiple forms or a single form multiple times. in these situations we have wrapper form components that repurpose our generic form component, but theyre pretty lightweight
[4:47]
not an overly common situation for us though, most of the time we’re aiming to architect ui for single form per page and question hard if the ui really needs mulitple forms
[4:48]
cases like trello dashboard are defo a yes
samselikoff [4:48 PM]
any chance I could see an example of a dedicated form page? Curious to gather examples as we make this video series
[4:48]
trello, yah. (edited)
[4:48]
(example code)
kyle [4:49 PM]
sure, will try grab something for you tomorrow if thats ok
ryanto [4:49 PM]
form component that wraps a generic form i think is good. it gives you a domain form component that can control side effects (edited)
[4:50]
like using `{{form-for}}` addon inside of `{{blog-post-form}}`
kyle [4:50 PM]
hang on - might have a snippet
[4:51]
```{{#ui-form as |form|}}
{{#form.title}}
Edit field
{{/form.title}}
{{#form.fieldset}}
{{#form.dropdown
options=contentFields
selected=changeset.contentField
onchange=(action (mut changeset.contentField))
placeholder="Please select"
as |contentField|
}}
{{contentField.name}}
{{/form.dropdown}}
{{#form.field}}
{{form.text-field
id="name-field"
placeholder="Name"
label="Name"
value=changeset.name
required=true
}}
{{/form.field}}
{{/form.fieldset}}
{{#form.footer}}
{{ui-button
label="Confirm changes"
theme="good"
onclick=(route-action "confirm")
}}
{{ui-button
label="Delete"
theme="danger"
onclick=(route-action "delete")
}}
{{ui-button
label="Cancel"
theme="simple"
onclick=(route-action "cancel")
}}
{{/form.footer}}
{{/ui-form}}```
(edited)
ryanto [4:53 PM]
is that a route template or component template?
kyle [4:53 PM]
route template
cowboyd [4:55 PM]
Have we talked about how all forms have form-level concerns? like whether it is submittable, whether it is submitting, whether its dirty, validation state and how all those play together every time?
[4:55]
also, diffs between current edits and the source object?
[4:55]
Don’t want to derail, but we’ve done some analysis on this and are trying to capture it in a pure js library https://github.com/cowboyd/form-x
[4:56]
I’d be curious to get some feedback. I think it’s beyond the scope of where the conversation started
ryanto [4:57 PM]
kyle makes sense, and i think if ever needed you can turn that into a form component, but as is thats very readable. i think our discussion is about what does it look like if that does become its own component.
cowboyd [4:57 PM]
but wanted to mention it at some point.
ryanto [4:57 PM]
cowboyd we havent, im of the opinion that the form should know how to do all those things 99% of the time.
cowboyd [4:58 PM]
Yeah, thats kinda the conclusion we’ve come to, and tried to map out, just what those things are.
[4:58]
because they seem intertwined.
kyle [4:58 PM]
@ryanto yeah in places where we need a reusable form, we repackage inside a dedicated component and then ddau (edited)
kyle [5:06 PM]
form-x looks really interesting
cowboyd [5:09 PM]
@kyle lemme know what you think. We’re just trying to capture all form concerns in a single place.
kyle [5:10 PM]
does it currently handle dirty values? (edited)
[5:11]
ah yes - see it in the form object
cowboyd [5:13 PM]
it will, yes. We haven’t actually written the Form class in practice though
kyle [5:14 PM]
ok cool, looks great
[5:15]
plans to handle relationship dirtying?
cowboyd [5:20 PM]
What is relationship dirtying? Like when a related object changes?
machty [5:22 PM]
hey, potential de-railment, again, but I wanted to share a new pattern i've discovered that relates to building configurable/composable APIs, that I think may very well likely impact our thinking about the ideal form API: https://ember-twiddle.com/d51ce8adf3870c771a1bbe0b12c0776f?numColumns=2&openFiles=templates.application.hbs
....
runspired [3:22 AM]
I have been sold on same file
[3:22]
But I'm less convinced they should be unified
[3:22]
I am however in favor of more powerful templates
[3:22]
I personally have started viewing component.js as a reducer / store
[3:23]
And the template as the component
[3:23]
Cc @cowboyd @machty
swastik [8:45 AM]
joined #topic-forms
machty [9:57 AM]
@runspired would be curious for what that looks like
[9:57]
can't tell if i already write code that way or what
cowboyd [11:49 AM]
That’s very similar to how I’ve come to think about it. Whether it’s using a component or a helper to contain state.
[11:51]
There are still cases where the cleanest way to compose things would be the ability to perform “reductions” inside the template.
[11:51]
and to do that, you need to be able to define lambda abstractions inside hbs (I think)
[11:52]
Let me see if I can come up with an example
machty [11:52 AM]
we have lambda abstractions but only with template blocks of html
[11:53]
you can't do `{{#each (map items (|i| i.wat)) as |wat|}}...`
cowboyd [11:53 AM]
right, so here’s where we ran up agains this limitation
[11:54]
and you hit the nail on the head btw
[11:56]
I think you may have even seen this. We had a file upload component that was fantastic. It kept all the upload state and then presented the current state to the template via a yielded parameter. `upload.progressPercentage`, `upload.isComplete`, etc… That was awesome..... until we wanted to track mulitple uploads concurrently.
[11:57]
because we need to reduce all of the uploads into a single aggregate state. i.e. reduce
[11:58]
a pretty simple reduction in any language, right? in js it would be like `uploads.any(upload => upload.isPending)`
[11:58]
I guess that would be `some`
machty [12:01 PM]
so you had something that presumably started off as an object/task on the component and you had to split that out into separate objects (edited)
[12:02]
was this the example where yall had these objects that were really just dressed up tasks?
cowboyd [12:02 PM]
p much.
[12:03]
would really like o be able to say: `{{any uploads (fn [u] u.isPending}}`
machty [12:07 PM]
yeah
[12:07]
you'd have to delegate to a helper
cowboyd [12:07 PM]
or an action I guess
machty [12:08 PM]
`{{any uploads (is 'isPending'))}}` (edited)
[12:08]
`{{any uploads (is 'someMethod' arg1 arg2))}}` (edited)
[12:09]
(this last one extends it so that someMethod could be a property or some bool method that accepts multiple args)
[12:10]
(or the method returns a Reference that essentially tells glimmer that it'll handle invalidating over time rather than letting the helper API decide to recompute as inputs change)
cowboyd [12:11 PM]
Yeah, those are all pretty good solutions, and you could even write a syntax transform so that you could use symbols instead of strings.
[12:12]
although usually the refactoring workflow is first `{{any uploads (fn [u] u.isPending}}`, then `{{any uploads (is pending)}}` so not having the intermediary available trips up your thinking
[12:12]
The other case is where you want to decorate extended values via a map.
[12:13]
We actually wanted to do that as well, and tripped up. you alluded to it with your map.
[12:13]
`{{#each (map files (|f| file-upload f)) as |upload|}}`
[12:15]
`(|f|)` love that as a syntax for `λ`
machty [12:15 PM]
yeah it's not bad...
[12:16]
huh
[12:17]
yeah, kinda really like it too
cowboyd [12:17 PM]
You just come up with that in the moment?
machty [12:17 PM]
lol yeah i didn't think it was anything special
cowboyd [12:18 PM]
well, fwiw, I give it a +1 :slightly_smiling_face:
[12:19]
Actually I got that wrong: it should be `{{#each (map files (|f| (file-upload f))) as |upload|}}` since `file-upload` is a function/helper
[12:20]
Is there any way to do that today in ember with hackery / syntax tranforms?
machty [12:27 PM]
i dunno
[12:28]
maybe ask #dev-glimmer
[12:28]
would be curious to see what all you could do with it
cowboyd [12:35 PM]
Probably a good idea.
[12:35]
(for a weekday)
machty [12:35 PM]
is that how you do for loops in clojure
cowboyd [12:37 PM]
like how?
machty [12:37 PM]
i was making a bad joke: `(for a weekday)`
cowboyd [12:38 PM]
hahahahhaha.
[12:39]
you actually had me trying to re-write that `map` up there as a `for` comprehension
[12:40]
Someone needs to rename this channel #off-topic-forms :slightly_smiling_face:
machty [12:41 PM]
let's bring it back
mmun [1:04 PM]
yeah i want lambdas too
[1:04]
people will flip tables, but i want to try it
cowboyd [1:05 PM]
Well @machty did all the hard work by coming up with a syntax.
mmun [1:05 PM]
every time i have to make a js file for a component i feel i have lost
cowboyd [1:05 PM]
*yes*
mmun [1:05 PM]
(not really true, but kinda true)
machty [1:05 PM]
ember has too much "do i really have to" API
mmun [1:06 PM]
obviously there are imperative things that are just easier to do with js (i.e. tasks)
[1:06]
i also want block-lambdas
cowboyd [1:06 PM]
do tell.
mmun [1:07 PM]
basically lambdas whose result is a handlebars block
[1:07]
so that you can do `{{each items &block}}`
[1:07]
analogous to `items.each &block`
[1:08]
you can think of it as a regular lambda that generates DOM (edited)
cowboyd [1:08 PM]
How would captured blocks specefiy their parameters?
[1:09]
in theexplicit form `{{#each items as |item|}}` `item` is what’s bound.
mmun [1:09 PM]
sure
machty [1:09 PM]
(possibly syntax to avoid introducing another sigil `{{each items as block}}`) (edited)
mmun [1:09 PM]
```{{#let-block greeting as |person|}} {{person.name}} {{/let-block}}
{{each items &greeting}}
{{each items &greeting}}
```
(edited)
[1:10]
^ not a good example for motivation. more of a tech demo.
[1:11]
the motivation would be to support drag-and-drop between two lists and not needing to rerender the item when it jumps from one list to the other
[1:11]
because we can statically determine that are rendered by the same block
machty [1:12 PM]
you could guarantee that by enforcing that all draggable things are defined in separate templates/components right?
mmun [1:13 PM]
yeah
machty [1:13 PM]
but i agree that i want that syntax as well
[1:13]
i see it as an alternative to the block slot syntax people want so bad
mmun [1:13 PM]
```{{#each items as |person|}} {{greeter person=person}} {{/each}}
{{#each items as |person|}} {{greeter person=person}} {{/each}}
```
[1:13]
in theory we could see that those two blocks are the same
[1:14]
but feels hacky
cowboyd [1:14 PM]
I like it. Would also be nice to have a module system to share blocks.
mmun [1:14 PM]
@machty: yes it absolutely is
machty [1:14 PM]
```{{#let-block header as |person|}} {{person.name}} {{/let-block}}
{{#let-block footer as |person|}} {{person.name}} {{/let-block}}
{{#let-block wat as |person|}} {{person.name}} {{/let-block}}
{{complex-component header=header footer=footer wat=wat}}
```
mmun [1:14 PM]
the problem, as i see it, is that it pulls the block away from where it is used
cowboyd [1:14 PM]
`{{import greeter="blocks/greeter"}}`
mmun [1:14 PM]
which kinda sucks
machty [1:15 PM]
i've given up on block slot syntax, which is both likely unsolvable and ultimately a subset of having local anonymous blocks
mmun [1:15 PM]
yeah, that’s the evolution i was getting at
[1:15]
to make them completely anoynmous
[1:16]
```{{complex-component
header=(|person| {{person.name}})
footer=(|person| {{person.name}})
wat=(|person| {{person.name}})
}}
```
[1:16]
:bike: :derelict_house_building:
machty [1:17 PM]
is that you riding your bike home away from this convo, or bikeshedding
mmun [1:17 PM]
derelict bike shed
[1:17]
i just mean that the syntax ^^ probably sucks.
machty [1:20 PM]
i want to avoid that bikeshed. can't imagine the solution along that path not looking like php (edited)
[1:21]
let's start with the assumption that you define the blocks at raw toplevel html level
mmun [1:21 PM]
fwiw, yehuda suggested it to me
[1:21]
named blocks are still useful as well, so seems ok to design them first (edited)
machty [1:22 PM]
is there a case where named blocks express something that can't be expressed w local anon blocks?
mmun [1:22 PM]
no
[1:22]
sry, got that reversed
[1:23]
named blocks allow you to reuse the same block and statically know that
[1:23]
that’s the only difference
machty [1:23 PM]
https://thefeedbackloop.xyz/stroustrups-rule-and-layering-over-time/
The Feedback Loop
Stroustrup's Rule and Layering Over Time
Programming language experts like to claim that syntax doesn't matter, that semantics is all that counts. Don't believe them! They're overrotating on a common, pre-rigorous misunderstanding of language design as superficially aesthetic. The study of semantics does provide deep insights into the mechanics of languages—but the mechanism is not
Written by
----------------
Dave Herman
Dec 16th at 2:53 AM
[1:23]
so do anonymous local blocks
mmun [1:24 PM]
yes, technically you’re right
[1:24]
you can do {{let blah=(anon block)}} (edited)
[1:25]
and arguably it would suck to have two ways to create blocks bound to variables
[1:25]
i.e. ` {{let blah=(anon block)}}` and `{{#let-block}}`
[1:26]
@cowboyd: have you ever felt this desire for first class blocks?
[1:27]
it becomes particularly apparent when you try to customize e.g. `power-select`
locks [1:27 PM]
Begging the question, sir :troll:
mmun [1:27 PM]
you are forced to pass in (component …) objects
cowboyd [1:27 PM]
Right, which means forcing a context switch.
mmun [1:27 PM]
i just hate having to create an extra tiny file (edited)
[1:28]
(the context switch!)
[1:28]
and also giving it a global name bugs me, though the module reform stuff has solutions for that particular issue (edited)
cowboyd [1:28 PM]
It also means it's harder for non-you to parse in 6 months (edited)
[1:28]
module reform?
mmun [1:29 PM]
dgeb’s big rfc
machty [1:29 PM]
good luck avoiding the global name and instead finding a syntax for inline that 1) makes sense 2) avoids ugly `{{ }}` stacking
locks [1:29 PM]
Module unification
[1:29]
You only have local and global lookup
mmun [1:29 PM]
@machty is that a genuine good luck or do you think it is a non-starter
[1:30]
:stuck_out_tongue:
machty [1:30 PM]
non-starter (edited)
[1:30]
sorry, that all came off super sarcastic.
[1:31]
i'm so sure it'll not work that i'm wary of all the bike-shedding that'd distract us away from the base primitives that would work great today
mmun [1:31 PM]
i don’t fully understand your position: what do you think is the best avenue to explore?
locks [1:31 PM]
I feel like this channel is what #topic-architecture should have been
[1:31]
Loving the discussions
machty [1:32 PM]
@locks yeah me too; it's a very nuanced kind of conversation that i've only been able to individually have with certain people and certain use cases. (edited)
cowboyd [1:32 PM]
btw, @mmun in clojure, `(defn name [x y])` is literally a macro for `(def name (fn [x y]))`, so I think having two forms, one expressed via the other is preferable.
[1:32]
rather than undesirable
mmun [1:32 PM]
@cowboyd: :+1: i appreciate your insights (edited)
locks [1:33 PM]
I hope you know I think this is vital, even if my answers are sometimes short
[1:33]
@cowboyd why not lisp?
mmun [1:34 PM]
@machty: is something #let-block-ish acceptable to you?
machty [1:34 PM]
```Primitive 1: define a local block and give it a local name.
(syntax open to bike-shedding)
{{#let-block foo as |person|}} {{person.name}} {{/let-block}}
Primitive 2: use that block anywhere you'd use `as |x|`
(syntax open to bike-shedding)
{{#each people as foo}}
In my mind, there is no third primitive.
We shouldn't add block slot syntax (for now at least).
Any component that desires block syntax can use the above primitives
to accept blocks as attrs. Note that proposed block syntax makes
it hard/impossible to use the same block in multiple places, whereas
the above primitives make it trivial
{{sample-component
slotName1=foo
slotName2=foo
slotName3=foo}}
```
locks [1:34 PM]
I'm more asking if you've tried to wrangle cljs
machty [1:34 PM]
@mmun ^ answers the best avenue question
cowboyd [1:35 PM]
@locks cljs is a lot of fun.
[1:35]
But it doesn’t have anything near the maturity or scope of Ember
mmun [1:35 PM]
yeah, I’m not enthusiastic about slots.
locks [1:36 PM]
I mean for templating
[1:36]
Like emblem, I guess
mmun [1:36 PM]
if you use slots you start to get into weird situations
machty [1:36 PM]
@mmun it sounds like you still want some third thing like
```{{complex-component
header=(|person| {{person.name}})
footer=(|person| {{person.name}})
wat=(|person| {{person.name}})
}}
```
mmun [1:36 PM]
like… what if you want to define multiple columns for a table… you’d want an array of column blocks
machty [1:37 PM]
but that is reducible to the final block slot replacement example i gave
mmun [1:37 PM]
sure, I see it the other way around haha
[1:38]
feels awkward that the “reduction” involves introducing a hygenic name in the scope (edited)
[1:39]
but, ultimately, they’re almost exactly the same thing to me
[1:39]
if you’re on board with let-block, i can get behind that.
[1:40]
there’s no argument: the lambda syntax is a bikeshedding black hole
cowboyd [1:41 PM]
Another issue you might have that would want to drive you towards
```{{complex-component
header=(|person| {{person.name}})
footer=(|person| {{person.name}})
wat=(|person| {{person.name}})
}}
```
[1:41]
is that you want to preserve the “high-level” conceptual context
[1:41]
wich is that I’m rendering the `complex-component`
[1:42]
if you see 10 lines a bunch of `let-block` statements before you actually get to the business of rendering `complex-component`
[1:42]
then it can feel like “why?” untill there’s an “oooooooh"
[1:42]
One way that might make it feel better is to allow putting the named let-blocks _after_ where they are used.
[1:43]
This is one of my favorite things about haskell
locks [1:43 PM]
That sounds super bad
machty [1:43 PM]
```{{complex-component
header=(|person| hi i am raw dom text fragment {{person.name}} or am
I misunderstanding the proposed <span>syntax</span>.
Commence the infinite bikeshed.
) }}
```
cowboyd [1:45 PM]
```{{complex-component header=personHeader}}
{{#where personHeader as |person|}} {{person.name}} {{/where}}
```
mmun [1:46 PM]
@machty: it works for JSX
cowboyd [1:46 PM]
Still relies on names to wire them together, but perhaps addresses some of the “separation” you feel.
[1:46]
(I feel that too)
mmun [1:46 PM]
there’s gotta be _some_ way to execute it in hbs
[1:46]
but if you strongly feel it is a waste of time (like a distraction) i’m happy to punt (edited)
machty [1:46 PM]
it works for JSX because everything is assumed to be wrapped in a component
cowboyd [1:47 PM]
I agree that it feels like a infinite :black_circle:, but to leave it unsolved also feels like admitting a fundamental deficiency
machty [1:47 PM]
this is why i posted the Feedback Loop article on the Stroustrup whatever
[1:47]
```{{#let-block sharedHeader as |person|}} {{person.name}} {{/let-block}}
{{complex-component
header=sharedHeader}}
{{complex-component
header=sharedHeader}}
{{complex-component
header=sharedHeader}}
```
[1:48]
^ we _know_ we want to support this
[1:48]
sharing an anon block between multiple complex-components
[1:48]
we should absolutely release this feature
mmun [1:48 PM]
yeah. cowbody convinced me with his clojure analogy
machty [1:48 PM]
and paralleledly/after the fact discuss an inline approach
[1:48]
i'm happy to hoist `let-block` defs so that order doesn't matter
mmun [1:50 PM]
i’d prefer not. less places to look
machty [1:50 PM]
lol "cowbody"
cowboyd [1:51 PM]
I know I haven’t worked out in months, but that’s pretty harsh man (edited)
machty [1:53 PM]
what's the syntax for yielding to a passed in block
[1:53]
like if complex-component wants to render header (and render a default if none specified)
mmun [1:54 PM]
today it is {{yield to=blah}}
[1:54]
where `blah=someNamedBlock` in the component invocation
[1:54]
glimmer more or less supports this internally. it’s just missing the let-block part to stash the block. but "block references” are a thing already. (edited)
cowboyd [1:54 PM]
you want something more like `{{yield &header}}`? (edited)
runspired [1:54 PM]
@locks we had these sorts of convos in #topic-architecture back in the day
locks [1:55 PM]
yeah
machty [1:55 PM]
maybe it's `{{yield a b c as namedBlock}}`
cowboyd [1:56 PM]
ah right that would be more principle of least suprisy.
machty [1:56 PM]
```{{#yield a0 b1 c2 as |a b c|}}
{{a}} {{b}} {{c}}
{{/yield}}
```
runspired [1:56 PM]
have you looked at Vue’s slots?
machty [1:56 PM]
naw, link?
runspired [1:57 PM]
https://vuejs.org/v2/guide/components.html#Content-Distribution-with-Slots
vuejs.org
Components — Vue.js
Vue.js - Intuitive, Fast and Composable MVVM for building interactive interfaces.
mmun [1:57 PM]
i’m not convinced by `as`. feels more like a `to`? e.g. you yield to oncoming traffic
runspired [1:57 PM]
people are using them for higher order components in Vue
machty [1:58 PM]
@mmun seems fine, i'm just aiming for minimal syntax introduction and conceptual consistency
mmun [1:58 PM]
{{yield to=‘inverse’}} works today
[1:59]
{{yield to=foo}} seemed the most natural to me
runspired [1:59 PM]
I’d love to reboot my named blocks proposal
[2:00]
I bikeshedded that with so many people but lost interest right when it started getting good :disappointed:
machty [2:01 PM]
@runspired i'd be happy to throw that around but only after this lands https://embercommunity.slack.com/archives/topic-forms/p1484419674000712
machty
```{{#let-block sharedHeader as |person|}} {{person.name}} {{/let-block}}
{{complex-component
header=sharedHeader}}
{{complex-component```
Show more…
Posted in #topic-formsToday at 1:47 PM
[2:01]
because that feature/functionality should exist regardless of a nicer syntax specific to single use named block slots
runspired [2:01 PM]
c
machty [2:02 PM]
so would everyone here :+1: an rfc for ^
[2:03]
(does one already exist that specifically requests just this?)
mmun [2:03 PM]
no one has approached it this way
[2:04]
there is one or two dynamic block capture solutions which i disagree with strongly
[2:04]
and one static named block strategy by chris, i think?
cowboyd [2:20 PM]
I think that would make a great start, and is limited enough in scope that it stands a chance.
ryanto [2:31 PM]
late to convo, but we have an app that needs to pass blocks around and our solution is so hacky. capturing blocks would be nice (edited)
[2:32]
what were using https://github.com/ryanto/ember-content-for
machty [3:41 PM]
i can haz RFC https://github.com/emberjs/rfcs/pull/199
mmun [3:45 PM]
nice
[3:46]
I’m looking through the RFCs. There’s an RFC there that I don't remember writing _at all_.
machty [3:46 PM]
hahaha
mmun [3:47 PM]
https://github.com/emberjs/rfcs/pull/43
https://github.com/emberjs/rfcs/pull/72
https://github.com/emberjs/rfcs/pull/193
[3:47]
^ those are 3 the block ones
machty [3:49 PM]
interesting
[3:49]
https://github.com/emberjs/rfcs/pull/43#issuecomment-109802499
[3:49]
nvm misread it
mmun [3:49 PM]
i’m pretty strongly against the rails style dynamic named yields (edited)
machty [3:51 PM]
can you link to what you mean
[3:51]
oh like cross-template?
ryanto [3:51 PM]
any reason why you dont like the rails capture/content_for?
mmun [3:52 PM]
there’s lots
[3:53]
the main one is that it just doesn’t work without weird hacks
locks [3:53 PM]
Same reason to discourage named outlets?
mmun [3:53 PM]
yes, but its worse than that
[3:53]
https://www.npmjs.com/package/ember-block-slots
npm
ember-block-slots
Support for targeted yield slots within a component block
ryanto [3:53 PM]
oh you mean in ember’s current state? yes totally strange hacks, but could this be fixed in a future state?
mmun [3:54 PM]
https://www.npmjs.com/package/ember-block-slots#usage (edited)
[3:54]
why do you need that first `{{yield}}`?
[3:54]
it is to execute side-effects
ryanto [3:55 PM]
its a hack, you need to capture the callers handlebars
mmun [3:55 PM]
rails strategy is fundamentally about side-effects
[3:55]
you leave a hole and fill it later
ryanto [3:55 PM]
yup
mmun [3:56 PM]
the static solution has no side-effects
ryanto [3:56 PM]
basically what i want is something like https://github.com/ef4/ember-elsewhere that doesnt need `send=(component)`, but can instead use block
[3:56]
i need to read about static solution
mmun [3:56 PM]
that solves a different problem
[3:57]
and is totally valid
ryanto [3:57 PM]
yes
mmun [3:57 PM]
e.g. to populate a sidebar
[3:57]
but if you don’t need side-effects you should avoid them
[3:57]
in the ember-elsewhere case, it’s hard to do it without side-effects
[3:58]
you’d need a declarative set of rules to determine what to render in the sidebar
[3:58]
and it would be pretty brutal
[3:59]
a good analogy is… in ruby there are both blocks and procs (edited)
[3:59]
both are useful
[4:00]
(technically there’s only procs, but :stuck_out_tongue: :stuck_out_tongue: ) (edited)
ryanto [4:00 PM]
similar to ruby, id like to be able to capture a block
cowboyd [4:00 PM]
there’s also lambdas, right?
mmun [4:00 PM]
yes, but they’re basically procs
cowboyd [4:01 PM]
except for return context
mmun [4:01 PM]
what i mean is that blocks, procs and lambdas are all represented as procs in the ruby vm code
cowboyd [4:01 PM]
gotcha.
mmun [4:01 PM]
but block are optimized to avoid allocating a proc unnecessarily
[4:03]
```def do_something_later
set_timeout 1000, do
puts "lol"
return
end
end
```
[4:03]
^^ doesn’t make sense. you can’t hold onto a block and execute it later. blocks are for immediately invoked stuff
[4:03]
that’s the example i return to when thinking about procs vs blocks
machty [4:04 PM]
hmm
[4:04]
i mean, you could just `sleep` in `set_timeout`...
mmun [4:04 PM]
yeah that’d work
[4:04]
because you haven’t left `do_something_later` (edited)
cowboyd [4:05 PM]
Right, the return statement will raise a `LocalJmpError`
[4:05]
oh, I see, the `,` is deliberate.
machty [4:06 PM]
@hudabot describe TCP
mmun [4:06 PM]
```def do_something_later
set_timeout 1000, proc {
puts "lol"
return
}
end
```
[4:06]
the return there is pretty pointless
[4:06]
:stuck_out_tongue:
cowboyd [4:06 PM]
it will raise a `LocalJmpError` I think.
mmun [4:07 PM]
hm, i would expect to to be the same as setTimeout(1000, function() { return })
ryanto [4:07 PM]
ya localjumperror
[4:07]
iirc
mmun [4:07 PM]
anyways, sorry for my metaphysical divergence
cowboyd [4:07 PM]
```def do_something_later
set_timeout 1000, lambda {
puts "lol"
return
}
end
```
will create a new call context.
mmun [4:08 PM]
the point is that i think both static blocks (machty’s rfc) and runtime hole-filling (ember-elsewhere) have their place (edited)
[4:08]
and just because you can sorta do the first with the latter doesn’t make it right :stuck_out_tongue:
cowboyd [4:09 PM]
So we have an RFC for `let-block`
[4:09]
is there one for `let`?
mmun [4:10 PM]
no, i keep slacking
[4:10]
:slack:
ryanto [4:10 PM]
agree re static, makes sense
mmun [4:15 PM]
btw, what i meant by “everything is a proc…” is that if you write
`def my_each(items, &block); puts block.class; end` it prints Proc
ryanto [4:16 PM]
yes because & is to_proc
mmun [4:16 PM]
not in the args list
ryanto [4:16 PM]
no? ah
mmun [4:16 PM]
well, i mean. it’s just syntax. you can think of it that way if you want
[4:17]
but the ruby vm will optimize the block (i.e. not allocate a proc/closure) if you don’t touch any of its Procy parts
ryanto [4:17 PM]
gotcha
cowboyd [4:17 PM]
Right, the moment you bind a block it becomes a proc.
mmun [4:18 PM]
these days you have to do more than just bind it
cowboyd [4:18 PM]
but if you never actually try to capture a reference to it, it doesn’t pay the overhead, is that what you’re saying?
mmun [4:18 PM]
`def my_each(items, &block); yield block; end` should be perf equivlanet to
`def my_each(items); yield; end`
[4:18]
(sorry if i butchered the syntax, i dont write much clever ruby code :P)
ryanto [4:19 PM]
block.call (?), but yes agree (edited)
samselikoff [4:19 PM]
Can someone explain let-block vs named yields, I've always thought named yields are friendly for beginners and solve a very real problem
[4:19]
Is it just that let-block accomplishes the same thing, and more?
mmun [4:19 PM]
what are named yields? (edited)
samselikoff [4:20 PM]
I haven't looked at RFC but slots or whatever?
ryanto [4:20 PM]
btw mmun, when i see let-block, block-slots, ember-elsewhere… i see them as the same problem “capture a block and use it some where in the future”, is my thinking right?
mmun [4:20 PM]
they seem like two sides of the same coin
samselikoff [4:20 PM]
Rails view layer
machty [4:20 PM]
@samselikoff you understand correctly
mmun [4:20 PM]
you bind a block to a name with let-block -> you yield to that name (edited)
samselikoff [4:20 PM]
I like rails view layer, I think it is a good easy to use abstraction that many rails deva understand use well?
[4:21]
I also agree with Ryan these seem like they share similar root problem
mmun [4:22 PM]
you can do that with ember-elsewhere
[4:22]
it doesn’t address how you e.g. customize power-select
samselikoff [4:22 PM]
But core ember
[4:22]
I need to see that
[4:22]
Why it dpesnt
machty [4:24 PM]
@samselikoff the RFC isn't too long and provides more context
cowboyd [7:54 PM]
One `let` rfc deserves another :slightly_smiling_face: https://github.com/emberjs/rfcs/pull/200
mmun [7:58 PM]
:clap:
locks [8:01 PM]
@cowboyd I have to say I'm firmly against inline let
cowboyd [8:04 PM]
I assume there are reasons?
mmun [8:05 PM]
i’m firmly for it
[8:06]
we don’t have many tools to combat rightward drift in HTML
[8:06]
so I’d like to take advantage of the ones I can
locks [8:07 PM]
/shrug Don't indent with curly blocks (edited)
cowboyd [8:07 PM]
@locks I came around to it. I was in the block form camp at first, but after using it a lot, it adds clarity for the reasons @mmun says.
locks [8:07 PM]
I think it'll be easy too confusing
[8:07]
Lol editing slack actions
mmun [8:08 PM]
so there’s lots of pieces in play here, and I definitely want to hear your side of it @locks
locks [8:08 PM]
I'm getting home, I can try to words better
locks [8:29 PM]
how can I see markdown without it being rendered?
[8:29]
I don't know how to leave inline comments
cowboyd [8:30 PM]
can you do that in the changes section of the PR?
locks [8:31 PM]
@cowboyd another honest question, why not define your layouts in the component's definition?
[8:31]
toran does
[8:31]
hm
cowboyd [8:33 PM]
Because I want to have my handlebars and eat it too
[8:33]
(My turn to be on mobile)
[8:35]
That's certainly one approach, and it does improve the proximity problem somewhat.
locks [8:36 PM]
right, I was specifically talking about that
[8:36]
I don't think we have good ergonomics for that currently
[8:36]
I sort of like web component's approach
[8:37]
this has been generally discussed in the module unification rfc
cowboyd [8:37 PM]
But only somewhat. Because you've still got two separate parse trees. You can see where values are coming from but they aren't transparently available.
[8:37]
Like they are with JSX
locks [8:37 PM]
yes, it wouldn't be JSX
[8:38]
just single-file components, WC/polymer/vue style
[8:38]
(they're popular)
[8:39]
sorry for being all over the place, lots of things to consider at once and I'm still getting used to thinking that big xD
cowboyd [8:40 PM]
but we can have the power of JSX by increasing the power of our expression language
locks [8:41 PM]
I mean
[8:41]
with let, let-block, marten's import thing
[8:42]
I guess what I'm saying is I'd come at it from the JavaScript side myself
[8:42]
aka JSX
cowboyd [8:44 PM]
Why not just JSX then?
locks [8:45 PM]
indeed
cowboyd [8:45 PM]
I think there is an awesome opportunity here because JavaScript is just not that expressive
locks [8:46 PM]
you should be able to more easily do it with glimmer2
[8:46]
so, I was thinking
[8:46]
clj doesn't have inline let
[8:46]
only block let
cowboyd [8:47 PM]
That's true although you could write A macro for it :smile_cat:
locks [8:47 PM]
yes! handlebars macros!
[8:47]
(plot twist, we already have them :troll: )
cowboyd [8:48 PM]
Making them more accessible would be dope
[8:49]
Also JavaScript does have inline let :)
[8:49]
:stuck_out_tongue:
[8:50]
It las block let in the form of an IIFE
locks [8:51 PM]
> Many lanugages
[8:51]
JS isn't declarative
machty [8:52 PM]
i don't think inline let is non-declarative
[8:52]
an example of a violation would be actually altering the context halfway through
[8:53]
inline let is just a syntactically reasonably way to _establish_ the context
[8:55]
> with let, let-block, marten's import thing
[8:55]
not sure what marten's import thing is but `import` is another good example where the scope is established rather than mutated by a declaration/assignment
locks [8:56 PM]
I'm not quite following what you mean
machty [8:56 PM]
it sounds like you're :-1:ing certain features as non-declarative
[8:56]
(which is good)
[8:57]
i just don't think inline let is an example of such a thing
locks [8:57 PM]
I don't grok the "it establishes the context"
[8:57]
because I'm thinking there's no context switch
[8:57]
like olden each/with
[8:58]
can't find it, but @martndemus has a thing for explicitly importing components in template files
machty [8:59 PM]
i don't know what context switch you're referring to
locks [9:00 PM]
hm, let's go from the top, what does establishing a context mean?
cowboyd [9:00 PM]
> can't find it, but @martndemus has a thing for explicitly importing components in template files
I like this idea
locks [9:00 PM]
see.
[9:00]
:joy:
[9:01]
why, and do you know where it is because I can't rmemeber
[9:01]
I thought it was an RFC
machty [9:01 PM]
this has also been an idea proposed at core f2fs
cowboyd [9:01 PM]
It’s a good idea, though I’ve never seen it.
machty [9:02 PM]
@locks by establishing context i mean clearly establishing what all the known bindings are: block params + anything else that is known before glimmer will try and lock up a reference on the context
cowboyd [9:02 PM]
Also, worth noting that cljs _does_ do inline stuff that effects subsequent scope where it makes sense (just doesn’t do it with `let`) Like the `ns` macro.
locks [9:02 PM]
github search is useless
machty [9:02 PM]
and i think a minor adjustment to that story is block params + any `let` statements
locks [9:03 PM]
the `ns` macro is the most baffling aspect of clj
[9:03]
I could grok macros and whatnot, but I always had to go figure out namespaces
[9:03]
so we need to be careful
cowboyd [9:03 PM]
it serves the same function as `import` and `export` in javascript
[9:04]
do you object to the way it works or the fact that it effects the scope of the entire file, even though it appears to be limited to the top?
locks [9:04 PM]
mostly the syntax/semantics
cowboyd [9:05 PM]
but can you see why they might want to optimize for indentation
```(ns foo)
(def my-var 5)
```
vs
```(ns foo
(def my-var 5))
```
locks [9:06 PM]
yes
[9:06]
but is `ns` restricted to the top-level of a module?
machty [9:07 PM]
to the REPLmobile
locks [9:07 PM]
hm, I'm seeing a problem with `{{import`
[9:09]
@machty `ns` in the actual repl works differently
machty [9:11 PM]
how's that
locks [9:11 PM]
I don't remember, it's been a while
[9:12]
https://www.beyondtechnicallycorrect.com/2013/04/14/loading-and-using-namespaces-in-the-clojure-repl/ likely related
[9:12]
hm doesn't totally explain it
machty [9:13 PM]
```borf=> (ns alex)
nil
alex=> (def a (ns lol))
#'alex/a
lol=>
```
[9:13]
i think `ns` is pretty side-effecty (edited)
[9:13]
only because it's grandspankenly obviously wrong to use it anywhere but the top of the file
[9:13]
cljs gives you a _few_ escape hatches, if you can even call them that, for setting global variables
[9:14]
ns could be considered one of them
locks [9:14 PM]
rust's module system is also super weird
[9:15]
clj was a bit of a disappointment. lovely language, utterly opaque ecosystem
machty [9:16 PM]
clj would benefit from ember experts
[9:16]
they are the masters of decomplection, n00bs at CoC
locks [9:16 PM]
CoC?
machty [9:16 PM]
convention over configuration
locks [9:16 PM]
I still remember the Pedestal framework being billed as next big thing
[9:16]
and then suddenly all the repos and websites disappear
[9:17]
"oh, we didn't like it, we use part of it internally now"
[9:17]
WhAt
cowboyd [9:17 PM]
`(ns wat)` expands to...... drum roll
[9:17]
```(do
(in-ns 'wat)
((fn*
loading__5569__auto__
([]
(. clojure.lang.Var
(clojure.core/pushThreadBindings
{clojure.lang.Compiler/LOADER
(. (. loading__5569__auto__ getClass) getClassLoader)}))
(try
(refer 'clojure.core)
(finally
(. clojure.lang.Var (clojure.core/popThreadBindings)))))))
(if (. 'wat equals 'clojure.core)
nil
(do
(. clojure.lang.LockingTransaction
(clojure.core/runInTransaction
(fn*
([]
(commute
(deref #'clojure.core/*loaded-libs*)
conj
'wat)))))
nil)))
```
locks [9:17 PM]
lovely macro (edited)
machty [9:18 PM]
lol
[9:18]
love it
[9:18]
i love clojure
[9:18]
i mean i haven't build anything in it
[9:19]
but when i get angry at ember i just `lein repl` and type `(+ 1 2 3 4 5)` just for funsies and i feel immediately better
locks [9:19 PM]
I tried to but, I ran into the ecosystem :X
[9:21]
last thing I did was a vehicle name generator for f-zero gx using core.logic
cowboyd [9:23 PM]
@machty I do the same thing, love to watch the macros incrementally expand.
[9:23]
expand, unexpand, expand all the way.
[9:24]
such relax
locks [9:24 PM]
incrementally expanding macros is my new prog rock ep
cowboyd [9:26 PM]
http://g.recordit.co/RNKY7oUZHB.gif (115KB)
mmun [9:26 PM]
`lein repl` sounds german
cowboyd [9:27 PM]
it’s `leine repl` when used in the singular.
locks [9:27 PM]
https://leiningen.org/img/leiningen.jpg (44KB)
cowboyd [9:30 PM]
the other thing that I just love about clojure is how hashes and arrays are also functions.
mmun [9:32 PM]
is decomplection a euphemism for "finding good primitives"?
locks [9:33 PM]
yes
cowboyd [9:33 PM]
if you haven’t watch simple vs easy it’s worth it
machty [10:02 PM]
uploaded this image: Image uploaded from iOS
Add Comment
machty [10:02 PM]
My friend looks like mr lein
----- Yesterday January 15th, 2017 -----
locks [3:59 AM]
I'm not fooled, that's you with a mustache
machty [8:43 AM]
i am wondering if `let-block` should actually be `let-component`
[8:44]
contextual components are already a thing
[8:44]
you pass them into HoCs as attrs
[8:44]
and you render them with `(component)`
[8:45]
it seems weird that as an HoC that some of your attrs would be `yield`ed and others would be `component`ed
machty [8:50 AM]
```Prior RFC API:
{{#let-block fooBlock as |a b c|}}
Hello {{a}}, {{b}}, and {{c}}!
{{/let-block}}
Maybe it should be component centric:
{{#let-component fooComp bar=123 as |c|}}
{{c}} is a reference to the component.
{{c.bar}} = 123 (unless the HoC override
bar when calling component helper)
{{/let-component}}
Just as before, you pass it in as attrs...
{{x-foo header=fooComp body=fooComp footer=fooComp}}
{{x-foo header=fooComp body=fooComp footer=fooComp}}
{{x-foo header=fooComp body=fooComp footer=fooComp}}
//x-foo layout hbs
{{component header more=123 values=456}}
{{component body more=123 values=456}}
{{component footer more=123 values=456}}
```
[8:52]
The yieldable block API isn't really congruent with contextual components
[8:56]
yieldable blocks only receive block params
[8:57]
hard to imagine how to merge a list of params with the hash of attrs that components receive when you render them
[8:59]
(and it would be bozo to try and write let-block / let-component positionalParams API)
machty [9:52 AM]
https://github.com/emberjs/rfcs/pull/199#issuecomment-272700009
cowboyd [4:09 PM]
Is the fundamental tension here that you cannot pass named parameters to a block?
[4:10]
I.e. there is no such syntax as:
```{{#let-block hello as |a b c :more "less" :values "123"|}}
{{a}} {{b}} {{c}}
* More is {{more}}
* Values are {{values}}
{{/let-block}}
```
machty [5:55 PM]
yes, something to that effect
[5:56]
blurg i thought i was going to avoid a slot syntax bikeshed but i don't think i can safely do so
locks [7:17 PM]
https://twitter.com/technomancy/status/819699427027755008
technomancy @technomancy
LISPERS: Lisp is great coz you can create any abstraction you want!
ALSO LISPERS: Let's use functions named after registers of the IBM 704
TwitterJan 12th at 7:15 PM
cowboyd [7:37 PM]
that’s a great quote.
machty [7:41 PM]
is that car cons stuff?
cowboyd [7:41 PM]
Yeah
locks [7:41 PM]
car and cdr I imagine
cowboyd [7:41 PM]
I knwo the `dr` is decrement register
[7:41]
and the `ar` is address register
[7:41]
but I can’t remember the `c`
locks [7:42 PM]
contents (via wiki)
cowboyd [7:43 PM]
@machty I didn’t see your response to my post about render syntaxt btw, just read the whole thing, so it kinda obviates my last comment
[7:43]
Sorry, if I came off as thick-headed.
machty [7:46 PM]
@cowboyd i never thought that
[7:46]
but here's more words! https://github.com/emberjs/rfcs/pull/199#issuecomment-272751317
cowboyd [8:12 PM]
Yeah, it seems totally reasonable. What would you say about an rfc to normalize rendering? I actually see that as a huge potential win.
locks [8:12 PM]
normalize rendering?
cowboyd [8:14 PM]
i.e. for `{{foo}}`
property? render it!
function? call and render it!
helper? call and render it!
component? render it!
[8:14]
standing at the head of an expression means evaluation.
[8:14]
period.
locks [8:15 PM]
https://twitter.com/eaf4/status/818425177918803968
Edward Faulkner @eaf4
@fbeausoleil @locks This is the default behavior in all of Javascript. Functions and values are not the same thing.
TwitterJan 9th at 6:52 AM
cowboyd [8:16 PM]
Good thing this isn’t JavaScript :slightly_smiling_face:
locks [8:16 PM]
read the thread
cowboyd [8:18 PM]
Yeah, I disagree with it.
[8:18]
eval position is special
[8:18]
let’s say I have two functions
[8:20]
`fn1` `fn2`
I’d expect `(fn1 fn2)` to evaluate `fn1` and pass `fn2` by value to `fn1` (edited)
[8:20]
So I don’t think Trek’s example makes sense in this case:
I would _not_ expect
`{{my-child some-foo=aPropertyThatIsAFn}}` to evaluate `apPropertyThatIsAFn`
[8:21]
the thing being evaluated is `my-child`
[8:22]
but I _would_ expect
`{{aPropetyThatIsAFn}}` to evaluate the function
locks [8:22 PM]
handlebars isn't lisp, yet
cowboyd [8:23 PM]
I also would expect:
`{{my-child some-foo=(aPropertyThatIsAFn)}}` to evaluate it.
[8:23]
It isn’t but I think we make it closer by simplifying its rules
locks [8:23 PM]
there's no eval position
[8:23]
you're breaking handlebars
cowboyd [8:24 PM]
I’m questioning the constraints, yes
[8:24]
and I do think there is an eval position
[8:24]
François Beausoleil`s intuition was pointing to it
[8:28]
It’s just what you do when something is in eval position:
currently `{{aPropetyThatIsAFn}}` evals `Function.prototype.toString()` when a function is in eval position
[8:28]
and except for debugging, I can’t think when you would ever want that.
locks [8:29 PM]
it evals everything to toString
cowboyd [8:29 PM]
yes, but that is evaluation that is happening when a value appears in a certain position.
[8:29]
and not in others
[8:30]
so there _is_ something special about `{{this-value and not others}}`
[8:30]
it just doesn’t happen to be a very useful evaluation
locks [8:31 PM]
that is not my understanding of the system
cowboyd [8:32 PM]
of what it _is_, or what it should be?
[8:33]
Like, I am totally totally with you. This is _not_ the way it behaves today.
locks [8:34 PM]
https://embercommunity.slack.com/archives/topic-forms/p1484530202001073 I disagree with this
cowboyd
so there _is_ something special about `{{this-value and not others}}`
Posted in #topic-formsYesterday at 8:30 PM
[8:35]
but I don't look too much under the hood
[8:35]
I still maintain that this breaks handlebars
cowboyd [8:36 PM]
I don’t look under the hood much either.
locks [8:37 PM]
hm, I don't see how to do the change
cowboyd [8:38 PM]
But conceptually, which is simpler?
locks [8:38 PM]
I like lisp :P
cowboyd [8:38 PM]
I’m curious how this breaks handlebars though.
[8:38]
As in an API change?
[8:38]
or philosophically?
locks [8:38 PM]
API change
[8:39]
you're changing the semantics
[8:39]
it'll not only break existing apps, it'll break in possibly silent ways
cowboyd [8:39 PM]
theoretically (which has very little basis in practicality) the semantics should be a superset
[8:40]
right now
`{{aPropetyThatIsAFn arg1 arg2}}`
[8:40]
is an error
[8:40]
so really, I’m proposing _unbreaking_ handlebars
[8:41]
the only apps that would break would be apps that rely on this error behavior.... which would be odd to say the least.
[8:42]
I have no idea what this would mean for the implementation
cowboyd [8:50 PM]
but that’s why I was soliciting opinion, because for me having a single concept for `{{thingy .........}}` which is `evaluate thingy and render it` for some definition of evaluate is extraordinarily powerful and easy to intuit.
machty [8:50 PM]
derailment in t minus 30s
cowboyd [8:50 PM]
derailment should be the name of this channel.
machty [8:50 PM]
```{{#with-slots (component 'complex-component' a=123) as |slot|}}
{{slot 'header' as |attrs|}}
{{/slot}}
{{#slot 'footer' as |attrs|}}
{{/slot}}
{{slot 'body' (component 'wat' foo=123)}}
{{/with-slots}}
```
cowboyd [8:51 PM]
did you just turn the problem inside out?
locks [8:51 PM]
irc rule #2: if a channel has a specific topic, 80% of the discussion will be off-topic
machty [8:51 PM]
yes, i decomplected!!!!
[8:52]
basically, i think i've convinced myself that whatever slot syntax we land on should be `(component)` centric
[8:52]
rather than template block centric (with positional block params) (edited)
[8:52]
so this is an attempt at a helper that collects slots, turns them into components, and passes them into the 'complex-component' as attrs
[8:53]
no new weird null zone funky syntax that the other RFCs have
[8:54]
i consider this a good idea regardless of whether some form of inline let / let-block is accepted
cowboyd [8:55 PM]
It’s really good
[8:56]
You can implement this today with `slot` as a contextual component, right?
machty [8:57 PM]
yeah, figure i'll try shortly
[8:57]
unless you wanna
cowboyd [8:57 PM]
like no change necessary.
[8:59]
nah, Imma go fill up my growlers.
ryanto [9:23 PM]
i like with slot, i can try to implement that
machty [9:25 PM]
i'm trying but i might likely fail
[9:25]
i'll let you know if i do
[9:25]
i don't actually know what's possible
ryanto [9:26 PM]
`{{#slot 'footer' as |attrs|}}`, what is attrs in this case? a=123?
machty [9:27 PM]
i think it is actually an instance of Component
[9:27]
with all the various properties merged into it already
[9:27]
like out `(component 'x-foo' bar=123)` might be rendered with `{{component xFooRef bar=456}}`
[9:28]
it's a bit wat but it's also pretty consistent / flexible with today's `(component)` usage
machty [9:44 PM]
@ryanto ok i don't have time to figure this out tonight (edited)
[9:44]
https://ember-twiddle.com/208b5d4a8c691f9ab882ec65514eb8c9?numColumns=2&openFiles=templates.components.complex-component.hbs%2Ctemplates.application.hbs
[9:45]
basically we need the ability to pass in something _like_ a contextual component
[9:45]
but it might be explicitly forbidden atm
mmun [10:48 PM]
https://embercommunity.slack.com/archives/topic-forms/p1484531547001105
machty
basically, i think i've convinced myself that whatever slot syntax we land on should be `(component)` centric
Posted in #topic-formsYesterday at 8:52 PM
[10:48]
convince me plz (edited)
[10:50]
anonymous blocks are the right primitive imo. components have too much machinery. but maybe i missed which use case you’re talking about? I would like to understand the use cases being addressed. We should make a spread sheet of usecases vs. solutions. e.g. i think anonymous blocks is the right solution for power-select. (edited)
[10:53]
https://embercommunity.slack.com/archives/topic-forms/p1484529815001063
locks
there's no eval position
Posted in #topic-formsYesterday at 8:23 PM
[10:55]
this comment is strange to me. clearly the first slot in an mustache/subexpression has different semantics than the remaining slots.
[10:57]
it seems fine to explore amending the semantics to support calling contextual things like `{{this.foo.bar blah blah}}`. i don’t think anyone is proposing to break ember. (edited)
[10:58]
there’s an issue with the ambiguity of `{{this.foo.bar}}` but it’s by no means a dealbreaker. e.g. you can disambiguate with `{{(this.foo.bar)}}` (edited)
cowboyd [11:11 PM]
what about just calling functions?
[11:11]
I think I see, basically `{{this.foo.bar}}` references a function
mmun [11:13 PM]
yeah, sure
[11:14]
i edited to “contextual things” there to keep it ambiguous :slightly_smiling_face: (edited)
cowboyd [11:14 PM]
ah, I thought I read it as helpers at first.
mmun [11:14 PM]
`{{this.foo.bar}}` have value-specific behaviour might be too trollish
[11:14]
e.g. execute if its a function, otherwise dont
[11:15]
it’s not obvious to me if that is too trollish atm
[11:15]
it gets worse when you have things like `onclick={{this.foo.bar}}` (edited)
cowboyd [11:15 PM]
does it?
[11:15]
oh, yeah
[11:15]
it does
mmun [11:16 PM]
`{{(this.foo.bar)}}` is an easy way to skip this issue :stuck_out_tongue:
cowboyd [11:16 PM]
I’m happy with `onclick={{action this.foo.bar}}`
mmun [11:16 PM]
that ship has sailed though
[11:16]
`onclick={{this.foo.bar}}` already works
[11:17]
but even if it hadn’t, I wouldn’t be a fan of value-specific semantics (e.g. determined by whether the value is callable or not) (edited)
[11:18]
^ it’s more subtle than how i stated… value-specific semantics are ok sometimes… ;/
cowboyd [11:19 PM]
I think it could work, but it would be a fundamental breaking change.
mmun [11:19 PM]
i really dislike `{{action this.foo.bar}}`
[11:19]
and action in general
[11:20]
i feel like i’m the only one who feels this way
[11:20]
but I just want to use plain old functions
cowboyd [11:20 PM]
no, I’m also not the hugest fan
[11:20]
because it’s an escape hatch
[11:20]
it’s pressing the eject button on your context
mmun [11:20 PM]
e.g. if i have a custom button that take’s an onclick attribute and uses it as `<button onclick={{onClick}}>`
[11:21]
and is invoked by `{{my-button onClick=(|| console.log("maybe one day");)}}`
[11:22]
i’m jk about the lambda,
cowboyd [11:22 PM]
I think it’s fab
[11:22]
but I also think that action was an important step in the evolution.
mmun [11:23 PM]
there’s lots of good reasons for action to exist
cowboyd [11:23 PM]
I got no beef with action, but again, a lot of the time its a backstop
[11:24]
for the inability to declare abstractions natively
mmun [11:24 PM]
they solve a lot of design issues that you have when just using functons
cowboyd [11:24 PM]
but I think that `{{(eval-and-render-me-plz)}}` is :thumbsup::skin-tone-3:
mmun [11:24 PM]
e.g. what is `this` inside of a function call in the helper
[11:25]
`<button onclick={{this.handleClick}}>` might not behave the way you expect (edited)
[11:25]
so I appreciate actions for making everyone productive in the mean time
[11:27]
but I think react’s `<Button onClick={(e) => this.handleClick(e)}>` is better. and i’m not ashamed to try and get ember to that point. (edited)
cowboyd [11:31 PM]
`<button onclick={{(|e| (this.clickHandler e)}}>`
[11:31]
totally gratuitous
[11:32]
but I’m falling in love with this `λ` syntax
mmun [11:32 PM]
why not `<button onclick={{|e| (this.clickHandler e)}}>`
[11:32]
maybe that’s what you meant? parens didn’t match
cowboyd [11:33 PM]
I suppose it could be bare
[11:33]
oops
[11:33]
`<button onclick={{(|e| (this.clickHandler e))}}>`
[11:37]
I’m just used to lambda forms having surrounding `()` e.g. `(fn [x y])` from clj or `(lambda (x y))` from scheme, so I naturally gravitate towards `(|x| )`
[11:37]
How would it effect the parser?
mmun [11:38 PM]
it’s all fine from a parse pov
[11:38]
it’s invalid syntax atm
cowboyd [11:39 PM]
so true, but the more I see it the more I wantz.
[11:41]
but in terms of less crazy ideas, how hard would it be to actually implement the `{{(call-and-render)}}`?
[11:41]
would you need anything else for contextual helpers?
mmun [11:42 PM]
it already works
cowboyd [11:42 PM]
with any function?
mmun [11:42 PM]
ah, probably not
cowboyd [11:43 PM]
I was almost about to get up and dance :slightly_smiling_face:
mmun [11:43 PM]
people are against having things being able to be looked up on the context and globals
[11:44]
there was a suggestion that it needed to have some way to statically disambiguate
[11:44]
like {{(this.call-and-render)}}
cowboyd [11:47 PM]
I’m getting a parse error https://ember-twiddle.com/fb7c1624c537966498dab9b2436c3309?openFiles=templates.application.hbs%2C
[11:48]
I’m a proponent of prefixing context values with `this.`
mmun [11:48 PM]
me too
cowboyd [11:48 PM]
feel strongly that lexical values should have highest priority (over globals) (edited)
mmun [11:49 PM]
oh, everyone agrees
cowboyd [11:49 PM]
well that’s a relief.
mmun [11:49 PM]
it was a bug that that wasn’t always true
[11:49]
i think it was fixed
cowboyd [11:50 PM]
in fact, might be awesome to have a global sigil too, in the same vein as a `this.` for context
[11:50]
{{`/global-value`}}
mmun [11:50 PM]
https://github.com/wycats/handlebars.js/blob/master/src/handlebars.yy#L140-L148
[11:50]
doesn’t include sexpr
[11:50]
oops
[11:50]
helperName is the first slot of a curly (edited)
cowboyd [11:53 PM]
But requireing `this.` to prefix values from the context is a super breaking change
[11:53]
I think it would be an exciting development, but highly break-o
locks [11:55 PM]
something something glimmer components
----- Today January 16th, 2017 -----
machty [4:37 AM]
https://embercommunity.slack.com/archives/topic-forms/p1484538531001133
mmun
convince me plz
Posted in #topic-formsYesterday at 10:48 PM
[4:37]
Some of this is coming from convos I've had with trek
[4:38]
Which elaborate on his ember camp talk that everyone references (edited)
[4:38]
We've been thinking about ways to extend/override components
[4:39]
Hmm you know i should just ask him what he thinks of with slots
[4:44]
But anyways the reason I like component centric is that it adds minimal bloat to the render api
[4:44]
Doing yield slots means expanding the yield api
[4:45]
The component approach has already proven its utility
[4:46]
Lots of apps pass in overridable bits in component form
[4:46]
With slots just lets you continue on that track without having to rewrite your higher order component's api
[4:47]
I think the higher order component case is key here
[4:47]
You want to be able to override internals with both a slot syntax and just passing an attr (is this controversial?)
[4:48]
But how would you write an HOC that allowed both?
[4:50]
In one case you render w {{component attrComp a=foo b=bar}} and the other you {{yield foo bar to=attrBlock}}
[4:52]
If the syntaxes were unified you'd need some way to pass simultaneously positional and named params
arielz [5:02 AM]
joined #topic-forms. Also, @taras joined.
fivetanley [9:50 AM]
dang, lotta decomplecting going on in this channel
locks [9:51 AM]
yeah, we gotta decomplect all the decomplecting
machty [10:07 AM]
@mmun curious for your response to all that
[10:07]
sounds like what i'm suggesting will be at odds with slots being "static"
mmun [10:09 AM]
I am not dogmatic about static vs. dynamic. There are just elements of the dynamic solution that are deeply unappealing to me in some cases. (edited)
[10:10]
like needing to {{yield}} to "register" side-effects
[10:12]
I can't help but make the analogy with procs & blocks again
machty [10:12 AM]
well before you do that, i don't think the with-slots solution suffers from that
mmun [10:12 AM]
{{yield foo bar to=attrBlock}}
{{yield foo bar to=&someComponent}}
machty [10:13 AM]
i mean, `with-slots` internally will yield, but that happens as an implementation detail to with-slots rather than something that all HOCs have to do
mmun [10:14 AM]
it's still deeply unsettingly to me.
[10:14]
but there's more
[10:14]
does `with-slots` invoke the component? (edited)
fivetanley [10:15 AM]
https://media.giphy.com/media/xkvd0OGbRt41G/giphy.gif (1MB)
[10:15]
there is reason to be upset, but this is my favorite gif
mmun [10:15 AM]
it's v good gif
[10:15]
@fivetanley are you still in TX?
fivetanley [10:15 AM]
c
mmun [10:16 AM]
https://embercommunity.slack.com/archives/topic-forms/p1484531459001101
(just bubbling it back up)
machty
```{{#with-slots (component 'complex-component' a=123) as |slot|}}
{{slot 'header' as |attrs|}}
{{/slot}}
{{#slot 'footer' as |attrs|}}```
Show more…
Posted in #topic-formsJan 15th at 8:50 PM
machty [10:17 AM]
`with-slots` yields the block passed to it to register side-effects (collecting all the slot blocks in a registry) and passing those slots in as attrs to the (component) you pass to it
mmun [10:17 AM]
`{{#with-slots (component 'complex-component' a=123) as |slot|}}{{/with-slots}}`
==?
`{{component 'complex-component' a=123}}`
machty [10:17 AM]
yes
mmun [10:18 AM]
ok so how do you curry a block/slot/whatever? (edited)
machty [10:19 AM]
so my idea, that is likely DOA (unless it can be made to work as an addon)
mmun [10:19 AM]
if its a good idea I don't like that it is fundamentally DoA :stuck_out_tongue:
machty [10:19 AM]
is that for each slot, we build an anonymous component that behaves as if it were created by `(component 'anonymous-component')`
mmun [10:19 AM]
we can hax glimmer
machty [10:20 AM]
and as a sneaky hack
[10:20]
the block param that each slot block takes is a reference to that anonymous component
mmun [10:20 AM]
what if you want to pass an array of blocks?
fivetanley [10:20 AM]
what advantage does this approach have over something like ember-block-slots?
mmun [10:21 AM]
we need to pin an answer to that question
machty [10:21 AM]
@fivetanley i'll answer in a moment
[10:21]
or maybe now?
[10:21]
@mmun what did you mean about array
mmun [10:21 AM]
sec, writing an example
[10:22]
```{{#my-table dataSource=recordArray}}
{{#column as |record|}}
{{record.id}}
{{/column}}
{{#column as |record|}}
{{record.name}}
{{/column}}
{{/my-table}}
```
(edited)
machty [10:23 AM]
lemme know when i should have enough info/context to respond (edited)
mmun [10:24 AM]
that is a strawman that embodies the idea, but by no means do i think ^^ is the syntax that would end up being the solution
[10:25]
i would hope our solution to tables would be closer to what is possible in react, where you could pass an array of component factories (edited)
[10:25]
`<MyTable dataSource={recordArray} columns={ [Column1, Column2] }>` (edited)
mmun [10:26 AM]
hands the mic to machty
machty [10:27 AM]
ohhhh ok
[10:27]
so that goes beyond giving a named list of overrridable slots
[10:27]
(have any of the proposed slot RFCs addressed that use case?)
mmun [10:28 AM]
RFCs no (edited)
machty [10:29 AM]
maybe slots with the same name are passed in as arrays
mmun [10:29 AM]
sure
machty [10:30 AM]
and HOCs like table components can provide contextual components with the name built in so that end users don't have to type `slot 'column'`
mmun [10:31 AM]
```{{#my-table dataSource=recordArray}}
{{#column heading="ID" as |record|}}
{{record.id}}
{{/column}}
{{#column heading="Name" as |record|}}
{{record.name}}
{{/column}}
{{/my-table}}
```
(edited)
[10:31]
if you keep down this path, this sort of thing ought to be possible as well ^ (edited)
machty [10:32 AM]
so i think that's all possible regardless of whether we opt for component or block centric
mmun [10:32 AM]
or maybe not
machty [10:32 AM]
i feel like i should clarify why i think component is a good idea (and what it actually means API wise)
[10:32]
unless that's already clear
mmun [10:33 AM]
the reason I'm knee-jerk softly oposed to components-centric is that I think something like {{#each}} being component centric would be strange
machty [10:34 AM]
let's figure out what that would actually look like
[10:36]
basically i'm not trying to somehow deprecate all of the yield API
mmun [10:36 AM]
I know
machty [10:36 AM]
for simple components that basically just wrap `each` and render items in a list, just use the yield API
[10:37]
but if you have a complex HOC and ONE of the things it happens to do is render multiple items in a list... then maybe container centric is OK?
[10:37]
so yeah, what's an example i/we can jot up
machty [10:43 AM]
Given x-foo layout:
```<div class="x-foo-header">
{{component header headerText=headerTextFromXFoo}}
</div>
<div class="x-foo-footer">
{{component footer footerText=footerTextFromXFoo}}
</div>
```
Here are all the ways you can pass overridable bits into x-foo
```// application.hbs
// using only slots
{{#with-slots (component 'x-foo') as |s|}}
{{#s.slot 'header' as |c|}}
<h1>{{c.headerText}}</h1>
{{/s.slot}}
{{#s.slot 'footer' as |c|}}
<h1>{{c.footerText}}</h1>
{{/s.slot}}
{{/with-slots}}
// just passing in a (component) w today's API
{{x-foo header=(component 'x-foo-header-override')}}
// combo platter
{{#with-slots (component 'x-foo'
header=(component 'x-foo-header-override')) as |s|}}
{{#s.slot 'footer' as |c|}}
<h1>{{c.footerText}}</h1>
{{/s.slot}}
{{/with-slots}}
```
(edited)
[10:43]
i forget if i've written up the latest, so here it is as i see it
[10:44]
@fivetanley (et al) the reason i favor this approach (the component-centric approach) is that it is compatible with how people are passing in / overriding components today
[10:45]
whereas slot syntax would build out the APIs specific to yielding
[10:45]
which use positional block params for passing data
[10:45]
which is at odds with the `attr=(component)` API and would always need this annoying translation layer (between positional block params and attr=) (edited)
[10:46]
not to mention we'd have to tell everyone who's already written HOCs via `attr=(component)` that the path forward is to rewrite their stuff using yield-centric slot syntax
fivetanley [10:48 AM]
interesting
[10:48]
i’m interested to see where this road leads
[10:51]
man JS devs have it so nice that people think about these things
[10:52]
you basically couldn’t do this in rails
[10:52]
without a bunch of weird presenter type things
machty [10:53 AM]
yeah
machty [11:28 AM]
@mmun is it possible to implement `with-slots` in an ember-twiddle? specifically i need a way to have the `slot` contextual component "stash" its yield block on the `with-slots` registry and 2) wrap those saved blocks in `(component)` anonymous components (edited)
[11:29]
i don't really know the glimmer limitations there
[11:29]
i'd really like to be able to play around with this pattern
cowboyd [12:04 PM]
When I read component-centric vs block-centric it makes me think of this:
In ruby, it was a constant source of pain in the `<= 1.8` days that the expressive power of methods and procs were different, and that you could not define one in terms of the other.
```proc do |capture *args &and_a_block|
# invalid syntax in prior to 1.9
end
```
That changed in 1.9 when procs could themselves capture both splat args and other procs and there was a palpable sigh of relief in the library author community because now there was no friction in generating new apis programmatically. Previously there was this false dichotomy which everyone felt, but few could place a finger on that made everything feel so much better when it went away. I know that’s a deep problem when applied to hbs, but is there consensus that it should be a long term goal? (edited)
machty [1:42 PM]
Here's a more fleshed out case for component-centric slots
[1:42]
https://gist.github.com/machty/c00c83f3fbefefa72cefb0bb2322fc4f
[1:46]
@cowboyd: I see the parallels
[1:47]
There's too many cases of multiple ways to do things in ember
[1:47]
It's like a depth first search
[1:48]
Follow your intuition, go down a path, find out 2 hours later you've hit a dead end and that in fact you need to use the OTHER API for accomplishing a similar thjng
[1:48]
Helpers vs components vs outlets
zigahertz [2:15 PM]
joined #topic-forms. Also, @cibernox joined.
cibernox [6:21 PM]
:hand::skin-tone-5:
davewasmer [6:28 PM]
joined #topic-forms
ryanto [6:28 PM]
Hey alex do you have that gist / markdown with all the form problems when we started this channel?
[6:28]
cant find it, wondering if it got eaten by slacks chat limit
machty [6:42 PM]
@ryanto https://gist.github.com/machty/68afad4c03109f36d4f4cffaae3c170b
[6:42]
updated it earlier today
ryanto [6:43 PM]
awesome ty!
locks [11:25 AM]
https://github.com/emberjs/rfcs/pull/200#issuecomment-273142254 :sob:
mmun [11:36 AM]
the intent is good
[11:37]
we should encourage him to submit a PR targeted at cowbody’s PR
[11:37]
that way we can discuss the differences
[11:38]
@cowboyd: what do you think of using a hash style for block-let?
[11:38]
i understand the reasoning, but it feels trollish to an outsider that block-let and inline-let have different apis (edited)
locks [11:39 AM]
I want to kill with, not add more things
lolmaus [11:42 AM]
joined #topic-forms by invitation from @mmun
mmun [11:45 AM]
The primary motivation for the `let` RFC is to decouple the if-like behaviour away from the local variable binding behaviour (edited)
[11:46]
This also gives us an opportunity to rethink the syntax, but that is secondary. (edited)
[11:47]
For that reason, I don’t see @lolmaus’s RFC as an alternative to the `let` RFC. (edited)
[11:48]
It is a power-up for `with`. (edited)
locks [11:49 AM]
but we can't remove the conditional behaviour
mmun [11:49 AM]
It is possible (and in my opinion, likely) that the `let` RFC will lead to a deprecation of `with`. In that event, it wouldn’t make sense to continue investing into `with`. (edited)
locks [11:49 AM]
if `let` gets in, that'll be my goal
mmun [11:51 AM]
Hi @lolmaus :slightly_smiling_face:
lolmaus [11:52 AM]
Hey @mmun, @locks. What do you think of the imperativeness of the inline form of `let`?
mmun [11:52 AM]
It is not imperative at all.
lolmaus [11:53 AM]
You open a large template, append a portion of code and use inline let.
mmun [11:53 AM]
it is a declaration of an alias (edited)
lolmaus [11:54 AM]
It either errors out because there's another inline let somewhere on this level, or you redefine a variable and some unrelated code breaks because it relies on the old value.
[11:55]
Depending on whether more than one inline let is forbidden
mmun [11:55 AM]
I implemented inline-let in `ember-let`
[11:55]
and I don’t understand your description
[11:55]
give me an example when you can (i assume you’re on your phone…) (edited)
lolmaus [11:56 AM]
Yes, I'm standing in a bus ATM :bus: , will try providing an example in a few hours.
mmun [11:56 AM]
:+1:
lolmaus [11:57 AM]
Does ember-let forbid more than one inline let on the same level? Or does it merge them?
mmun [11:57 AM]
It is not forbidden. I don’t think merge is the right word. They get nested
[11:58]
```{{let a = 1}}
{{let b = (multiplty a 2)}}
...
```
(edited)
lolmaus [11:59 AM]
I'm AFK, thx for inviting me to the discussion.
mmun [11:59 AM]
is like
```{{#let a=1}}
{{#let b=(multiply a 2)}}
...
{{/let}}
{{/let}}
```
(edited)
[11:59]
no problem. I want to make sure we consider all the best ideas.
cowboyd [12:12 PM]
https://embercommunity.slack.com/archives/topic-forms/p1484671080001375
mmun
@cowboyd: what do you think of using a hash style for block-let?
Posted in #topic-formsToday at 11:38 AM
[12:13]
I don’t see a problem with this. It makes the block form a little more magical
[12:15]
but the inline form is more magical and seems to be really tripping people up.
[12:18]
Using cardinality to bind names to values is an anti-pattern. I.e. I wouldn’t like this code.
```{{#let 1 2 3 4 as |a b c d|}}
{{/let}}
```
locks [12:20 PM]
inline-let gives me the sheevs
cowboyd [12:21 PM]
I think this reads just fine.
```{{#let a=1 b=2 c=3 d=4}}
{{sum a b c d}}
{{/let}}
```
Based on my knowledge of the runtime at the time I was implementing `let` I didn’t see how this was possible.
[12:21]
without making deeper changes than just adding a helper
locks [12:21 PM]
```{{#let (hash one=1 two=1) as |blurp|}}
{{blurp.one}}
{{/let}}
```
^ what people do with contextual components
[12:21]
which I think is fine
[12:21]
given that it's already a pattern
[12:22]
I've seen it used with `with` too
cowboyd [12:22 PM]
Once you start to really lean on it, it really suffers from “aww do I have to?” syndrome.
mmun [12:24 PM]
using `hash` makes optimizations harder (edited)
[12:25]
not a strong argument for the user, but a strong one for implementers :stuck_out_tongue:
cowboyd [12:28 PM]
user argument: if you’ve never seen ember before compare `{{#let name=value}}` vs `{{#let (hash name=value)}} as |thing|}}` (edited)
mmun [12:28 PM]
yep
[12:29]
the word hash is very specific
cowboyd [12:29 PM]
if a hash is really what you want: `{{#let thing=(hash name=value)}}`
mmun [12:29 PM]
it’s just a map. or can you prove that it uses hashes? (edited)
cowboyd [12:30 PM]
yeah, I actually don’t like the `hash` helper
[12:30]
name
mmun [12:30 PM]
that ship has sailed :stuck_out_tongue:
[12:30]
i might have implemented it..
locks [12:31 PM]
don't named arguments make let megamorphic
cowboyd [12:32 PM]
That sounds pretty awesome!
[12:32]
(but only because I don’t know what it means)
mmun [12:32 PM]
i think there are two many layers of abstraction between the JIT and handlebars to be able to answer that
[12:32]
megamorphic a JIT heuristic
[12:33]
it means “very polymorphic"
[12:33]
and thus, tends to not get optimized for any specific type
locks [12:33 PM]
@cowboyd me neither, but didn't I sound really cool
mmun [12:33 PM]
this isn’t a bad thing, though. if the function is genuinely megamorphic you don’t want to specialize for every possible type (edited)
locks [12:33 PM]
but I do mean, won't it bust the shape up
[12:34]
and deopt
cowboyd [12:34 PM]
@locks I was thinking of like megalodon swooping in and swallowing the entire scope.
machty [12:44 PM]
There should be a hash literal syntax
[12:44]
(Wat=lol)
cowboyd [12:47 PM]
I like that a lot. See also `(wat: lol)`, `(:wat lol)`
[12:47]
although I think NV pairs are so established elsewhere in hbs, that `=` is the only real alternative
locks [12:50 PM]
something something clojurescript
machty [1:11 PM]
It'd have to be =
cowboyd [2:06 PM]
That actually might be a compelling alternative `{{#with (firstName="bob" lastName="Dobalina") as |person|}}` I’ll include it in the alternatives section.
locks [2:07 PM]
I thought `()` would mean an invocation, with the first item being special
cowboyd [2:08 PM]
You have a point, this would definitiely have to be a special case.
locks [2:09 PM]
ambiguity :\
cowboyd [2:10 PM]
`(# firstName="bob" lastName="dobalina")`
mmun [2:22 PM]
there's no ambiguity with `(firstName="bob" lastName="Dobalina")`
[2:22]
it just requires one token look ahead
locks [2:26 PM]
for programmers
[2:26]
it's confusing enough to have to use parens for nested expressions
samselikoff [2:27 PM]
`{{#with (firstName="bob" lastName="Dobalina") as |person|}}` is kinda awesome
locks [2:28 PM]
would that be falsey if both named args were falsey?
mmun [2:28 PM]
wat
locks [2:29 PM]
with has conditional semantics
[2:29]
I'm asking how that interplays
mmun [2:29 PM]
they don't depend on the fields of the value
locks [2:29 PM]
what do you mean
mmun [2:30 PM]
{{#with (firstName="") as |person|}}
{{#with (hash firstName="") as |person|}}
{{#with this.personWithEmptyName as |person|}}
[2:30]
`with` behaves the same way for all of them
[2:30]
which is to display the block (edited)
locks [2:39 PM]
it doesn't
[2:40]
the last one doesn't display a block
[2:40]
if the first item is falsey, it doesn't render
[2:42]
`hash` returns an object, so that's never falsey
[2:42]
so I'm wondering about the named args stuff
mmun [2:50 PM]
regardless, they would all have the same semantics
locks [2:51 PM]
I don't like breaking with for everyone
mmun [2:51 PM]
what on earth are you talking about
locks [2:52 PM]
https://embercommunity.slack.com/archives/topic-forms/p1484681404001479
mmun
{{#with (firstName="") as |person|}}
{{#with (hash firstName="") as |person|}}
{{#with this.personWithEmptyName as |person|}}
Posted in #topic-formsToday at 2:30 PM
[2:52]
you're saying the three forms behave the same, and they render the block
mmun [2:52 PM]
i don't care what they do... (edited)
[2:52]
as long as they do the same thing! (edited)
locks [2:52 PM]
but the last one doesn't
[2:52]
currently
[2:52]
the last one renders the else block
[2:53]
so you need to change the existing semantics
mmun [2:53 PM]
that's not true
locks [2:53 PM]
I just tried it
mmun [2:53 PM]
you did it wrong (edited)
[2:53]
but it's besides the point
[2:53]
the should have the same semantics
[2:53]
whatever the current semantics are
[2:53]
they should, all 3, do the same thing.
locks [2:56 PM]
welp
mmun [2:59 PM]
https://ember-twiddle.com/8625148b9e90ece2308cac6147b08b10?numColumns=2&openFiles=templates.application.hbs%2Ccontrollers.application.js
cowboyd [3:00 PM]
`this.person` works like today?
mmun [3:01 PM]
can you elaborate?
cowboyd [3:01 PM]
Like in your twiddle, you used `this.person` I wasn’t aware that was a thing.
mmun [3:02 PM]
oh yes. since the very beginning
[3:02]
it can be used to break ties vs. globals and locals
cowboyd [3:02 PM]
well that’s an embarassing gap in my knowledge
lolmaus [3:03 PM]
@mmun Trying `ember-let` in a Twiddle, and it says "let is not a helper". :thinking_face:
mmun [3:05 PM]
:poop:
[3:07]
how does the ember-twiddle even support addons
[3:07]
:glimmer:
[3:10]
I don't know why it doesn't work in ember-twiddle
lolmaus [3:16 PM]
@mmun Have you tried it yourself?
mmun [3:16 PM]
yes
lolmaus [3:16 PM]
@mmun Does it work for you?
mmun [3:16 PM]
no
lolmaus [3:16 PM]
Ok... I'll try to describe with words then.
[3:19]
@mmun Imagine you've got a template where you use `ember-let` like this:
```{{let apples=(array 1 2 3)}}
<p>
We've got {{array-reduce apples}} apples.
</p>
```
This is followed by lots of Handlebars and HTML code.
You open this file and you don't remember there's `apples` defined somewhere above. You decide to define it:
```{{let apples="Malus pumila"}}
```
[3:20]
And suddenly your app crashes because `"Malus pumila".reduce` is not a function.
[3:21]
@mmun
mmun [3:22 PM]
how is that any different from a block form?
[3:24]
if you want to keep the scope of your variables tight, then use the block form
[3:24]
in practice this doesn't really happen
[3:26]
```{{let apples=(array 1 2 3)}}
<p>
We've got {{array-reduce apples}} apples.
</p>
<div>
{{let apples="Malus pumila"}}
An {{apples}} a day keeps the doctor away.
</div>
<p>
We've still got {{array-reduce apples}} apples.
</p>
```
[3:26]
Under the current scoping rules, this will work correctly.
[3:27]
the second `let` definition only lives until the end of the `div`
lolmaus [3:27 PM]
@mmun What if you use two lets on one level?
mmun [3:27 PM]
that case will break
[3:27]
```{{let apples=(array 1 2 3)}}
<p>
We've got {{array-reduce apples}} apples.
</p>
{{let apples="Malus pumila"}}
<p>
An {{apples}} a day keeps the doctor away.
</p>
<p>
We've still got {{array-reduce apples}} apples.
</p>```
(edited)
[3:28]
^ bad times
lolmaus [3:28 PM]
@mmun If the developer used a block for manually, without the magical transformation, they'd be seeing exactly what they're doing.
But this inline let is doing something un-obvious. That's perefectly fine for an addon, but for Ember core it's too funky, IMO.
mmun [3:29 PM]
I disagree. It works fine in every other programming language with a declarative let.
lolmaus [3:30 PM]
In other languages an assignment does not influence code above it. But with inline `let`, it does! :scream_cat:
mmun [3:32 PM]
ok, I respect your point and would be ok with forcing inline-let's to be at the top of a block (edited)
[3:32]
or at least to not have multiple on the same level (edited)
[3:33]
or some kind of rule to alleviate what you're saiyng.
[3:33]
```let apples = vec![1,2,3];
println!("We've got {} apples.", apples.iter().sum());
let apples = "Malus pumila";
println!("An {} a day keeps the doctor away.", apples);
println!("We've still got {} apples.", apples.iter().sum());
```
[3:33]
In rust, this would throw a compiler error.
locks [3:33 PM]
@mmun I see where we talked last each other
mmun [3:34 PM]
@lolmaus my understanding of your argument is that we can't throw a compile-time error the way Rust does here, so we have resolve this issue some other way. (edited)
locks [3:34 PM]
Let me try to reformulate, with with named arguments is always truthy? Could you mix positional and named args? What would that mean?
mmun [3:35 PM]
for what it's worth, this _would_ compile:
```let apples = vec![1,2,3];
println!("We've got {} apples.", apples.iter().sum());
{
let apples = "Malus pumila";
println!("An {} a day keeps the doctor away.", apples);
}
println!("We've still got {} apples.", apples.iter().sum());
```
[3:37]
@locks: I see. I was just entertaining the idea. I'm not in favour of giving `with` the additional semantics laid out in Andrey's RFC 1) because we missed the boat on the original design and it would be too confusing to have support both positional _and_ named arguments and 2) we have an opportunity with `let` to get it right without the baggage. (edited)
locks [3:39 PM]
As it's probably obvious by now, I agree with :skull: with, was going down that road though
[3:39]
Seems like it introduces complexity
mmun [3:40 PM]
Complexity is ok. Ember-concurrency is complex.
locks [3:40 PM]
We can do regular named params with let right
mmun [3:40 PM]
but yeah, unnecessary complexity is not ok.
locks [3:41 PM]
E-c is trying to solve concurrency, not bind some lexical values ;x
lolmaus [3:42 PM]
What if we prevent inline `let` from affecting the code above it? (edited)
[3:42]
sorry
mmun [3:42 PM]
that's already the case
locks [3:43 PM]
Please define above
mmun [3:43 PM]
```{{let color="red"}}
{{color}}
{{let color="blue"}}
{{color}}
```
=> red blue
[3:44]
the binding only applies from them declaration until the end of the block
lolmaus [3:44 PM]
@mmun Oh then my objection wasn't valid. I'm sorry.
mmun [3:44 PM]
It is valid.
[3:44]
I object to your counter-objection.
lolmaus [3:44 PM]
:scream:
mmun [3:45 PM]
If you have a large template like:
```{{let color="red"}}
I love {{color}}!
... lots of stuff ...
I still love {{color}}!
```
```I love red!
... lots of stuff ...
I still love red!
```
(edited)
[3:46]
and someone comes along and introduces new code _that is also at the same level_ you can have issues
locks [3:46 PM]
Can we error?
[3:46]
Duplicate definition
mmun [3:47 PM]
```{{let color="red"}}
I love {{color}}!
... lots of stuff ...
{{let color="blue"}}
Mary's favourite color is {{color}}!
... lots of stuff ...
I still love {{color}}!
```
```I love red!
... lots of stuff ...
Mary's favourite color is blue!
... lots of stuff ...
I still love blue! <-- oops
```
(edited)
[3:48]
Errorring for a duplicate definition for the same name AND the same level is a pretty reasonable compromise. (edited)
locks [3:48 PM]
Rust style ;)
mmun [3:48 PM]
no - rust is perfectly content with the "oops" scenario
[3:49]
but that is because you don't normally edit the middle of functions in code (edited)
[3:49]
but with templates you do (and very often!) (edited)
locks [3:49 PM]
Js style? :[
mmun [3:50 PM]
I am pretty happy with that compromise.
lolmaus [3:50 PM]
My point is that with the block form there's no way this could happen unnoticed. Because the user consciously defines the start and the end of a variable's scope.
But this inline thing is shady. It's like we're creating a hole in the floor, realize it's to dangerous so we cover it with wood planks. Now people are gonna stumble on the planks, but at least they don't fall into the hole.
mmun [3:51 PM]
I'm going to need a non-carpentry metaphor
[3:52]
concrete issues that can occur
lolmaus [3:53 PM]
@mmun The block form is perfectly safe. The inline form creates a problem. We're gonna work around the problem by forbidding more than one invocation on the same level. People are gonna run in this limitation and they'll be frustrated.
locks [3:53 PM]
I don't actually agree with the block argument
[3:53]
The delimiters are at the beginning and the end
mmun [3:53 PM]
What does safe mean?
[3:53]
It's not concrete.
locks [3:53 PM]
With sufficient coffee you don't know the scope you're in
mmun [3:54 PM]
my concern with block-let is that it causes your templates to drift to the right.
lolmaus [3:54 PM]
Safe = nothing un-obvious happens under the hood.
mmun [3:54 PM]
inline let is not surprising to me.
lolmaus [3:55 PM]
Because you're the author of the addon? :trollface:
mmun [3:55 PM]
because I've programmed in functional languages.
[3:56]
`let` is the poster child for declarative bindings
lolmaus [3:56 PM]
@mmun I consider extra indentation to be a price you have to pay for doing logic in templates. :smiling_imp:
I think I understand why inline let scares me. It makes Handlebars feel like JS. Where instead of defining HTML structures you write commands line by line.
mmun [3:57 PM]
to me the block form and the inline form are exactly equivalent
[3:57]
one just doesn't force an indent, but at the cost of lasting until the end of the scope
cowboyd [3:57 PM]
@lolmaus I originally wrote the addon with block form only.
mmun [3:57 PM]
if you want more scope-control then i would use the block form
cowboyd [3:57 PM]
and it was ok, and I was only lukewarm on the inline form
locks [3:57 PM]
Most langs with let don't allow multiple declarations
cowboyd [3:57 PM]
but once you accept it into your lexicon, it really disappears into the background in a way that the block form doesn't
mmun [3:58 PM]
that's not true.
[3:58]
most languages with `let` allow you to shadow previous bindings
[3:58]
JS is the exception
locks [3:58 PM]
:thinking_face:
[3:58]
What am I confusing it with then
mmun [3:58 PM]
```let a = 1;
let a = a*a;
```
[3:59]
i do this all the time in rust haha
locks [3:59 PM]
You are a bad person
mmun [3:59 PM]
no
locks [4:00 PM]
Good thing ember is a js fw then
mmun [4:00 PM]
I wouldn't use it in the example above
[4:00]
but in rust it's very useful
locks [4:01 PM]
Rust warns me about unused var :joy:
mmun [4:01 PM]
e.g. you can downcast a mutable reference to a immutable reference temporarily
[4:01]
for better type safety
locks [4:02 PM]
Ok, you can't rebind a non mut let, nvm
[4:02]
Two "let count = 0" is an error :thinking_face:
mmun [4:03 PM]
```fn main() {
let mut foo = vec![1,2,3];
let foo = &mut foo; // downcast ownership -> mutable reference
let foo: &Vec<_> = foo; // downcast mutable reference -> immutable reference
foo.sort(); // errors!
}
```
(edited)
cowboyd [4:09 PM]
imho, if someone sees `let` in handlebars and thinks “hmmm, what is this imperative construct doing here?” then there has already been a failure on the part of the community to communicate the essence of what handlebars is about. The first time I saw `let` in Haskell, i did not think “hmmm.... what is this imperative construct doing in haskell?” I thought instead “hmmm, how do I re-interpret my understanding of this construct to fit inside of a system free of side effects?" because for all its problem with messaging, they are crystal clear on this point: evaluation is _not_ imperative” The strength of the paradigm eliminated that interpretation.
[4:10]
I feel crystal clear about this in hbs
mmun [4:11 PM]
strong confirm
cowboyd [4:12 PM]
Unfortunately, it’s a very tricky thing to drive home this message and not come off like a cretin :slightly_smiling_face: (edited)
slackbot Custom Response [4:12 PM]
:explicitwarning: We'd love for this to remain an awesome place for all Emberers. Helps us out by editing that message. :point_up: https://github.com/cromwellryan/embercommunity-slack-guidelines/blob/master/CodeOfConduct.md
new messages
mmun [4:13 PM]
That paragraph felt good.
lolmaus [4:34 PM]
@cowboyd I was incorrect in understanding how inline let compiles. I believe, your RFC would really benefit from an example of how two inline lets on the same level are transformed.
cowboyd [4:35 PM]
I agree, but there’s the way it works currently in the addon, but there’s also the way it _ought_ to work of which I’m not as sure.
[4:36]
seems like the options are warn, error, or shadow.
locks [4:48 PM]
My vote is error since the others are silent
[4:48]
Error also potentially provides the most guidance
machty [5:48 PM]
how bout error when building for prod
[5:49]
actually, not sure which error you're referring to
[5:49]
but there was an example that came up the other day that would have been annoying if it'd error in dev
locks [6:15 PM]
@machty `{{let a=3}}{{let a=3}}` should error with binding already exists (or somesuch)
[6:15]
> SyntaxError: Identifier 'a' has already been declared
[6:15]
(node)
[6:16]
IMO shadowing (same scope) is confusing in templates
[6:16]
and a deprecation is still a silent error
[6:17]
unless you turn deprecation warnings into errors for production builds, but that's also annoying because it tells you about the problem at the 11th hour
machty [6:21 PM]
Yeah that seems reasomabe
[6:21]
Oh I remember what it was: someone proposed erroring when you don't end up using a let car
[6:21]
Var
locks [6:41 PM]
that seems more like a linting warning
cowboyd [10:54 PM]
While we’re on the subject of language semantics, just watched this short talk which has some pretty cool moments. Definitely has me wanting to try out Racket https://www.youtube.com/watch?v=TfehOLha-18
YouTube Racket Lang
(sixth RacketCon): Alexis King -- Languages in an Afternoon
(edited)
----- Today January 18th, 2017 -----
machty [9:10 AM]
that guy seems pretty legit
[9:10]
daring to futz w mirror displays mid prezo
[9:10]
also racket seems awesome
[9:11]
how does the racket platform compare to LLVM?
mmun [9:48 AM]
or ajax, for that matter?
machty [9:56 AM]
so what's up peoples
mmun [9:56 AM]
my (first) plane got delayed an hour (edited)
[9:57]
which makes me less mad about having a 1.5 hour layover
locks [9:57 AM]
data is up son
machty [9:57 AM]
thought that was actions
mmun [9:58 AM]
data up. new thing we’re trying
locks [9:58 AM]
actions are data
[9:58]
it's the new lisp era
[9:58]
`let` it wash over you and elevate you to new heights
machty [9:59 AM]
let it drift me rightward
locks [10:01 AM]
https://twitter.com/jessilikestech/status/821501700968058880 this is what monads get you
Jessi Aboukasm @JessiLikesTech
Hey @Twitter you might want to unwrap your Optionals before displaying them on the watch app :grimacing::see_no_evil: https://pbs.twimg.com/media/C2aPcPnUkAAkDzt.jpg
TwitterYesterday at 6:37 PM (14KB)
mmun [10:02 AM]
I prefer that
machty [10:02 AM]
i have a weird spider sense where convincing the powers that be to allow/add more powerful enhancements to Hbs syntax would be more successful if i made more racket comparisons than clojure comparisons
[10:03]
if there's anything i've learned since getting involved in Ember it's how to package imperfect/not-totally-fleshed-out-ideas for improvement in the language of some open source underdog
mmun [10:03 AM]
yeah. racket & Dijkstra/von Neumann quotes are more thought-leadery than clojure/rich hickey
[10:04]
referencing smalltalk is good too (edited)
machty [10:04 AM]
uploaded this image: Pasted image at 2017-01-18, 10:04 AM
Add Comment
machty [10:04 AM]
are these images supposed to mean anything
cowboyd [10:05 AM]
@locks @machty actions are data as they travel downwards
mmun [10:05 AM]
the “stable" one reminds me of graphs i learned in chaos theory
locks [10:06 AM]
I don't like batteries included
[10:06]
I have to wait for them to recharge instead of just swapping out
mmun [10:06 AM]
locks i dont think we can be friends
locks [10:06 AM]
:-1:
[10:06]
IDE? heavy. bigly.
[10:06]
mature? what is this, senior home, we need the blood of teenagers (literally)
[10:07]
the best of? compromise, weak
mmun [10:07 AM]
http://mathworld.wolfram.com/images/eps-gif/LogisticEquationBifurcation_850.gif (11KB)
locks [10:07 AM]
that looks like someone trying to puncture a zit
[10:07]
aka, amazing
mmun [10:08 AM]
it is amazing… but not for that reason
[10:09]
@machty ok here’s the thing
[10:09]
if compiled templates have the ability to bind arbitrary blocks (they might even already have this feature…) (edited)
[10:09]
you can actually just write your own lang on the glimmer vm
[10:09]
if only someone had designed a hbs alternative...
cowboyd [10:10 AM]
> if compiled templates have the ability to bind arbitrary blocks (they might even already have this feature…)
not fully following.
mmun [10:11 AM]
in glimmer, today, we have all the machinery to support yielding to arbitrary blocks
cowboyd [10:11 AM]
what is the interface for a “block” at the low level?
mmun [10:11 AM]
{{yield to=”inverse”}} turns into [‘yield’, someIntegerRepresentingTheBlock]
cowboyd [10:12 AM]
something that just returns some DOM?
mmun [10:12 AM]
it’s an array of “opcodes"
[10:13]
let me phrase it different
[10:13]
I suspect that you can craft a compiled template that has bound blocks
[10:13]
in the way that #let-block can bind blocks
[10:14]
that compiled template will not be something that the handlebars -> compiled template compiler can do
[10:14]
but it may be useful for experimenting
[10:15]
e.g. write some handlebars -> get a template -> monkeypatch the template before loading the app
cowboyd [10:18 AM]
monkey patch as in monkeypatch the opcodes?
mmun [10:19 AM]
yeah
[10:19]
the compiled template is just json
[10:19]
you can tweak it
[10:21]
(technically speaking, it’s not opcodes yet)
machty [10:21 AM]
oh i was thinking: there might be a way to experiment with this stuff by writing a broccoli plugin that converts anonymous blocks to anonymous files (edited)
rwjblue [10:21 AM]
joined #topic-forms
rwjblue [10:21 AM]
is this thing on?
locks [10:21 AM]
mic check
machty [10:21 AM]
i really want to make a proof of concept of the "component-centric" slots syntax
[10:21]
since i think i've only succeeded in convincing myself
[10:22]
but hacking that into broccoli *might* be easier?
mmun [10:22 AM]
i strongly suspect you’ll be able to hack the compiled templates
[10:22]
blocks are already first class objects in the runtime. they are even references
[10:22]
in the same way `foo.bar` is a PathReference
machty [10:23 AM]
hmm
mmun [10:23 AM]
hm, at least that used to be true. I could have sworn there was something called a BlockReference
machty [10:23 AM]
i don't think _I_ have enough context to knock that out
mmun [10:27 AM]
k i’ll try and hack something
machty [10:34 AM]
fudge
[10:34]
i was wrong about making this work with a broccoli hack
[10:34]
for obviously reasons in hindsight
[10:35]
it's gotta be at the glimmer layer
[10:35]
capturing blocks/scope
mmun [10:38 AM]
hm, blocks aren’t first class values at the compiled template level (edited)
machty [10:46 AM]
what are they?
mmun [10:57 AM]
Hard to explain but tldr there is two slots baked in for main/inverse blocks
[10:58]
Theres atill hope. It will just be a bit trickier
machty [11:03 AM]
i'd like to discuss component-centric slot syntax further with anyone interested
mmun [11:07 AM]
The table/column usecase is important to me
[11:08]
I will try and come up with a more complex example where slots might break down.
[11:08]
:airplane_departure:
machty [11:08 AM]
you want an API for you use "slots" to essentially define the schema of the table?
mmun [11:09 AM]
I want to define header/main/footer cells for each column (edited)
[11:09]
And not worry about doing an each loop myself
[11:10]
Cuz then it can use smoke and mirrors under the hood or whatever (edited)
machty [11:12 AM]
smoke-and-mirrors the addon?
mmun [11:12 AM]
Yeah
[11:12]
In case your table is very large
[11:13]
Its not an actual problem i have atm but i believe that sort of abstraction should be possible...
[11:14]
In react the solutions are very clear for this :p
[11:15]
You could just pass an array of { headerComponentClass, bodyComponentclas, footerComponentclas }
[11:16]
Same is true in ember i guess
[11:17]
The issue is just that the extra files are annoyong i suppose
[11:17]
I tgibk i see what you mean. Taking off now
machty [11:22 AM]
JSX elegantly weaves in and out of JS/JSX nesting
[11:23]
which makes it easy to express all of those cases
[11:24]
the inability to weave in and out of {{}}/DOM syntax screws us over (edited)
[11:26]
`{{x-foo template=(|foo| <div>Hello I am {{foo.title}}</div>)}}`
[11:27]
in JSX it's
[11:27]
```<XFoo template={ foo => {
return <div>Hello I am { foo.title }</div>;
} }/>
```
[11:27]
can't say it's beautiful but it works today and according to "Just JS™" rules that everyone understands
[11:28]
if you wanted to pass in arrays of { headerComponentClass, bodyComponentclas, footerComponentclass }:
[11:30]
```<XTable columns={ [
{
header: data => <span>{ data.wat }</span>,
body: data => <span>{ data.wat }</span>,
footer: data => <span>{ data.wat }</span>,
},
{
header: data => <span>{ data.wat }</span>,
body: data => <span>{ data.wat }</span>,
footer: data => <span>{ data.wat }</span>,
},
{
header: data => <span>{ data.wat }</span>,
body: data => <span>{ data.wat }</span>,
footer: data => <span>{ data.wat }</span>,
},
] }/>
```
machty [11:34 AM]
uploaded this image: Pasted image at 2017-01-18, 11:34 AM
Add Comment
cowboyd [11:34 AM]
yep. This is why I feel that hbs has got to evolve some pretty big superpowers in order to remain a compelling alternative. “Separation of logic” is not an end unto itself.
locks [11:34 AM]
hbs isn't exactly about separation of logic
cowboyd [11:36 AM]
https://media.giphy.com/media/ljaDzjv8cpIpa/giphy.gif (Not automatically expanded because 10MB is too large. You can expand it anyway or open it in a new window.)
[11:36]
(agree)
[11:37]
100%
[11:38]
But I think there is a large conception that "separation of logic" is an end unto itself and I think its harming handlebars’ prospects.
[11:38]
I think “elimination of side-effects” is a worthy goal
[11:39]
but so many of the scars that we all got from ERB and liquid templates, can’t happen in handlebars because of the way it’s built.
machty [11:39 AM]
yeah
[11:39]
that JSX template is side-effect free (edited)
[11:40]
i feel like there _should_ be a way to represent that in HBS
cowboyd [11:41 AM]
and furthermore, experimenting with different approaches shouldn’t require changes to the compiler.
[11:42]
JSX can do this because it has a way to express simple abstractions.
machty [11:42 AM]
glimmer capitalizes on efficient rerendering of the known-to-be-static bits
[11:43]
+ the ability to know which piece of data changed
[11:43]
which further narrows down the computations involved to figure out what changed / what needs to be re-rendered
[11:43]
Inferno JSX already does the first part of that
[11:44]
JSX is "just JS" but you can still parse a JSX template and tell what the static bits are
[11:44]
so it's not like that's a feature unique to the handlebars syntax
[11:45]
man
[11:45]
there are so many crappy strawman arguments against JSX
samselikoff [11:46 AM]
its hard to take an unbiased look at everything
[11:47]
could you have done glimmer rewrite with jsx? Did hbs give them certain guarantees that made it possible to do that? I mean that was a big win for a lot of apps
machty [11:49 AM]
i don't think anyone's suggesting it should have been on top of jsx
machty [11:51 AM]
added this Plain Text snippet: nested handlebars syntax?
curly style
{{x-table columns={{ (array
(hash
header=(|data| <span>{{data.wat}}</span>)
body=(|data| <span>{{data.wat}}</span>)
footer=(|data| <span>{{data.wat}}</span>)
)
(hash
header=(|data| <span>{{data.wat}}</span>)
body=(|data| <span>{{data.wat}}</span>)
footer=(|data| <span>{{data.wat}}</span>)
)
(hash
header=(|data| <span>{{data.wat}}</span>)
body=(|data| <span>{{data.wat}}</span>)
footer=(|data| <span>{{data.wat}}</span>)
)
) }} }}
or glimmer style:
<x-table columns={{ (array
(hash
header=(|data| <span>{{data.wat}}</span>)
body=(|data| <span>{{data.wat}}</span>)
footer=(|data| <span>{{data.wat}}</span>)
)
(hash
header=(|data| <span>{{data.wat}}</span>)
body=(|data| <span>{{data.wat}}</span>)
footer=(|data| <span>{{data.wat}}</span>)
)
(hash
header=(|data| <span>{{data.wat}}</span>)
body=(|data| <span>{{data.wat}}</span>)
footer=(|data| <span>{{data.wat}}</span>)
)
) }} />
Add Comment Collapse
cowboyd [11:52 AM]
@machty I like the idea of `(|x| )` for lambda abstraction over values, `{|x| }` for lambda abstraction over DOM (edited)
machty [11:53 AM]
added this Plain Text snippet: with [] and (key=value) array/hash literals
<x-table columns={{ [
( header=(|data| <span>{{data.wat}}</span>)
body=(|data| <span>{{data.wat}}</span>)
footer=(|data| <span>{{data.wat}}</span>)
)
( header=(|data| <span>{{data.wat}}</span>)
body=(|data| <span>{{data.wat}}</span>)
footer=(|data| <span>{{data.wat}}</span>)
)
( header=(|data| <span>{{data.wat}}</span>)
body=(|data| <span>{{data.wat}}</span>)
footer=(|data| <span>{{data.wat}}</span>)
)
] }} />
Add Comment Collapse
cowboyd [11:53 AM]
`header={|data| <span>{{data.wat}}</span>}`
machty [11:53 AM]
@cowboyd interesting...
[11:56]
that would mean `<x-foo someDom={{{hey i am a text fragment}}}/>`
cowboyd [11:57 AM]
Yeah, or `<x-foo someDom={{{|| hey i am a text fragment}}}/>`
[11:57]
I guess it wouldn’t be ambiguous, I think @mmun has thoughts on this.
locks [11:59 AM]
dear god
machty [12:00 PM]
@locks tellme
locks [12:01 PM]
just general change anxiety
samselikoff [12:01 PM]
it is a lot
cowboyd [12:01 PM]
but it is actually so little
locks [12:01 PM]
seems very pro-oriented
cowboyd [12:02 PM]
JSX: pro-oriented?
samselikoff [12:02 PM]
(not really fair for me to comment, ive been in and out of the convo)
cowboyd [12:02 PM]
totes fair
[12:02]
all is fair in love and Ember
locks [12:02 PM]
@samselikoff that hasn't stopped me :troll:
machty [12:03 PM]
here's the thing, cowbody and i post our hamstrung syntaxes that look like terse pro-user features, but what's missing are the comparisons with today's solutions involving multiple files and passing of attrs / data that would be elegantly solved by having a lambda syntax
[12:04]
:cow:
samselikoff [12:04 PM]
yes
[12:04]
would be great to have a single use case that's really hard right now
[12:05]
well there's a lot going on in the convo right. one is js/hbs split for simple things, and if that's good or bad
[12:05]
other is, missing primtiives that make certain things hard/difficult
[12:06]
ryan and i were talking yesterday. is `{{let hasStatus=(bool user.status)}}` better than `hasStatus: Ember.computed.bool('user.status')`
[12:06]
```{{let isOpen=(eq a b)}}
{{let isNew=(eq c d)}}
{{let isActive=(and isOpen isNew)}}
...
<a class={{if isActive 'active'}}>Foo</a>
```
[12:07]
i think this is one piece of the convo. whether the split is better or worse
cowboyd [12:08 PM]
https://embercommunity.slack.com/archives/topic-forms/p1484759175001848
We all know where I stand on the matter :slightly_smiling_face:
samselikoff
ryan and i were talking yesterday. is `{{let hasStatus=(bool user.status)}}` better than `hasStatus: Ember.computed.bool('user.status')`
Posted in #topic-formsToday at 12:06 PM
samselikoff [12:08 PM]
:slightly_smiling_face:
[12:08]
well once the truth helpers came, I mean
[12:08]
`{{if (eq a b) 'active'}}`
rwjblue [12:08 PM]
btw, @cowboyd thank you for writing the RFC :slightly_smiling_face:
samselikoff [12:08 PM]
I do this all the time now. I think its better
[12:08]
what about `(eq (or (and a b) (and c d)))`? idk
cowboyd [12:09 PM]
that’s why you need let ^^
samselikoff [12:09 PM]
and once it gets to that point, should it be at top of hbs template like ^ or moved to a JS CP
rwjblue [12:09 PM]
aye, giving it a name makes it much much better
[12:09]
and basically no different than JS CP (IMO)
[12:10]
the only reason it is better in JS is that you get to give it a name
[12:10]
and `let` lets you do that just fine
[12:10]
(pun intended)
cowboyd [12:10 PM]
```{{let x=(and a b) y=(and c d)}}
<div attr={{or x y}}></div>
```
(edited)
[12:10]
@samselikoff see how a dragon becomes a teddy bear ^^
samselikoff [12:10 PM]
hehe
locks [12:10 PM]
that's literally code from your projects isn't it
samselikoff [12:11 PM]
is this harder for newbies, like now they have to learn good programming practices in nearly two languages
locks [12:11 PM]
they already did
samselikoff [12:11 PM]
is it harder for designers looking at templates? (does that matter?)
locks [12:11 PM]
that's a trick question
[12:11]
it matters :P
samselikoff [12:12 PM]
also if all these constructs are more for lib authors than app developers
[12:12]
i mean i work mostly with app developers. the mistakes their making are nowhere near this stuff you know
[12:12]
none of the programmers ive mentored have said "you know i really need a lambda in my template"
cowboyd [12:13 PM]
I bet they have
[12:13]
although they did not express it in that way
[12:13]
You wouldn’t teach JSX without functions, and people manage to learn it somehow.
[12:14]
This is programming, and no matter where you run, the need for functions will find you.
locks [12:14 PM]
you cna't function otherwise
cowboyd [12:14 PM]
:tophat:
machty [12:15 PM]
added this Plain Text snippet: nested DOM/hbs syntax and slots
If we were able to infinitely nest HBS/DOM syntax (like you can in JSX), then we wouldn't even need to define a proprietary new syntax specific to "slots" or "named yields".
<x-foo slots={{ (hash
header=(|data| <h1>{{data.foo}}</h1>)
body=(|data| <h1>{{data.foo}}</h1>)
footer=(|data| <h1>{{data.foo}}</h1>)
) }} />
Add Comment Collapse
machty [12:16 PM]
also I believe Yehuda proposed a _similarish_ strawman syntax to @mmun not long ago...
cowboyd [12:17 PM]
I still think you need different syntax for values and DOM
machty [12:19 PM]
that's fine, i'd file that under bikeshed though
cowboyd [12:19 PM]
yeah, don’t want to detract from your point which is a fine one :slightly_smiling_face: (edited)
machty [12:19 PM]
mostly just want to convince people that JSX works for a reason
[12:19]
n00bs understand JSX
[12:19]
React has proven this
cowboyd [12:20 PM]
truth
[12:21]
Because you end up having to teach _less_ in the long run
[12:22]
as you need less one-off mechanisms to address specific use-cases
samselikoff [12:22 PM]
> as you need less one-off mechanisms to address specific use-cases
i can totally buy this
machty [12:23 PM]
slot syntax is a scenario solve
cowboyd [12:31 PM]
block re-use comes for free:
```{{let header=(|data| {{data.foo}})}}
<x-foo mode=x header=header>
<x-foo mode=y header=header>
<x-foo mode=z header=header>
```
locks [12:32 PM]
when is `data` captured?
cowboyd [12:32 PM]
when `x-foo` yields to it
locks [12:33 PM]
inside x-foo `{{header pieceOfData}}`?
cowboyd [12:33 PM]
yuh-huh
locks [12:34 PM]
ok, it doesn't capture from outer scope?
cowboyd [12:34 PM]
it does,
locks [12:35 PM]
hm.
cowboyd [12:37 PM]
I’m sure what exactly was “captured” would be up for no small amount of discussion, but I’d expect:
```{{let header=(|data| {{this.name}} {{data.foo}})}}
<x-foo mode=x header=header>
<x-foo mode=y header=header>
<x-foo mode=z header=header>
```
to work
[12:38]
or maybe you exclude dynamic scope and only capture lexical scope
[12:38]
```{{let name=this.name}}
{{let header=(|data| {{name}} {{data.foo}})}}
<x-foo mode=x header=header>
<x-foo mode=y header=header>
<x-foo mode=z header=header>
```
mmun [12:41 PM]
I use let when i have multiple moment-format that i want to format the same way in a single template
machty [12:42 PM]
@cowboyd what is `{{this.name}}` even referring to? (edited)
mmun [12:42 PM]
{{let dateFormat="DD YYYY"}}
[12:43]
Btw love everything machty and cowbody are putting down in the last hour
cowboyd [12:46 PM]
@machty YIL https://embercommunity.slack.com/archives/topic-forms/p1484683316001513
cowboyd
Like in your twiddle, you used `this.person` I wasn’t aware that was a thing.
Posted in #topic-formsYesterday at 3:01 PM
machty [12:46 PM]
ah
[12:46]
tie-breaker
[12:46]
yeah i definitely think lexical is the way to go
[12:47]
it behaves the same as if you moved the contents outside of that anonymous block
[12:47]
(other than the missing block param)
[12:48]
this wins an award https://embercommunity.slack.com/archives/topic-forms/p1484760663001900
cowboyd
block re-use comes for free:
```{{let header=(|data| {{data.foo}})}}
```
Show more…
Posted in #topic-formsToday at 12:31 PM
[12:49]
i want this so bad
[12:49]
i'm going to cry if it hits a dead end and we end up shipping toys for noobs instead
cowboyd [12:50 PM]
me too
machty [12:52 PM]
i think glimmer/hbs syntax has conceptual integrity to it
[12:52]
it's a declarative syntax
[12:53]
that makes it possible for the rendering engine to understand where data is changing
[12:53]
in a way that wouldn't be possible with JSX
[12:53]
and we should make it as awesome as it should be within those bounds
samselikoff [12:54 PM]
youre saying that block/lambda doesn't go outside of those bounds, bc you can't do anything you want within the body of the lambda?
machty [12:55 PM]
you can't do anything side-effecty / nondeclarative period, and introducing lambda syntax doesn't violate that in any way
samselikoff [12:55 PM]
```{{let header=(|data| {{ Ember.run.scheduleOnce }})}}
```
[12:55]
right
machty [12:55 PM]
i don't want that
[12:55]
we can consider opening that door in a separate RFC
samselikoff [12:55 PM]
right your mental model there is still, declarative transforms
[12:55]
i see how block/lambba doesnt really change that
machty [12:56 PM]
yeah
samselikoff [12:56 PM]
basically, when your writing your templates
[12:56]
and you need to jump back to JS just to do CPs
[12:56]
95% of hte time you're trying to transform data
[12:56]
"massage" as they say, into a form suitable for your ui
machty [12:57 PM]
we had some other examples the other day where lambda syntax could actually replace a lot of one-off helpers
samselikoff [12:57 PM]
if you could keep that stuff in hbs, could be an improvement
[12:57]
(whereas, some complicated polling task that happens on component init, maybe more suitable for a JS function?)
machty [12:58 PM]
yeah
[12:58]
for sure
[12:58]
nothing about today's insights make me want to move EC / state mgmt stuff into the template
[12:58]
(though @cowboyd's microstates gets close to that arena)
cowboyd [1:02 PM]
microstates is just about using type information to infer the implicit actions for a piece of data
[1:03]
the state management is still handled in JS
[1:03]
but you can declaratively map events to _transitions_ in hbs (edited)
machty [1:04 PM]
gotcha
new messages
cowboyd [1:06 PM]
for reference: https://github.com/cowboyd/ember-microstates
machty [1:04 PM]
gotcha
cowboyd [1:06 PM]
for reference: https://github.com/cowboyd/ember-microstates
machty [1:10 PM]
set the channel topic: poorly named room to discuss (possibly missing) patterns of composition in Ember. Backlog manually persisted here:
https://gist.github.com/machty/68afad4c03109f36d4f4cffaae3c170b
mmun [1:11 PM]
declarative-all-the-things is a pretty big step. i would probably just move to elm or something functional (edited)
[1:11]
declarative templates isn't
[1:14]
@cowboyd: i assume you mean `<x-foo mode=x header={{header}}>` and not `<x-foo mode=x header=header>`
cowboyd [1:14 PM]
yes
[1:15]
I’d mean `x` to be a variable too.
mmun [1:15 PM]
a while ago yehuda was musing with me if we could get away with `<x-foo mode=x header={header}>` :stuck_out_tongue:
[1:15]
double curlies is so heavy :’(
cowboyd [1:31 PM]
Congratulations everybody! I think we’re officially back on topic if we re-parse `forms` to mean syntactic forms.
locks [1:31 PM]
forms of programming
[1:32]
why aren't we in #topic-architecture again? :P
cowboyd [1:33 PM]
inertia, momentum, or both.
mmun [1:33 PM]
lol
machty [1:35 PM]
topic-architecture is too open ended
[1:36]
i think we all realized there was some fundamental missing stuff related to forms/composability/higher order components
[1:37]
i think i'm bout ready to yank my let-block rfc
[1:37]
in favor of nested DOM/block/lambda RFC in conjunction w inline-let RFC
mmun [1:41 PM]
for the
*VERY*
ambitious
locks [1:41 PM]
fcp let
[1:42]
I'll deprecate with (sorry @lolmaus)
[1:42]
and we take over ember with our lispiness
cowboyd [1:42 PM]
*LoL*
let over lambda is all you ever need
locks [1:42 PM]
"shtop in the name ov lishp"
machty [1:43 PM]
that's more sean connery's speech impediment
mmun [1:43 PM]
the `let` rfc needs a little more time to :stew: (edited)
locks [1:43 PM]
doubt we have consensus anyway :P
machty [1:44 PM]
nested DOM/block/lambda syntax ain't dependent on it. can use `#with` or `ember-let` (edited)
locks [1:44 PM]
did we agree on erroring for multiple declarations of same var in same scope?
cowboyd [1:44 PM]
yup.
mmun [1:45 PM]
I am OK with that rule.
[1:45]
It should not come often in practice anyways.
locks [1:45 PM]
and the binding is only accessible from the declaration downwards? (aka, my last in-thread comment is correct)
mmun [1:46 PM]
We can also suggest a refactoring (in the RFC): If you _really_ want to bind the same name twice, then make the lifetime of the name explicit by using a let-block
locks [1:47 PM]
yy
[1:47]
and if you want to nest, it shadows
[1:48]
what about derived bindings?
[1:48]
`+{{let* a=1 b=(sum a 5)}} <!-- `b`'s binding expression sees `a` -->` in the rfc
[1:49]
```{{let a=1}}
{{let b=(sum a 5)}}
```
?
mmun [1:49 PM]
I don't know. It may be helpful to grep some clojure codebases to get a sense of how common it is
[1:50]
Personally I think it's fine to additionally support `let*`, but I don't want to complicate getting inline-let merged :stuck_out_tongue: (edited)
locks [1:50 PM]
I think I use it in what little clj code I have :joy:
[1:51]
not sure I'm comfortable with that semantic change post-doc
mmun [1:51 PM]
that is not an option
[1:51]
we don't break userspace!
machty [1:51 PM]
it (derived/serial bindings) is extremely common in clj (edited)
miguelcobain [1:52 PM]
joined #topic-forms
mmun [1:52 PM]
let should absolutely have clj-let semantics.
locks [1:52 PM]
oohh, you mean literally `let*`
mmun [1:52 PM]
yes
cowboyd [1:53 PM]
`let*` would just be another transform of block `let`
mmun [1:53 PM]
originally I implemented ember-let as let* (not knowing about let & let* in clj), but Charles convinced me otherwise.
locks [1:53 PM]
can't find `let*` in clj docs
machty [1:53 PM]
i don't think `let*` is clojure
locks [1:53 PM]
ok
[1:54]
clj-let just has those semantics already
cowboyd [1:54 PM]
it’s in scheme, CL and elisp
machty [1:54 PM]
the clj syntax is `(let [x 'xValue' y 'yValue'] ...)`
[1:54]
if you wanna binding one thing just do `(let [x 'xValue'] ...)`
locks [1:54 PM]
hey, if we're going down this road we should go for broke :P
mmun [1:54 PM]
well, I'll let @cowboyd make the argument (edited)
cowboyd [1:55 PM]
@machty `let*` is a bout sequential vs parallel binding
mmun [1:55 PM]
`{{let a=1 a=(mul a a)}}`
machty [1:55 PM]
when would they ever behave differently?
mmun [1:55 PM]
^ that is a weird thing to do in hbs
[1:56]
can you do that in CL? (define the same name twice) (edited)
machty [1:56 PM]
```user=> (let [a 2 a (* a a)] a)
4
```
mmun [1:56 PM]
i c
locks [1:57 PM]
www.tryclj.com for future discussions
cowboyd [1:57 PM]
So Clojure is `let*` all day (edited)
locks [1:57 PM]
c
cowboyd [2:04 PM]
Same example in scheme:
```scheme@(guile-user)> (let ((a 1) (a (* a 2))) a)
;;; <stdin>:6:15: warning: possibly unbound variable `a'
<unnamed port>:6:0: In procedure #<procedure 107f5fb80 at <current input>:6:0 ()>:
<unnamed port>:6:0: In procedure module-lookup: Unbound variable: a
Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue.
scheme@(guile-user) [1]> (let* ((a 1) (b (* a 2))) b)
$3 = 2
scheme@(guile-user) [1]> (let* ((a 1) (a (* a 2))) a)
$4 = 2
scheme@(guile-user) [1]>
```
mmun [2:07 PM]
```(defun foo (a b)
(let ((a (max a b))
(b (min a b)))
```
[2:08]
that is totally something i've done in rust
[2:08]
`let (a, b) = (min(a,b), max(a,b));`
[2:09]
while let* can be convenient I ultimately think we should use the weaker construct
knownasilya [2:11 PM]
joined #topic-forms
knownasilya [2:12 PM]
@machty what's the alternative to your RFC?
machty [2:15 PM]
@knownasilya something like this https://embercommunity.slack.com/archives/topic-forms/p1484760663001900
cowboyd
block re-use comes for free:
```{{let header=(|data| {{data.foo}})}}
```
Show more…
Posted in #topic-formsToday at 12:31 PM
[2:15]
glimmer syntax that allows zipping in and out of glimmer/dom syntax
[2:15]
so that we can pass in things as attrs
machty [2:20 PM]
so i'm gonna go ahead and talk about "component-centric slots" in the context of these new ideas
[2:20]
because i think it's an opportunity for conventions and structure that ember can provide where other frameworks might lack (edited)
knownasilya [2:27 PM]
sweet.
[2:27]
I'm not a fan of the syntax, but that's secondary
lukemelia [2:33 PM]
joined #topic-forms
machty [2:35 PM]
player 2 has entered the game
machty [2:48 PM]
ok, well i'm stuck again so i'll share my thought process
machty [2:49 PM]
added this Markdown (raw) snippet
Here's a component that renders components passed into it.
Due to today's limitations, these components have to live in
separate files, and any data that those components need to
do their job must be explicitly passed in (e.g. x y and z).
```hbs
{{x-foo
header=(component 'x-header' data=(hash x=x y=y z=z))
body=(component 'x-body' data=(hash x=x y=y z=z))
footer=(component 'x-footer' data=(hash x=x y=y z=z))
}}
```
This implies that `x-foo`'s layout template was using the
`{{component}}` helper to render these components-passed-as-attrs:
```hbs
{{! x-foo's layout template }}
{{component header bar=123}}
{{component body bar=123}}
{{component footer bar=123}}
```
Let's say we add some JSX-style syntax where we make easy
to pass in a template block as an attr. Let's just start
with `footer` for now (actual syntax for inline template
blocks is in bikeshed territory outside the point I'm trying
to make):
```hbs
{{x-foo
header=(component 'x-header' data=(hash x=x y=y z=z))
body=(component 'x-body' data=(hash x=x y=y z=z))
footer=(|data|
<p>
I used to have to live in another file but
now I can just live here! Yay!
{{x}} {{y}} {{z}}
Look ma, no excessive attr passing!
I work just like classic blocks that
close over the current scope!
What about data passed in from x-foo?
How about: {{data.bar}}
</p>
)
}}
```
Add Comment Collapse
dfreeman [2:49 PM]
joined #topic-forms
machty [2:50 PM]
questions / comments on the above:
[2:51]
1. It'd be awesome if the above refactor didn't require making any changes to `x-foo`; what used to be renderable with `{{component attrName}}` is still renderable with `{{component attrName}}`
[2:51]
2. But since it's still rendering with `{{component}}`, should it be wrapped in a tag, or should there be implicit `tagName: ''`?
[2:53]
3. What is `|data|`? It _could_ just be a hash of merged attrs, OR we could consider it just making it the anonymous instance of Ember.Component that's rendering that template block, in which case it'd still represent the merged hash of attrs and be consistent with the classic `{{component}}` API
mmun [2:54 PM]
I disagree with the premise
[2:54]
And sorry for drive by pooping... About to take off again
machty [2:55 PM]
4. The reason I don't want to just extend the `{{yield}}` API here (to allow you to just `{{yield a b c to=someBlockAttr}}` is that we'd be fragmenting the world between things that accept an attr hash (components) and things that render with positional params (yield)
mmun [2:56 PM]
Agreed. If anyrhing block sbould be coercible to component
machty [2:56 PM]
If we extended yield. then we couldn't support swapping between `attr=(component 'x-footer')` and `attr=(|data| <div></div>)`
mmun [2:56 PM]
And invokable via {{component}}
machty [2:58 PM]
@mmun but would we still support `{{yield a b c to=someBlockAttr}}` ?
mmun [2:58 PM]
Unclear.
[2:58]
Also i would expect the block argument to be attrs but i think we agree there
machty [2:58 PM]
if you do, then we'll have to explain to the world when/why you'd write a component whose API either expected blocks with `|data|` or blocks with `|positional params|`
cowboyd [2:59 PM]
wouldn’t it make the most sense to have blocks just take attrs too?
[2:59]
`{|a b c= d=| {{a}} {{b}} {{c}} {{d}}}` (edited)
mmun [2:59 PM]
Yes
[3:00]
Its confusing syntax thoug
machty [3:00 PM]
keep in mind the ideal goal of being able to quickly switch `attr=(component 'x-footer')` and `attr=(|data| <div></div>)`, back and forth
mmun [3:00 PM]
You need to choose a local binding name (edited)
machty [3:00 PM]
and if you make it easy/possible/common to yield with positional params, then you can 't do that without dipping into esoteric `positionalParams` API
mmun [3:01 PM]
Import { foo } vs import { foo as bar }
[3:01]
Machty you raise good points. I will ponder it
machty [3:01 PM]
additionally, it's not uncommon to for a component like `x-foo` to forward its component-y attrs to yet another component, so THAT component would also need to agree on the API
mmun [3:02 PM]
There is a simple solution to just go all in with lambdas
cowboyd [3:02 PM]
remind me why simplying saying `{{attr data name='value'}}` (inside body of x-foo) doesn’t work again? I feel like I keep asking the same question. (edited)
machty [3:03 PM]
because what is `data` when you go back to using `attr=(component 'x-foo')`
[3:03]
how does `x-foo` access it without using `positionalParams` api
mmun [3:04 PM]
`attr=(|data| {{x-footer ...=data}})`
machty [3:05 PM]
so we should name that solution "write your own translation layer whenever you want to use `{{yield}}`"
mmun [3:06 PM]
Catchy
machty [3:06 PM]
i predict Translation Layers Everywhere if we open that pandoras box
[3:06]
lol
[3:06]
hahaha
[3:07]
wherein machty fails to out-pedantic mmun
[3:08]
but anyway, yeah, that's my hunch. if we open that pandora's box, then people will have to write these anonymous blocks to translate between something that wants to yield positional params vs pass named attrs
[3:08]
and sure you could probably conceive of some helper/component to aid in that translation
mmun [3:08 PM]
Yeah
machty [3:08 PM]
(but that sucks)
cowboyd [3:13 PM]
so if I understand: a block could be easily made to masquerade as a component, but not vice-versa, so we want to shoot for the lowest common denominator for yielding, which is the `{{component}}` api.
[3:13]
i.e. named parameters only.
[3:16]
slight, but potentially unifying scope creep would be to beef up positional parameters for a component to make them low-friction
[3:16]
seems like you want two things: the ability to access them in a conventional way without having to explicitly declaring the mapping in your `.js` file
[3:17]
so that you can use them in your templates and from js
machty [3:17 PM]
yeah, not to mention i don't think lots of people should have to know about positionalParams, AND the api for it is weird (you have to reopenClass)
[3:18]
i really don't think the benefits are worth beefing up pos params syntax (edited)
cowboyd [3:18 PM]
the benefit is that you now have parity between the component-centric and block-centric apis
[3:19]
which means from the perspective of composition, 1 mental model instead of 2
[3:19]
which seems pretty huge, unless I’m missing something.
machty [3:19 PM]
yeah
[3:20]
i think we're on the same page
[3:20]
unfortunately, there are 2 mental models today
[3:20]
{{yield}} and {{component}}
[3:20]
i just want to standardize on one
[3:20]
if one should be a relic of the past, it should be yield
[3:21]
i made this point in a separate room, but i think JSX has this weakness; when you nest elements, it sets `this.children` prop on the component
[3:21]
but once you wanna passed multiple named "blocks", you no longer use `this.children`
[3:22]
you use something that "feels" a little different
[3:22]
(this is a minor / weak point; just wanted to highlight that it's not specific to ember/component/yield)
cowboyd [3:27 PM]
So you would rather see the complete external/internal scenario like this:
anonymous block
```{{let header=(|data=| {{data.foo}})}}
<x-foo mode=x header={{header}}>
<x-foo mode=y header={{header}}>
<x-foo mode=z header={{header}}>
```
external component:
```{{let header=(component 'external-header' other-prop="something-else"})}}
<x-foo mode=x header={{header}}>
<x-foo mode=y header={{header}}>
<x-foo mode=z header={{header}}>
```
inside `x-foo` template:
```{{component header data=(hash foo='bar')}}
```
(edited)
machty [3:28 PM]
correction: `{{component header foo='bar'}}`
[3:29]
(what's `other-propr`? positional param?)
cowboyd [3:30 PM]
wait, so the block would get a single positional param which was the attrs passed to the component API?
[3:32]
I was assuming an extended block param syntax to bind nv pairs
machty [3:32 PM]
one sec
cowboyd [3:32 PM]
`{{let header=(|foo=| {{foo}})}}`
machty [3:37 PM]
yeah
[3:38]
single positional param of attrs
[3:40]
i'd be happy to add a destructuring syntax for that
[3:41]
so i have one last idea to share
[3:41]
the final piece of the puzzle
[3:42]
but i'll wait on that
cowboyd [3:43 PM]
Love the idea of a uniform api. Don’t love it being named `component` since that would officially be a lie.
machty [3:43 PM]
or is it
cowboyd [3:44 PM]
I suppose if you wrap it in an anonymous component it wouldn’t be.
[3:47]
but it still would be a lie from the user’s perspective _unless_ we called them anonymous components instead of anonymous blocks.
[3:48]
in the expression `{{let header=(|attrs| {{attrs.foo}})}}`, `header` is an anonymous component full stop.
machty [3:49 PM]
i might be ok with that
[3:50]
i guess it comes down to whether there's some other non-component-y way to render such a block
[3:50]
i can't think of one
cowboyd [3:50 PM]
So what about the case where the component _does_ have positional params?
[3:50]
oh right, in components, positional params always have to be mapped.
[3:51]
so you can always render with named params
machty [3:52 PM]
yeah
[3:52]
so one big open question that's related to my "final piece of the puzzle" is if/when/whether to allow subclasses of Ember.Component
cowboyd [3:53 PM]
that’s easy: `(|attrs|->extends(Compo-nant) {{attrs.foo}})`
machty [3:54 PM]
we've been using `|attrs|` in our examples but it _could_ literally just be a reference to a component instance
locks [3:54 PM]
jc
[3:54]
this channel is bad for my health
machty [3:54 PM]
Keep Calm and Remember Yehuda Proposed Inline Hbs Syntax at One Point
locks [3:55 PM]
yehuda can be wrong too :troll:
cowboyd [3:56 PM]
@locks I feel you :slightly_smiling_face: this is the nerd equivalent of fear and loathing in Las Vegas
machty [3:56 PM]
damn has that excuse worn thin?
locks [3:56 PM]
btw, I was checking some random ember stuff
cowboyd [3:57 PM]
but it’s good for you in the long run
locks [3:57 PM]
and I saw something from you telling someone else to not worry about query params, that they were moving to the route soon
machty [3:57 PM]
i said that?
locks [3:57 PM]
yeah
[3:57]
on the blog comments
machty [3:57 PM]
i wouldn't be surprised if i did
[3:57]
oh to the route
[3:57]
i thought they were
locks [3:58 PM]
we all did at one point
[3:58]
when routable components were months away
machty [3:58 PM]
(how's this relevant?)
locks [3:58 PM]
it isn't, I just remembered
[3:58]
having public records is awesome for spelunking
cowboyd [3:58 PM]
https://embercommunity.slack.com/archives/topic-forms/p1484772843002157
machty
we've been using `|attrs|` in our examples but it _could_ literally just be a reference to a component instance
Posted in #topic-formsToday at 3:54 PM
[3:59]
curious where you were about to go with this ^^
machty [3:59 PM]
right
[3:59]
well first off it's interesting/of note that if we made it a component instance the api would be the same
[3:59]
just that you might also be able to access properties on component instance (edited)
[3:59]
which is maybe a smell if it's just Ember.Component
[4:00]
but if we made it possible to use a component.js class but with BYO template, it'd might be a nice pattern (edited)
[4:00]
component can expose properties / things / actions / tasks (edited)
locks [4:00 PM]
container component style?
machty [4:00 PM]
maybe, is that defined somewhere?
cowboyd [4:02 PM]
kinda like a template “mixin” ?
locks [4:03 PM]
in react literature, but I mean a component with just `{{yield …}}` for a template
cowboyd [4:03 PM]
right. the pattern of having a component whose only job is to present data to sub components.
[4:04]
@machty How would you specify the component superclass in a template?
machty [4:05 PM]
```{{media-player
tracklist=(|c|
<ul>
{{#each c.tracks as |t|}}
<li class="track">{{t.title}}</li>
{{/each}}
</ul>
<button onclick={{t.togglePlay}}>
{{if t.isPlaying 'Pause' 'Play'}}
</button>
)
}}
```
[4:05]
this _seems_ like a nice API, regardless of whether it's implemented using this approach or not
[4:06]
(this approach of specify the class but BYO template)
[4:06]
in this case it'd be up to `media-player` to specify the component.js class
[4:06]
this is also a la trek style component extendability / overridabilty (edited)
cowboyd [4:06 PM]
How is this different than:
```{{#media-player as |c|}}
<ul>
{{#each c.tracks as |t|}}
<li class="track">{{t.title}}</li>
{{/each}}
</ul>
<button onclick={{t.togglePlay}}>
{{if t.isPlaying 'Pause' 'Play'}}
</button>
{{/media-player}}
```
(edited)
machty [4:07 PM]
it's only different when you selectively override multiple different parts
webark [4:07 PM]
joined #topic-forms
machty [4:07 PM]
`{{yield}}` only becomes a crappy API once you need to yield more than one thing
cowboyd [4:08 PM]
you could even steal a play from ES6 modules’ book.
alexander-alvarez [4:08 PM]
joined #topic-forms
machty [4:08 PM]
i guess my example wasn't clear: you're rendering a `media-player`, which renders lots of things, including a tracklist, that you can individually swap out with your own thing
cowboyd [4:08 PM]
right
[4:09]
to continue the es6 analogy, you could even say something like `{{yield}}` is equivalent to `{{component default}}`
[4:09]
not that it’s a requirement, but just trying to rif on the underpinnings of what you’re proposing (edited)
machty [4:10 PM]
sure, though maybe better to avoid the yield comparisons since then you have to think/talk about positional params
[4:10]
so anywho
[4:10]
how might `media-player` render your template with its own built in .js file...
new messages
cowboyd [4:11 PM]
`{{media-player layout=}}`?
machty [4:13 PM]
hmmm
[4:13]
is it layout or template?
[4:13]
(is `template` even overridable anymore?)
cowboyd [4:14 PM]
shrugs
locks [4:14 PM]
template is gone
machty [4:14 PM]
werd
[4:14]
i think we're getting closer to stuff that can be solved in user-space once the basic features are in place
[4:15]
it's worth relinking this particular section https://gist.github.com/machty/c00c83f3fbefefa72cefb0bb2322fc4f#x-calendar-layout
[4:16]
because in all of this jsx-inspired, open-ended / component-y stuff, there are still some reaaaally nice conventions here
[4:16]
conventions that have been hiding behind present day clunky glimmer/hbs
cowboyd [4:24 PM]
I actually have to go heads down for a bit....
machty [4:27 PM]
same
cowboyd [4:28 PM]
this channel is addictive tho `:crack-pipe-emoji:`
samselikoff [4:58 PM]
nerds
locks [5:08 PM]
https://slackhq.com/threaded-messaging-comes-to-slack-417ffba054bd#.vil1khrdy
Several People Are Typing — The Official Slack Blog
Threaded messaging comes to Slack
Keep conversations organized and easy to follow with Threads
Reading time
----------------
4 min read
(269KB)
Yesterday at 1:00 PM
[5:08]
brain assplosion
machty [5:08 PM]
saw that too... the buttons haven't shown up for me yet
locks [5:10 PM]
and thus starts slack's descent
samselikoff [5:23 PM]
i just saw this today https://risingstars2016.js.org/, and find it interesting wrt this channel's convos. Because vuejs has a template/js separation
risingstars2016.js.org
2016 JavaScript Rising Stars
A complete overview of the JavaScript landscape in 2016: trends about front-end and node.js frameworks, tooling, IDE, Static site generators... (48KB)
locks [5:29 PM]
they have single file though
cowboyd [5:29 PM]
Overall, I see template/js separation as a good thing. Just a matter of what goes where. Also, Vue has a great escape hatch when that’s not what you want.
locks [5:29 PM]
which appeases most people
cowboyd [5:29 PM]
yeah
locks [5:29 PM]
and they have veux
samselikoff [5:31 PM]
what's the escape hatch?
[5:31]
> they have single file though
this wouldn't explain why react devs are switching
locks [5:34 PM]
one rfc down, muahaha
[5:34]
@samselikoff sure, they're separate but imo related things
machty [5:34 PM]
what do you think i'm working on
locks [5:35 PM]
colocation is enough for most people
[5:35]
as in, the general concern I see is "I have to have two files open, boo", not "I want JSX"
mmun [7:35 PM]
I dont share the love for {{component}}
[7:36]
Block lambdas let you pass fragments
[7:38]
In react you can pass a component factory as a prop or pass a function that when executed returns dom
[7:38]
How are people dealing with this dichotomy?
[7:39]
Or does react support fragment components?
machty [7:40 PM]
afaik react doesn't yet support fragments?
[7:40]
https://github.com/facebook/react/issues/2127
mmun [7:40 PM]
We should ask ppl in the know
machty [7:40 PM]
but anywho: if it's a tag-less component, what's the difference?
[7:41]
(i forget what the plan is for glimmer components, whether they're tagless or how they work at all)
mmun [7:41 PM]
Yes thats fine for named components (edited)
[7:41]
But were talking about compositions that only involve one file
machty [7:42 PM]
yeah
[7:42]
well it's not clear yet what the value of an anonymous block actually is
mmun [7:42 PM]
It bugs we that there isnt one obvious solution (edited)
machty [7:43 PM]
is it some BlockReference or something?
[7:43]
or maybe it's a tagless component right off the bat (edited)
mmun [7:43 PM]
With layout simply `{{yield}}`
machty [7:44 PM]
?
mmun [7:45 PM]
Bleh.
machty [7:46 PM]
```{{x-foo
thing=(|c|
<div>
{{c.title}}
</div>
)
}}
```
(edited)
[7:46]
the question "what is `thing`" is up for debate
[7:47]
one possible answer is it's an Ember.Component with `tagName: ''`
[7:47]
you render it with `{{component}}` and it'll be a fragment
[7:48]
if it were `thing=(component 'x-foo')` then it'd defer to x-foo's .js to figure out what it is, or be wrapped in a div by default
[7:48]
or some default that aligns w glimmer components
mmun [8:30 PM]
That part i can live with. What is c is the sticky wicket
[8:31]
If you invoke a block as a component it could be attrs.
[8:31]
If you invoke it with yield its the regular thing
[8:31]
Both seem fine
machty [8:31 PM]
i don't want these to be invocable with yield for the many reasons i laid out above
mmun [8:32 PM]
You just became my 006
[8:32]
Machtrevelyan (edited)
machty [8:33 PM]
lol what's that mean
mmun [8:35 PM]
Haha. 006 betrays 007 at the beginning of goldeneye
[8:37]
I prefer yield and lambdas. You resist because of the indirection introduced when you wrap a component invocation with a lambda
[8:38]
But in my eyes the component subexpression is just as gnarly
machty [8:38 PM]
(also because: how do you "forward" your yield+lambda syntax to internal components that expects `(component)`s) (edited)
mmun [8:38 PM]
Especially when you consider html component invocations
machty [8:38 PM]
say more
mmun [8:39 PM]
Ugh hard to type on phone
[8:39]
In a lambda you can invoke glimmer componnents eith plain html syntax
[8:40]
Ok sorry im tackling the wrong strawman
[8:40]
Your suggesting that the lambda syntax is a component
[8:41]
Is be coolish with that if it plays well with @attrs and doesnt require {{component}}
machty [8:41 PM]
man
[8:41]
i'm out of the loop
[8:41]
what is `@attrs` (and what "stage") (edited)
mmun [8:42 PM]
<glim-comp @foo="{{bar}}">
[8:43]
In yehudaa mind probably stage 2 but no rfc yet (edited)
machty [8:43 PM]
ok
mmun [8:43 PM]
Yehudada
[8:43]
:tm:
machty [8:43 PM]
my spider sense tells me i'm going to want to flip tables at the end of how many constraints are imposed by new untested glimmer syntax
mmun [8:44 PM]
@ have a very legit purpose
[8:44]
For html integration
machty [8:44 PM]
ah ok
locks [8:44 PM]
I think `@` is pretty solidly here
[8:44]
regardless of actual sigil
mmun [8:45 PM]
Sorry. We call them args now. Not attrs.
machty [8:45 PM]
in that case i'd imagine `|c| c.wat` would access `@wat="..."`
locks [8:45 PM]
:joy:
machty [8:45 PM]
oh boy
locks [8:45 PM]
this is good @machty, trust us <3
mmun [8:45 PM]
No
locks [8:45 PM]
they're good components (edited)
mmun [8:45 PM]
Dont trust us.
machty [8:45 PM]
i really don't trust yall
mmun [8:46 PM]
We need to convince people on merit
machty [8:46 PM]
I really don't believe in the angle bracket push. i believe it to be unbelievably low priority
[8:46]
for all the stuff missing in ember
locks [8:46 PM]
2 years in the making isn't low enough priority for you? :P
machty [8:46 PM]
it's been this hovering ghost of compat issues whenever improvements to the view layer come up
12 replies Last reply today at 6:20 AM View thread
locks [8:47 PM]
I'm interested in having that (other) conversation @machty
machty [8:51 PM]
@locks which one (sorry might gotten confused by the slack thread thing)
locks [8:52 PM]
missing stuff in Ember
[8:52]
I DMed you
[8:53]
y'all have threads!?
machty [8:55 PM]
check out my sick new threads (edited)
locks [8:55 PM]
all I have is fibers
machty [9:12 PM]
https://github.com/ember-animation/liquid-fire/blob/master/addon/templates/components/liquid-bind.hbs
[9:13]
there's a lot of examples like these
[9:13]
i feel like this kind of stuff should be within scope of what i'm/we're proposing
[9:13]
it's a good case for why `{{component}}` shouldn't be the only way to render these things
mmun [11:11 PM]
~
runspired [11:22 PM]
@mmun: c?
mmun [11:28 PM]
c
runspired [11:34 PM]
@mmun: thought maybe you were confused by mentions you don't see
[11:34]
I replied on that thread above :P
alkamin [11:41 PM]
joined #topic-forms
----- Today January 19th, 2017 -----
locks [6:27 AM]
@ryanto @samselikoff I now understand why you were talking about self-contained components ;P
[6:27]
that countries CP though
machty [6:58 AM]
@mmun i'm starting to agree that `{{component attrBlock}}` + `|c|` == component instance is wack
[6:58]
it might be the best option in the end
[6:58]
but it is weird
machty [9:27 AM]
OK, here's a rough draft of an RFC of all the bozo stuff we've been talking about
[9:27]
https://gist.github.com/machty/04aee681d6a0b6fb4484d8c1f8d06d82
[9:27]
even though i feel it raised compelling points, it still feels gross?
locks [9:34 AM]
straps in
locks [9:48 AM]
> { ... } denotes regions of JavaScript, whereas <...> denotes regions of JSX
so this is the crux of the thing (edited)
[9:49]
```<x-foo
header=(|d|
<my-header
subheader=(|h|
<h1>{{d.foo}}, {{h.foo}}, and {{outerFoo}}</h1>
)
>
)
>
```
is also :+1: @machty ? (edited)
machty [9:50 AM]
does glimmer make you put `/>` at the end?
locks [9:50 AM]
I'm curious about 2. unwrapped dom fragments must be supported, is this for parity with blocks?
machty [9:51 AM]
yeah
locks [9:51 AM]
oh… I'm not sure angle bracket components have an inline form (edited)
machty [9:52 AM]
hmm
[9:52]
`/>` is nicer than just `>` out in the open
jrowlingson [9:52 AM]
joined #topic-forms
locks [9:53 AM]
general caveat about angle bracket syntax not existing atm
locks [9:53 AM]
last time I looked you would have to always do `<my-comp></my-comp>`
[9:54]
let's shelf it, I don't want to derail
machty [9:54 AM]
yeah no worries
locks [9:56 AM]
```{{let header=(|d| I am fragment, hear me {{d.action}})}}
{{x-foo header=header}}
```
is tight
machty [9:56 AM]
i think it might be nice to specify the order of importance of various features:
1. we shouldn't build out yield; positional params will fragment the ecosystem and (component) works well
2. we should continue the pattern of passing in templates/components as attrs, rather than blocks living in their own closed off inaccessible namespace
3. (less important but hopeful) a Glimmer syntax that was recursively nestable like JSX would be the most universal solution to this
cowboyd [9:58 AM]
Thanks @machty for making sure this conversation never stalls out. And for writing two rfcs in like 4 days.
locks [9:59 AM]
> when passed a template block, render it as a fragment (i.e. tagName: "")
this raises some questions wrt event handling and such
[9:59]
hm
[10:01]
I don't think enhancing `yield` is a good idea, same situation with `let`/`with` imo. with the slight nuance that I still think `yield` is a useful construct
samselikoff [10:03 AM]
> that countries CP though
@locks where'd you see this, the component args video?
locks [10:03 AM]
yy
[10:04]
there was, curiously, a discussion on the pattern of CPs with no dependent keys at #general (edited)
[10:07]
@machty this rfc would deprecate `{{yield}}`, c/d
machty [10:08 AM]
no.... probably not
[10:08]
blurg i dunno, it's weird
[10:08]
it's like ruby
[10:08]
what do you do when you want to pass multiple blocks to ruby?
[10:09]
you can't use the do/end syntax at the end of the method anymore
locks [10:09 AM]
you cry in a corner because functions aren't first-class
machty [10:09 AM]
you gotta start passing in options that point to lambdas/procs (possibly constructed w do end)
locks [10:09 AM]
right
machty [10:09 AM]
if you're writing a single purpose component then yield's fine
locks [10:10 AM]
but I still think `yield` is useful
[10:10]
it's more limited because it's conceptually simpler
machty [10:10 AM]
(prior art: JSX's this.children pattern vs passing in named props that point to separate compoennts)
cowboyd [10:11 AM]
I still feel trouble convincing the inner sanctum of my soul of ‘component-centric’ render, even though my rational mind is very close. Let me see if I can’t try and write some of it down. (edited)
locks [10:11 AM]
this makes sense, and goes with glimmer making component a primitive
locks [10:23 AM]
@machty seems `<my-component />` is on the table afterall
machty [10:30 AM]
cool
[10:31]
well i figure i'll let people comment on this rfc draft today and work out some kinks before posting it
[10:31]
@locks what's your general feeling? i know this stuff kinda makes you queasy but does it seem over-engineered or anything like that?
locks [10:33 AM]
I think this is hard to teach and a bit of a slippery slope, but then again people already do all sorts of hacks with private apis and stuff
[10:33]
but I think it's a good approach
machty [10:34 AM]
hmm i'm trying to imagine what grandiose feature follows in the same path as this enhancement
rlivsey [10:40 AM]
joined #topic-forms
machty [10:44 AM]
`hasBlock` is weird
[10:45]
the fact that blocks live in their own entire world and need special built-ins to query them is just weird
[10:45]
i'm sure there's some justification for them
[10:45]
but i think it could also be explained as an accident of history
[10:45]
where block helpers were a thing before components
[10:45]
there was no concept of attrs, no conventions around components
machty [11:02 AM]
machty's rule of ember composability: if you can't access it in both JS/Handlebars, it's a bad primitive for composition (edited)
locks [11:05 AM]
oh god, you just made me realize people will programmatically render passed in components
machty [11:05 AM]
lol i don't think that's possible
[11:05]
but you should be able to write computed properties dependent on whether there's a block
[11:06]
blurg i'm sure any one on the core team that was involved in this decision could out argue me but they're still be wrong
[11:06]
ok i need to actually do work today
[11:06]
bbl
locks [11:06 AM]
I think that was simply an oversight
[11:07]
my webs are dial-speed atm
[11:08]
nvm, I was thinking of something else
[11:08]
https://github.com/emberjs/ember.js/issues/11741#issuecomment-121248949
machty [11:13 AM]
@locks excellent link
machty [11:23 AM]
https://github.com/emberjs/rfcs/pull/102
[11:24]
it's my hope that my RFC would render 102 moot
[11:26]
yeah, this stupid channel as addicting af
knownasilya [11:29 AM]
lol
locks [11:29 AM]
> It does simply seem odd that you can't use hasBlock as a computed property.
[11:30]
why can't it be jsut a property :x
knownasilya [11:30 AM]
yeah..
[11:31]
someone should write a bot for slack that saves history periodically for a channel..
[11:31]
to a gist like machty is doing
locks [11:37 AM]
it's against the TOS
knownasilya [12:07 PM]
ah..
[12:07]
lame, but i do like the latest slack features. video and threads..
[12:07]
guess we'll live with it :slightly_smiling_face:
locks [9:25 PM]
@machty https://gist.github.com/carols10cents/b6d03a6da9f2ea950571f59fb19cc56e I think you'll like this
machty [10:00 PM]
i like those literals in hbs
[10:00]
`['travis-ci', 'appveyor']`
[10:00]
should be a thing
[10:01]
commas are interchangeable with spaces in clj (edited)
[10:01]
you can use em for clarity, or not
locks [10:01 PM]
yy
machty [10:01 PM]
i think i'm gonna submit my rfc
locks [10:02 PM]
I'd rather not have the commas in hbs tbh
machty [10:02 PM]
`['travis-ci' 'appveyor']`
locks [10:02 PM]
nor the array literal ;P
machty [10:02 PM]
lol why
[10:02]
you must hate n00bs
locks [10:03 PM]
with my gguttss
[10:03]
na, it's just, tricky
[10:03]
the more JS it looks, the more JS people want to put in
machty [10:04 PM]
seems fine to let in all the declarative side-effect free things?
[10:04]
@cowboyd was typing. should i hold off on the rfc til you tell me your component thoughts?
cowboyd [10:05 PM]
Nah, I need to write them down
[10:05]
I was actually typing that i never knew that `,` was interchangeable in clj
locks [10:05 PM]
what I think I want to say: the more different hbs looks, the easier the context switch will be
cowboyd [10:05 PM]
I guess my brain just erased it
locks [10:05 PM]
it's like spaces and tabs in ruby
[10:05]
there's no right answer, but the wrong one is to use tabs
cowboyd [10:05 PM]
But I can leave that feeback on the rfc, or discuss it in here
locks [10:06 PM]
I'm about to say something stupid @machty
[10:06]
I'd rather `{a=3}` be the hash shorthand than `(a=3)`, as well as the lambda syntax (edited)
machty [10:07 PM]
doesn't sound stupid to me
[10:07]
haven't really thought too hard about it
locks [10:07 PM]
I know you don't want to fall into bikeshed pits
[10:08]
but my goal isn't to argue for arguing
[10:08]
I'm thinking of clojure here, once again
[10:08]
and how hickey approached introducing syntax to the language to make it, imo, easier to parse
[10:09]
like, the parens fall away even more, because now you have some sort of delineation
[10:09]
"`[]`? ok, those are the function args"
cowboyd [10:10 PM]
I wonder how vector literals are implemented in clj
locks [10:12 PM]
I just opened the cljs webpage and regretted it xD
[10:12]
lovely language, dreadful environment
cowboyd [10:13 PM]
```user> (macroexpand [])
[]
user> (type [])
clojure.lang.PersistentVector
```
[10:13]
https://embercommunity.slack.com/archives/topic-forms/p1484881977002508
locks
lovely language, dreadful environment
Posted in #topic-formsYesterday at 10:12 PM
[10:13]
whyzat?
locks [10:14 PM]
it feels completely opaque to me, I want to do some simple thing and have to learn about 10 things
[10:15]
but they don't even say that there even are 10 things to learn about
machty [10:16 PM]
i semi-agree
[10:16]
i definitely agree when it comes to om effing next
locks [10:16 PM]
haha
[10:17]
https://clojurescript.org/guides/faq-js#are-there-good-editors-for-clojurescript
[10:17]
https://clojurescript.org/guides/faq-js#are-there-build-tools-for-clojurescript
[10:17]
watness
[10:17]
(Light Table :heart: )
cowboyd [10:17 PM]
@locks maven repositories are a fundamental aspect of computer science
[10:17]
that every programmer needs to learn eventually.
locks [10:17 PM]
I feel like I'm being trolled
[10:17]
by you and by maven
[10:17]
;P
cowboyd [10:18 PM]
seeing as they underpin all of functional programming
locks [10:18 PM]
(broccoli has this problem)
[10:20]
@machty I really wanted to do om
[10:20]
and especially om.next
[10:20]
but the incidental complexity killed me
machty [10:29 PM]
incidental complexity? in clj? no such thing
[10:29]
trololol
[10:29]
the hubris attached to that lib is kind of unbearable
[10:30]
backwards incompatible new version
[10:30]
advertised as "the way UIs will be built in the future"
locks [10:30 PM]
sorry, I meant the decomplected complexity
machty [10:30 PM]
yeah
locks [10:30 PM]
I do like david nolen
[10:30]
like, a lot
machty [10:30 PM]
i'm just salty cuz he made me feel dumb
locks [10:30 PM]
aw
machty [10:35 PM]
i want ember to decompose like clojure and i want someone experienced in ember to build frameworks in clojure
locks [10:39 PM]
thankfully we have you :heart:
machty [10:40 PM]
we'll see
[10:40]
might run off once the feedback comes in :slightly_smiling_face:
locks [10:44 PM]
https://github.com/priyatam/mala did `lein dev`, it's been installing for 1min
[10:45]
oh jesus
[10:46]
there's no CSS, it's "garden"
[10:46]
there a whole dsl for typography
runspired [11:12 PM]
where is this plato
machty [11:13 PM]
hahah
[11:13]
>`{{yield}}` is not the same thing as `{{yield to=(|| {{yield}})}}`
[11:13]
oh boy
[11:13]
shouldn't have opened pandora's box here
[11:13]
i violated moron-moron confidentiality
runspired [11:14 PM]
oh god you’ve gone too far I cant trust you gtfo
machty [11:14 PM]
haha
[11:14]
agree
[11:14]
vamoose
runspired [11:14 PM]
I was reading up on some of the proposals in here earlier
[11:14]
so many good juices flowing
----- Today January 20th, 2017 -----
mmun [12:15 AM]
actually, `{{yield}}` should be the same thing as `{{yield to=(|| {{yield}})}}`
[12:15]
blocks should be TCP
[12:15]
order is restored
[12:15]
`{{yield to=(|| {{yield}})}}` is a strawman though
machty [12:15 AM]
define should
[12:15]
they are?
[12:15]
or they should be changed to be
mmun [12:17 AM]
If you define a component
```{{!-- components/calendar-wrapper.hbs --}}
{{power-calendar dayBlock=(|d| {{yield d}})}}
```
and invoke it as
```{{#calendar-wrapper as |d|}} {{d.number}} {{/calendar-wrapper}}
```
I would expect this be the same as a direct call to
```{{power-calendar dayBlock=(|d| {{d.number}})}}
```
[12:18]
This is precisely the guarantee you get if block lambdas satisfy TCP (edited)
[12:20]
so, if we assume we the blocks are TCP, it also forces that in a component’s layout `{{invoke (|| {{yield}})}}` is the same as `{{yield}}` (edited)
[12:21]
{{invoke}} here is just a strawman since i don’t want to get overly attached to {{yield to=block}} (edited)
machty [12:21 AM]
procs break TCP right?
[12:21]
gah
mmun [12:22 AM]
well i wouldn’t phrase it like that
machty [12:22 AM]
i know
mmun [12:22 AM]
if your procs are TCP then you can do non-local jumps if you’re not careful (edited)
[12:22]
if they’re not TCP then you can’t have problems
[12:24]
my comments above are just listing out properties that I think a reasonable implementation of blocks should have (edited)
[12:24]
tl;dr i think they should satisfy TCP so you can do the fancy block-forwarding.
[12:25]
haha...
[12:25]
and you can make a `(yield)` subexpression which is a shorthand for `(|a b c ...| {{yield a b c ...}})}}`. and obviously for `(yield to='inverse')` as well (edited)
[12:25]
I remember edward proposing that now
[12:27]
damn i wish i still had that talk slot for the ember sf meetup
[12:29]
{{#slot ‘talk’}}
machty [12:32 AM]
oh interesting
[12:33]
`(yield)` makes perfect sense
[12:33]
blurg
[12:33]
am i right about the component/yield divide?
[12:33]
is it as big a deal as i'm making it?
[12:33]
i feel like everyone's already dead set on yield (edited)
machty [12:40 AM]
alright i'm gonna submit this thing
mmun [12:47 AM]
https://twitter.com/kelseyhightower/status/774076482637312001 :stuck_out_tongue:
Kelsey Hightower @kelseyhightower
The best technical discussions focus on trade offs under a given set of constraints; not better or worse comparisons.
TwitterSept 8th, 2016 at 10:46 PM
machty [12:48 AM]
https://github.com/emberjs/rfcs/pull/203
[12:48]
here we go
[12:48]
god this is gonna fail so hard when people see the nested syntax
[12:48]
alright bedtime
[12:49]
is sleep TCP?
mmun [12:55 AM]
:grimacing:
sclaxton [1:22 AM]
joined #topic-forms
sclaxton [1:57 AM]
Wow. Shit is crazy
slackbot Custom Response [1:57 AM]
:explicitwarning: We'd love for this to remain an awesome place for all Emberers. Helps us out by editing that message. :point_up: https://github.com/cromwellryan/embercommunity-slack-guidelines/blob/master/CodeOfConduct.md
sclaxton [1:59 AM]
personally I feel like `{{component}}` is more of a problem than `{{yield}}`
[2:00]
It's all about that statically analyzable syntax
[2:00]
And referential transparency
mmun [2:04 AM]
hmm, can you elaborate?
sclaxton [2:07 AM]
`{{component}}` enables more layers of referential indirection by letting you dynamically generate component names to be invoked
[2:08]
Like it's totally possible to invoke a bunch of components in a project but their invocation site isn't discoverable by searching for the name of the component
[2:08]
That's :sob:
mmun [2:10 AM]
hmm, can you give a concrete example?
[2:10]
dynamic component invocations isn’t really pattern matching with me
[2:11]
you could imagine a sub-expression form of component invocation that evaluates to a factory (edited)
[2:11]
`(foo-bar blah="blah")` instead of `(component 'foo-bar' blah="blah")` (edited)
sclaxton [2:12 AM]
Say I have a bunch of types that the server sends me `red`, `blue`, `green` as string data
[2:13]
Then I define components `red-car`, `blue-car`, `green-car`
[2:15]
And invoke them dynamically as `{{component (concat colorType "-car")}}`
mmun [2:15 AM]
sure
[2:15]
sounds like a dr. seuss novel
sclaxton [2:15 AM]
In some ways it's a powerful patrern
[2:15]
But also terrible imo
mmun [2:16 AM]
I understand this much of what your wrote.
[2:16]
I don't understand how it relates to alex's RFC
sclaxton [2:16 AM]
Just saying things I don't like about `{{component}}`
[2:16]
Haha
[2:18]
Since his rfc is deductively `{{component}}` > `{{yield}}`
[2:18]
*reductively
[2:18]
Meaning I'm doing the reducting not him heh
mmun [2:18 AM]
I have to read it carefully still. But going into it I have the same initial feeling as you. (edited)
sclaxton [2:19 AM]
My rfc on slots isn't great either
[2:19]
Or doesn't really feel like the "right" solution
mmun [2:19 AM]
I'm really in favor of {{yield to=...}} + block lambdas
sclaxton [2:19 AM]
Yah
mmun [2:20 AM]
at least that's how I'm leaning atm
sclaxton [2:21 AM]
I do think we need something to solve the general problem these both attempt much sooner rather than later
mmun [2:21 AM]
hmm, I don't feel the pressure myself.
[2:21]
I've only written one component at work that would have benefited from it
[2:22]
but I do feel bad for addon authors that are struggling with their own complex components
sclaxton [2:22 AM]
It's mostly those writing component libraries that would benefit
[2:22]
Yep
[2:22]
But that's a pretty huge part of the ember ecosystem
[2:23]
If we have a strong set of usable and reusable components, we have a strong UI building ecosystem
mmun [2:24 AM]
ah you work at linkedin
[2:24]
I'm in SF until next saturday :slightly_smiling_face:
sclaxton [2:24 AM]
Guilty haha
mmun [2:25 AM]
you should socialize block lambdas internally (if you support it) (edited)
[2:25]
I think several people there are really focused on a slot syntax (edited)
[2:25]
given the messages that chad shared a few minutes ago :stuck_out_tongue:
sclaxton [2:26 AM]
Tweets or slack?
[2:26]
But yeah, that makes sense
[2:26]
I'm certainly one of them
mmun [2:26 AM]
the ember core slack, private chan
[2:26]
I would share otherwise but feels backstabby
sclaxton [2:26 AM]
Gotcha
[2:26]
No worries
mmun [2:27 AM]
I'm not opposed to a slot syntax. I think I do prefer block lambdas
sclaxton [2:28 AM]
So block lambda are an alternative?
mmun [2:29 AM]
I think slot syntax has more edge cases to design around
sclaxton [2:29 AM]
Is there somewhere I can read up on that idea?
mmun [2:29 AM]
Machty's RFC might discuss it
sclaxton [2:29 AM]
Kk
mmun [2:29 AM]
are you goin to the ember meetup?
sclaxton [2:30 AM]
Ember SF?
mmun [2:30 AM]
ya
[2:30]
next tues
sclaxton [2:31 AM]
I should be able to make it
mmun [2:31 AM]
i will try too!
sclaxton [2:33 AM]
Dope. Much block invitation syntax discussion will be had by all
[2:35]
are block lambdas the `(|| {{stuff}})` business?
[2:37]
how would that receive the block params?
mmun [2:47 AM]
(|o hi| ...)
sclaxton [2:47 AM]
but like where are those coming from?
1 reply Today at 4:05 AM View thread
sclaxton [2:48 AM]
where are they yielded from and how I guess
[2:48]
its anonymous right?
[2:49]
with named slots you yield to the named block
[2:49]
I think I’m missing something with how you would invoke a block lambda
runspired [3:20 AM]
@mmun I didnt realize you were in town
[3:20]
we should hang :slightly_smiling_face:
[3:22]
@sclaxton we actually have a path for making component statically analyzable once the modules rfc lands
mmun [3:48 AM]
let's!
[3:49]
fwiw the `(|| ...)` syntax is not really acceptable to me because the `...` could very likely contain a `)` (edited)
sclaxton [4:02 AM]
@runspired yeah I’ve heard talk of that as well
[4:03]
I guess that’s fine
[4:03]
I feel like the real argument here is what’s the atomic template primitive we want to expose to users, blocks or components (edited)
[4:04]
With named slots components essentially become a keyed collection of blocks arranged in some way
[4:05]
so blocks would be the atomic primitive
[4:06]
what is?
[4:07]
right now block don’t really seem like a front-and-center primitive because they’re essentially treated as an implementation detail of components (edited)
[4:08]
block lambdas would also have the effect of making blocks the primary template atom (edited)
locks [4:14 AM]
has anyone read the slot syntax thing of web components?
sclaxton [4:14 AM]
parts
[4:15]
I feel like it should be pretty orthogonal to ember “slots" no?
[4:15]
which is why we maybe should stop calling them slots?
locks [4:16 AM]
http://stackoverflow.com/questions/38540025/web-components-why-content-was-replaced-with-slot
stackoverflow.com
Web Components - why was replaced with
Version 1.0 of Shadow DOM will completely replace the <content> tag with <slot>. There are examples on the web I cannot find a relevant discussion which justifies this change.What was...
[4:16]
aren't they the same thing?
sclaxton [4:17 AM]
cause like shadow dom isn’t really a model that’s relatable to Ember? (edited)
[4:17]
unless I havne’t thought hard enough about it
[4:17]
which is almost certainly true
locks [4:18 AM]
well, sure
[4:18]
but ignore the shadow dom bit
[4:18]
that's only relevant for CSS right?
sclaxton [4:19 AM]
I honestly also need to readup on shadow dom
locks [4:19 AM]
I wouldn't :D
sclaxton [4:19 AM]
I thought it was basically just dom that doesn’t actually live in the dom tree
[4:19]
it’s not exposed
[4:19]
it’s in the…shadows
locks [4:20 AM]
the web component crew really :poop3d: it imo
[4:20]
custom elements v1 are nice I guess
sclaxton [4:20 AM]
which is why we stopped tracking our components with web components right?
locks [4:20 AM]
still getting used to the massive api change
[4:21]
kinda, yeah
[4:21]
anyway, I mention slots because of that too
[4:21]
he WC slots don't look that good
sclaxton [4:21 AM]
I mean it’d be cool if we could make ember slots web components slots + handlebars block params or something
[4:22]
cause web standards
[4:22]
but not cool cause I like Ember’s mental model better
locks [4:22 AM]
"cause web standards" isn't valid here imo
sclaxton [4:22 AM]
I think Ember slots would literally just be extending `yield`
locks [4:23 AM]
they refused to shift course
sclaxton [4:23 AM]
to yield to a certain “sub-block” of components
[4:23]
so it’s like web components only in the sense that it’s putting content somewhere heh
[4:24]
the machinery would be the exact same as now
locks [4:44 AM]
https://hayato.io/2016/shadowdomv1/#insertion-points-v0-vs-slots-v1 I can't even at this hour of the day
sclaxton [4:50 AM]
"Shadow piercing combinators"
[4:50]
chills
machty [6:46 AM]
> I'm really in favor of {{yield to=...}} + block lambdas
[6:47]
this is likely to be the most common response
[6:50]
but you can't just say you prefer it without addressing the semantic divide and fragmentation that'll occur by allowing both
[6:50]
both component and yield
machty [7:03 AM]
just added this to rfc PR
[7:03]
i hope it's not too jerkish
[7:03]
```By submitting feedback to this (likely to be controversial) RFC, you are implicitly agreeing to the statement below:
I, Ember enthusiast, have, to the best of my efforts, fully absorbed the nuances of the {{yield}} vs {{component}} APIs, and I understand machty's concerns about the fragmentation that would occur if we continued to build out the {{yield}} API in such a way that "named yields" were not effortlessly interchangeable with the attr=(component ...) pattern.
```
locks [7:04 AM]
:joy:
[7:04]
I :heart: you @machty
machty [7:12 AM]
uploaded this image: Pasted image at 2017-01-20, 7:12 AM
Add Comment
locks [7:16 AM]
don't be afraid @miguelcobain
miguelcobain [7:17 AM]
I always thought that component blocks were very similar to `{{#if`s. Allow me to explain:
- we can use the simple form
```{{#if boolean}}
{{!-- main block --}}
{{/if}}
```
just like components
```{{#my-component}}
{{!-- main block --}}
{{/my-component}}
```
- however, we can also use the inverse blocks
```{{#if boolean}}
{{!-- main block --}}
{{else}}
{{!-- inverse block --}}
{{/if}}
```
A component also has an inverse block. But why not expanding this syntax for a proper blocks support?
```{{#my-component}}
{{!-- main block --}}
{{block "header"}}
{{!-- header block --}}
{{/my-component}}
```
We should be able to pass in an arbitrary number of blocks and block params:
```{{#my-component}}
{{!-- main block --}}
{{block "header"}}
{{!-- header block --}}
{{block "footer" as |year|}}
{{!-- header block --}}
Copyright {{year}}.
{{/my-component}}
```
In the component's layout, we would use the current api for yielding to inverse blocks, but with named blocks:
```{{yield to="header"}}
{{yield}}
{{yield to="footer" currentYear}} {{!-- this is a bit strange --}}
```
For recreational purposes, we should be able to recreate an `{{#if` equivalent using just component constructs:
```{{#if-component boolean}}
{{!-- main block --}}
{{block "else"}}
{{!-- else block --}}
{{/if-component}}
```
and the component's template
```{{#if boolean}}
{{yield}}
{{else}}
{{yield to="else"}}
{{/if}}
```
this is just to illustrate the similarities with `{{#if`. (edited)
[7:18]
The only thing still missing is to solve the problem with components without main blocks.
locks [7:20 AM]
not sure I agree
[7:21]
the conditional behaviour of components is handlebars helpers baggage
[7:21]
and we don't have a `case` in handlebars, which seems like the more apt correlation to slots
miguelcobain [7:23 AM]
@machty's RFC is certainly more flexible.
> a) whenever the components need to be used in multiple places and b) whenever the template block grows so large that it'd be easier to understand as a separate file.
(edited)
locks [7:23 AM]
this reminds me a point sandi metz made in a talk about `if` in smalltalk
[7:26]
https://www.youtube.com/watch?v=9lv2lBq6x4A
YouTube Confreaks
BathRuby 2015 - Nothing is Something
machty [7:27 AM]
is there a more specific time?
locks [7:28 AM]
the preamble kinda sets up the context
[7:28]
but ~3min
[7:28]
3min exactly, actually
machty [7:31 AM]
i hope to attain 3% of her command of audience by the time emberconf rolls around
locks [7:31 AM]
sandi and katrina owen are like, up there
machty [7:32 AM]
i read the sandi metz red ruby book
[7:32]
still definitely don't unit test
locks [7:32 AM]
haha
machty [7:32 AM]
i mean, not to her degree
[7:33]
having to test A and B in isolation, AND ensure the mocks follow along with changes to either's API is harrowing af
[7:33]
i wish i'd seen this talk 8 years ago
locks [7:35 AM]
I'm so bummed for not being able to go to emberconf
machty [7:37 AM]
i'd love to see sandi and rich hickey have a convo
[7:37]
so much of FP is case-matching against known types _by intention_
locks [7:45 AM]
```~/s/e/ember.js git:(master) yarn update glimmer-engine
yarn update v0.17.10
error Did you mean `yarn upgrade`?
info Visit https://yarnpkg.com/en/docs/cli/upgrade for documentation about this command.
```
[7:45]
why didn't this just work
machty [7:46 AM]
brew upgrade is different than update
[7:46]
if they just made it work then they wouldn't be able to add that in the future
locks [7:49 AM]
I wonder how much justification there is for the api decisions
[7:49]
like, npm update -> yarn upgrade (kinda)
machty [7:51 AM]
i can never remember
miguelcobain [7:52 AM]
npm install --save -> yarn add
locks [7:52 AM]
any thoughts on https://embercommunity.slack.com/archives/topic-forms/p1484914661002763 ? (edited)
[7:53]
I mean, it kinda makes sense to have different terminology for different semantics
machty [7:53 AM]
i'm not sure how it ties in or what it's recommending
[7:53]
it doesn't address the component/yield divide
[7:54]
(minor correction: `{{yield to="footer" currentYear}}` needs to be `{{yield currentYear to="footer"}}`) (edited)
miguelcobain [8:01 AM]
@machty component/yield divide?
machty [8:04 AM]
@miguelcobain oh, i was assuming your if/component comparison was in regards to the rfc https://github.com/emberjs/rfcs/pull/203
miguelcobain [8:06 AM]
I was basically suggesting a blocks syntax.
[8:06]
And trying to understand why something like that wouldn't work.
[8:06]
(You gave this topic a lot more thought than i did)
machty [8:07 AM]
word
[8:07]
wellll this is my dissertation: https://github.com/machty/rfcs/blob/nested-handlebars/text/0000-nested-handlebars-syntax.md#why-not-yield
miguelcobain [8:35 AM]
Somehow, things made more sense the second time I read it. Thanks.
[8:37]
@machty does your RFC include `yield` deprecation? Because with that API, `{{yield` wouldn't be needed anymore. (edited)
machty [8:37 AM]
I don't know, probably not
[8:37]
that'd be a bit too bold
[8:37]
i'll wait for feedback first
locks [8:57 AM]
just to be clear, if `yield` would get deprecated in function of this rfc, it would be an additional deprecation rfc
machty [8:59 AM]
yeah
[8:59]
my hope is that people take seriously the yield/component divide, adapt to the arguments made, and refine the role that `yield` should take
[9:00]
i'm not privy to lots of internal glimmer convos so i def can't predict the response
locks [9:00 AM]
I'd be interested to see someone make a generators correlation
machty [9:01 AM]
how so? (edited)
[9:02]
generator functions or ember-cli generators?
locks [9:02 AM]
generator functions
cowboyd [9:07 AM]
I do take seriously the yield component / divide, but doesn’t it also only make sense if `positionalParams` api is deprecated? Because isn’t that cat out of the bag already?
[9:09]
Do I understand correctly that if a component uses `positionalParams`, then it _cannot_ be rendered programmatically?
locks [9:09 AM]
we need splat operator and the router service (in master behind a feature flag, woop woop) to kill positional params (edited)
cowboyd [9:11 AM]
but is the plan to do that?
[9:11]
irrespective of @machty’s rfc? (edited)
locks [9:11 AM]
I don't think there's an actual plan
[9:11]
but positional params are costly
[9:11]
and some people would like to axe them
[9:11]
right @serabe
cowboyd [9:13 AM]
I definitely feel like a choice must be made between eliminating positional params on the one hand, or extending programmatic rendering to account for them.
[9:13]
The situation where a subset of components are magically 2nd class because they use an api is an unfortunate one.
locks [9:14 AM]
I think the concerns about the splat operator are in the hbs repo
[9:14]
positional params are 2nd class ;X
machty [9:16 AM]
how would you extend the programmatic rendering? (edited)
cowboyd [9:17 AM]
I don’t know, but I’m curious to explore it in order to more fully understand the choice, because if I understand it, then it it is a mutually exclusive one.
rwjblue [9:17 AM]
@machty can ask questions RE RFC#203 here?
[9:18]
The examples leave me wondering a number of things
cowboyd [9:19 AM]
seems like you would have to be able to bind p-params from a template. Right now it’s a JS only thing (edited)
[9:20]
(and is therefore subject to @machty’s rule of weak sauce)
machty [9:24 AM]
@rwjblue of course
rwjblue [9:24 AM]
I have a list, and don't want to derail convo
cowboyd [9:24 AM]
derailing the convo is the official topic of this channel.
rwjblue [9:24 AM]
LOL
[9:24]
OK
cowboyd [9:24 AM]
In a very positive way
rwjblue [9:25 AM]
```// classic curly style:
{{media-player
tracklist=(|data|
{{#each data.tracks as |t|}}
<div class="track">{{ track.name }}</div>
{{/each}}
)
}}
```
* What is `data`? How is it passed in?
* What does `media-player`'s `layout` look like? (edited)
[9:25]
Further down you suggest that it would invoke `tracklist` via `{{component` right?
[9:26]
I suspect it might be something like:
```{{component tracklist}}
```
cowboyd [9:27 AM]
iirc `{{component tracklist tracks=model.tracks}}` right?
rwjblue [9:27 AM]
I am not fond of the idea that the hash arguments are basically turned into a POJO that is the first block param.
[9:28]
`{{component` already supports positional arguments, why would we not use them?
[9:29]
Also, the RFC talks alot about "we are not using yield" and "why not yield", but I don't really see the explanation that I can get behind
[9:29]
I totally dig invoking via `{{component` helper (or a new helper for `{{block` or whatever)
[9:30]
however, saying "we are not using `{{yield}}`" seems weird
[9:32]
because the first thign I wanted to do when reading the snippet I pasted above was:
```{{media-player
tracklist=(|data|
{{#each data.tracks as |t|}}
<div class="track">{{yield t}}</div>
{{/each}}
)
}}
```
media-player's layout:
```{{#component tracklist tracks=whatever as |track|}}
<a href={{url-for 'track.details' track}}>track.title</a>
{{/component}}
```
(edited)
[9:32]
I don't think its "lets not use yield" so much, as "lets use yield for its intended purpose"
machty [9:33 AM]
what is `<div class="track">{{yield t}}</div>`?
rwjblue [9:33 AM]
I made it up
[9:33]
if you can pass blocks, and those blocks are basically like components, why can't you yield?
machty [9:33 AM]
how would media-player's layout component render that? (edited)
rwjblue [9:34 AM]
thats the second snippet (edited)
cowboyd [9:34 AM]
My natural intuition is to render the head of every expression:
```{{#x-foo as |a b c=}}
{{a}} {{b} {{c}}
{{/x-foo}}
```
whose template looks like:
```{{yield a b c=d}}
```
is really just a synonym for:
machty [9:34 AM]
that looks like really intensively recursive stuff @mmun and i were half-jokingly discussing last night
cowboyd [9:34 AM]
```{{x-foo yield=(|a b c=|) {{a}} {{b}} {{c}} }}
```
(edited)
[9:35]
i.e. helper-less render.
rwjblue [9:36 AM]
anyways, the focus on "why not yield" distracts from the proposal IMO
[9:36]
I quite like the primitive you are suggesting
[9:36]
assuming we can do it and not feel like a "bolt on" after the fact thing
[9:37]
:clap: :clap: for convincing me of one of these "slots" RFC's :slightly_smiling_face: (edited)
machty [9:37 AM]
@rwjblue if you stick with the pattern it's:
```consumer:
{{media-player
tracklist=(|data|
{{#each data.tracks as |t|}}
<div class="track">{{component t...CRAP I DUNNO}}</div>
{{/each}}
)
}}
media-player layout:
{{component
tracklist tracks=whatever
snippet=(|a|
<a href={{url-for 'track.details' a.track}}>{{a.track.title}}</a>
)
}}
```
[9:38]
i don't know what to tell you about what roll `{{yield}}` should have
[9:38]
just that one you start using it, you've severed swappability with `{{component}}`
[9:38]
and i don't know where to tell you where one API should begin and the other end
rwjblue [9:38 AM]
to me, it depends on what the point is
machty [9:38 AM]
just that the one thing that's certain is that we should not extend `{{yield}}` to be more powerful than it is
[9:38]
also, you kinda snuck in a feature that you can't even do today with yield
rwjblue [9:39 AM]
if the idea is that `tracklist` is "just like any other component" it should be able to yield (edited)
machty [9:39 AM]
block templates today can't yield
[9:39]
but you provided an example in the proposed RFC style where it does
rwjblue [9:39 AM]
@machty totally agreed, *but* you are essentially saying this is a component (you don't propose `{{block` helper, you use `{{component` helper)
[9:40]
if it is a component, it should be a component
[9:40]
otherwise you have super weird rules about what is allowed and what is not in a "component" template
[9:40]
which (if I read them right) violates "machty's rules of lame sauce"
machty [9:41 AM]
what are these weird rules?
rwjblue [9:42 AM]
if I write a component template (actually layout but whatevs) I can use `{{yield` to yield to the provided block
[9:42]
if I do your proposed thing, I cannot
[9:42]
even though it is effectively being called a "component"
[9:43]
or do you mean the rules of lame/weak sauce? (because I thought you made that up?) (edited)
machty [9:45 AM]
there's nothing in my RFC that prevents what you're trying to do
cowboyd [9:45 AM]
Hah. The rule I was referring to was what you coined way up in the convo which called any API that was Hbs only was lamesauce.
[9:45]
A sentiment with which I wholeheartedly agree.
machty [9:46 AM]
my RFC just points out in no uncertain terms that we already have this problem today (you can pass in chunks of dom via both attr=(component) and yield-able templates to component) and we should standardize on a story/future and please god i hope it's not to put fuel on the fire by extending yield
[9:46]
https://gist.github.com/machty/68afad4c03109f36d4f4cffaae3c170b#file-gistfile1-txt-L7193
[9:47]
i replaced "weak sauce" with "bad primitive for composition"
rwjblue [9:47 AM]
but weaksauce was better :slightly_smiling_face:
[9:47]
@machty the thing is, `{{yield` has a purpose today
[9:47]
unless you are suggesting that we deprecate it completely, it likely will still have a use case
machty [9:48 AM]
TBD. i don't have an answer yet
[9:48]
i just wanna get everyone talking about the same thing
[9:48]
(and i have succeeded :slightly_smiling_face: )
locks [9:48 AM]
extending yield to support slots, right (edited)
machty [9:48 AM]
:troll:
[9:49]
that was a good one
locks [9:49 AM]
first rule of slots club is you talk about lambdas
rwjblue [9:49 AM]
@machty I don't agree with some of the choices you have made here (e.g. I don't think we should use hash args into a single pojo), but overall the general thrust of "lets make it nestable" is good
machty [9:50 AM]
@rwjblue if you don't like that then you need to counter with an alternative that preserves attr=(component) swappability
rwjblue [9:50 AM]
ha! I don't *need* to do anything
[9:50]
I'm just going to sit back and what and see what happens
[9:50]
remember I am the thought laggard, I just like doing mountains of work
[9:51]
Also, I have no clue wtf `attr=(component)` swappability means
machty [9:51 AM]
https://github.com/machty/rfcs/blob/nested-handlebars/text/0000-nested-handlebars-syntax.md#why-not-yield-impedance-mismatch-with-component
rwjblue [9:53 AM]
yeah, don't get it
machty [9:53 AM]
you don't like the attrs pojo
rwjblue [9:54 AM]
well, my issue is mostly with lack of splat
[9:54]
if we had splat I would have no issue
machty [9:54 AM]
but that constraint is that layout templates render attr compoents via `{{component attr foo=123}}`
[9:54]
and that works today if you passed in `attr=(component 'x-lol')`
rwjblue [9:55 AM]
with hash args being translated automatically to a pojo and passed as block params, you loose the ability to actually create the attrs in JS space
machty [9:55 AM]
`x-lol` receives foo=123 as an attr along with anything else
rwjblue [9:55 AM]
which is "weaksauce"?
machty [9:55 AM]
so if you wanted to replace `attr=(component 'x-lol')` with `attr=(|xyz| <div>inline template from RFC</div>)`, what else could `xyz` possibly be
[9:56]
without requiring your layout template change the way it renders
[9:56]
how would splats help here
rwjblue [9:56 AM]
my issue is with not being able to dynamically change the arguments in JS
machty [9:57 AM]
that is an orthogonal feature
[9:57]
(that i too want, and happened to have implemented)
rwjblue [9:57 AM]
hah! its all orthogonal :stuck_out_tongue:
machty [9:57 AM]
but whether there's splat or no, the block param can't be anything but a pojo of attrs
rwjblue [9:58 AM]
yeah, I don't really see why
machty [9:58 AM]
(destructuring syntax might also help)
[9:58]
> so if you wanted to replace `attr=(component 'x-lol')` with `attr=(|xyz| <div>inline template from RFC</div>)`, what else could `xyz` possibly be
[9:58]
@rwjblue this is the question
rwjblue [9:58 AM]
to change from `attr=(component 'foo')` to `attr=(|xyz| sasdfasdfsd)` you still have to change many things
machty [9:58 AM]
like?
rwjblue [9:58 AM]
`foo` template? (edited)
[9:59]
the place where this invocation is (obviously) (edited)
[9:59]
now, we could do an awesome thing and have named block params
[9:59]
but that also seems hard
[10:00]
(though maybe not, since the block param syntax is more constrained already)
[10:00]
but I guess then you would have to duplicate / repeat yourself
[10:01]
`attrs=(|name=name title=title| {{name}})` or whatever
[10:01]
which kinda sucks (edited)
locks [10:01 AM]
`attrs=(|(name,title)| {{name}})`
[10:02]
only half joking, what I mean with ^ is "destructuring"
machty [10:02 AM]
obviously if you make the refactoring decision to change from passing `attr=(component 'x-bar')` into an inline template, you'll need to copy x-bar's template into the inline template block and change prefix what used to be references to attrs with `theBlockParam.`
[10:02]
the point is that `media-player` or whatever shouldn't have to change to accommodate that
[10:03]
it should keep on keepin on rendering components with `{{component myAttr some=value}}`
rwjblue [10:03 AM]
hmm, I thought you were suggesting that you might want to wrap a component
[10:04]
`attr=(component 'x-lol')` with `attr=(|xyz| <div class="special">{{component 'x-lol' ...xyx}}</div>)` which is where I went on with wanting splat / spread / whatever (edited)
[10:05]
it would be nice if ^ refactoring could happen without changing `x-lol` layout at all
machty [10:06 AM]
that is an excellent use case
[10:07]
lemme think about that
[10:07]
i understand the use case you're describing
[10:07]
you understand mine too, right?
rwjblue [10:07 AM]
aye
machty [10:07 AM]
:+1:
[10:07]
yeah you'd need splat syntax
[10:07]
for what you're describing
rwjblue [10:07 AM]
I only _slightly_ dislike the thing I was talking about BTW, 90% +1 on your proposal
[10:08]
its hard to make it clear that I know I am talking about edge cases
machty [10:08 AM]
well you don't strictly need splat syntax
[10:08]
you could explicitly list out all the properties you wanna pass
[10:08]
but that sucks
rwjblue [10:08 AM]
which completely couples everythign (edited)
machty [10:08 AM]
it does and it doesn't
rwjblue [10:08 AM]
imagine that it was `attr=(component somethingPassedIn)` instead
machty [10:09 AM]
if `media-player` starts adding new attrs, the components that receive it would need to change in order to start using those attrs
rwjblue [10:09 AM]
now the "middle" layer must be aware of all the properties
machty [10:09 AM]
pre-existing attrs that were already being manually forwarded due to lack of splat syntax will continue to propagate the change just fine
rwjblue [10:09 AM]
confirm
machty [10:09 AM]
but confirm: now the "middle" layer must be aware of all the properties
rwjblue [10:10 AM]
I dont really think it is a new problem though
[10:10]
so likely doesn't make sense to address in this RFC
knownasilya [10:11 AM]
If the middle layer had a way to access all properties, e.g. `attrs` property, then it would be less of an issue
rwjblue [10:11 AM]
but can I just say damn you people for making another channel I have to read?
locks [10:11 AM]
#sorrynotsorry
rwjblue [10:11 AM]
@knownasilya not really, because even if you know them in JS you can't pass them all in templateland
locks [10:11 AM]
btw, I can rename the channel
[10:11]
#dev-dev-ember? :joy:
rwjblue [10:11 AM]
#dreamland
locks [10:11 AM]
I know, #weaksauce
[10:12]
@mmun what were the splat blockers? (edited)
knownasilya [10:12 AM]
@rwjblue you could if you made them into an array, [{key, value}]
[10:12]
but you lose the context
[10:12]
putting all the attrs on equal ground
rwjblue [10:13 AM]
locks IIRC it was kpdecker?
[10:13]
but I can't really remember
machty [10:13 AM]
no, it's blocked by yehuda and Glimmer concerns
knownasilya [10:13 AM]
so yeah, for anything worthwhile the middleman needs to be updated
rwjblue [10:13 AM]
@machty nice
machty [10:13 AM]
kpdecker was +1
rwjblue [10:13 AM]
@knownasilya right, which hurts composability
[10:13]
IMO
[10:14]
@machty any idea if we can try to shake it loose?
machty [10:14 AM]
I don't know
[10:14]
last I heard he had perf concerns
[10:14]
and perhaps it doesn't model well in the Reference abstraction
rwjblue [10:14 AM]
interesting
machty [10:15 AM]
but the composability story is hurting without it
[10:15]
React has proven this
rwjblue [10:15 AM]
it sounds like vague "I am unsure what the future is and it makes me uncomfortable to add new syntax until this other stuff I really care about is done".... (edited)
[10:16]
which is reasonable, but frustrating
machty [10:16 AM]
yeah
[10:16]
i think we're nearing that point
[10:16]
@runspired seems to think so
[10:16]
the point of comfort to add things
rwjblue [10:17 AM]
@machty ya
[10:17]
@machty hurry up and finish this RFC so we can actually do it would ya? (edited)
locks [10:18 AM]
:thinking_face:
[10:18]
we could try to overwhelm yehuda while he's vulnerable :troll:
machty [10:18 AM]
lol what do you think i've been doing https://twitter.com/machty/status/822416787971145728
Alex's Matchneer @machty
Here's a controversial Ember RFC for y'all https://github.com/emberjs/rfcs/pull/203 https://pbs.twimg.com/media/C2nPe_qXgAAZWhU.jpg
TwitterToday at 7:13 AM (75KB)
locks [10:19 AM]
so atm
[10:19]
- let
- captured blocks
- splat
?
[10:20]
I was talking about ember at yesterday's meetup
[10:20]
and I explained how ember is the land of "it'll get better soon"
samselikoff [10:22 AM]
thats so defensive lol. not very compelling..
knownasilya [10:22 AM]
haha
samselikoff [10:22 AM]
not how i would sell it :stuck_out_tongue:
knownasilya [10:22 AM]
and it does, but then we want more :slightly_smiling_face:
samselikoff [10:22 AM]
aye
locks [10:23 AM]
that wasn't how I sold it :P
knownasilya [10:24 AM]
he said use vue :stuck_out_tongue:
locks [10:24 AM]
and not quite how I phrased it
[10:24]
in other words "stability without stagninity"
rwjblue [10:24 AM]
hah, I have been a Cubs fan my whole life
locks [10:24 AM]
well, it _has_ been getting better
rwjblue [10:24 AM]
"theres always next year" is in my blood
machty [10:25 AM]
lol stagninity
locks [10:25 AM]
we can has a lot of nice things
machty [10:25 AM]
strategery
knownasilya [10:25 AM]
this is the goof-off channel
locks [10:26 AM]
I was mentioning module unification, javascript import api, `class` support, tree shaking, lazy loaded engines, etc
knownasilya [10:26 AM]
lazy loaded engines are a thing, just not routeless
[10:26]
but there are a bunch of caveats lol
[10:27]
but there is caviar
locks [10:27 AM]
right
[10:27]
and you can't share components, and there's still a bunch of overhead, etc
[10:28]
but it's something that was "we'll get there" and we did
[10:28]
for almost free for users :D
mmun [11:18 AM]
what do we do about right parens in content? (edited)
[11:18]
escape it?
machty [11:19 AM]
i don't have a good answer
[11:20]
differing to opinionated people
[11:20]
might make sense try treat it like do/end in ruby which have expectations of being preceded by newline
mmun [11:26 AM]
i dont think that works nicely with one-liners (edited)
locks [11:28 AM]
we can have ( an escaping character
[11:28]
`((()` if you want a `)` in your content
mmun [11:30 AM]
@machty do you also feel that a regular block helper invocation should be able to replace the block with a component?
rwjblue [11:30 AM]
@locks the trolls are strong with this one
knownasilya [11:30 AM]
:troll:
mmun [11:31 AM]
{{#my-component}} foo {{/my-component}}
{{my-component &default=(component 'foo')}}
machty [11:31 AM]
only if there are no block params i guess
knownasilya [11:32 AM]
component blocks still have their place I feel, especially for bigger content that doesn't get duplicated
[11:32]
easier to refactor and read IMO
[11:33]
inline-components make sense when using thirdparty code and you need to override a small piece, instead of the whole thing with the default block.
[11:34]
or your own code that is generalized
mmun [11:35 AM]
machty: so then if you want to remain compatible {{yield}} has to be able to yield to a component
[11:35]
_I rest my case your honour_
rwjblue [11:35 AM]
:popcorn:
machty [11:36 AM]
@mmun what happens if it yields positional block params?
mmun [11:39 AM]
you must use positional params
[11:40]
you're the one that wants blocks & components to be interchangeable. you tell me! (edited)
machty [11:41 AM]
there's no good answer
locks [11:41 AM]
:chompy: :popcorn:
machty [11:42 AM]
maybe we make it possible to render the default / inverse blocks with `{{component}}`
[11:42]
but your component needs to be built one way or the other
[11:42]
if it classic yields: positional params, and no good way to bridge the gap with attr=(component) (edited)
[11:43]
it it component yields: the default template block would also be passed `|attrs|`
[11:43]
(and we'd need a syntax for `(component &default)`) (edited)
[11:43]
the wat is strong, but no more wat than the present situation (edited)
mmun [11:46 AM]
you can avoid a lot of design by simply going all in with yield and wrapping a component with block lambda. that qualifies as effortless to me.
machty [11:47 AM]
"do i have to"
mmun [11:48 AM]
namely: you can avoid designing an override for built in slots like &default, you can avoid thinking about the `positionalParams` api, and instead just mapping arguments
machty [11:48 AM]
ctrl-f translation layers https://github.com/machty/rfcs/blob/nested-handlebars/text/0000-nested-handlebars-syntax.md#why-not-yield-positional-params-vs-named-attrs
mmun [11:50 AM]
> First off, this assumes that we don't care that people have already written plenty of components in the header=(component ...) style; those people would have to rewrite both x-foo's internals and change any code that renders x-foo to support this.
We can provide tools to polyfill your component (edited)
machty [11:51 AM]
what's the polyfill?
[11:51]
`positionalParams` API?
mmun [11:52 AM]
{{#if (is-component header)}}
machty [11:52 AM]
...
[11:53]
if is-component header, then translate/reinterpret positional params into named things
[11:53]
internals still need to change to accommodate this
mmun [11:53 AM]
yes
[11:54]
either way internals have to change (because you need to define positional params) (edited)
[11:54]
unless you also want to design named arguments for blocks
machty [11:54 AM]
i think i've proposed the approach that such that this API is preserved
[11:54]
```{{x-foo
header=(component 'x-header' x=1)
body=(component 'x-body' y=2)
footer=(component 'x-footer' x=3) }}
```
[11:54]
can you restate the argument that made you "rest your case"?
[11:55]
why do i have to design named arguments for blocks
[11:55]
i've pointed out the inconsistency and that it is an unfortunate artifact of the past and we should align towards a brighter future
[11:55]
two worlds exist today. they're incompatible. pick one. it'll hurt either way, but one is clearly superior IMO
mmun [11:56 AM]
exactly.
[11:56]
the superior one is the one everyone uses
[11:56]
blocks
[11:56]
grep how many people use {{yield}} vs {{component}}
machty [11:57 AM]
i dunno man i don't want to restate everything i argued in the RFC
mmun [11:57 AM]
your proposal is to continue with both {{yield}} AND {{component}}
machty [11:57 AM]
your way means translation layers and template-specific polyfill hacks that don't actually fully address the divide
[11:57]
so is yours
[11:57]
are you going to deprecate {{component}}?
mmun [11:58 AM]
no, i just imagine it will be used much more sparingly
machty [11:58 AM]
you answer is "i don't know what to do about {{component}}" and mine is "i don't know to do about {{yield}}"
mmun [11:58 AM]
where as {{#foo-bar}} ... {{/foo-bar}} is gonna be around for ever
machty [12:00 PM]
https://gist.github.com/machty/c00c83f3fbefefa72cefb0bb2322fc4f#slot-syntax
[12:00]
> We'd lose the pattern for global overrides app/ (yes, globals can always be abused, but they're great for establishing app-wide defaults while still leaving the door open for further overrides). The only way we could support "default block" templates in app/ would be to either add a syntax for declaring block params within the template (rather than at the tail end of a helper, e.g. {{#each ... as |blockParam|}}, or potentially by leveraging the esoteric positionalParams API so that "default blocks" would actually be default components that know how to convert positional block params to named attrs
[12:00]
yield would lose out on this pattern
[12:03]
there are other use cases / potentials that i haven't gone into
[12:03]
that have to do with Trek's vision of reusing/extending/overriding
[12:04]
whether it's component JS or hbs
[12:04]
that are _so close_ to being there with `{{component}}` but would need additional constructs with a yield-centric approach
[12:04]
i wish i could inundate you with examples but I cannot hack past the present glimmer limitations (edited)
machty [12:12 PM]
> so then if you want to remain compatible {{yield}} has to be able to yield to a component
[12:12]
more like: there will still be two ways to pass in overridable DOM today: one with classic block+yield, one with (component) and attrs
[12:13]
just as there are today
[12:13]
and components authors will still need to decide for what they're doing whether they're prefer the simple but limited yield + positional params approach
[12:13]
or they want to pass multiple things in (or plan one being able to do so in the future)
runspired [12:14 PM]
Y'all generate too much for me to reasonably read at this point :P
knownasilya [12:14 PM]
lol
[12:14]
summary: they are all saying the same thing, but in different ways, and a blindness to the other's direction :troll:
machty [12:15 PM]
it ain't so bad
[12:15]
we're caremad
[12:15]
at least i am
locks [12:15 PM]
and I just troll
[12:15]
we'll either end up implementing clojurescript or jsx
[12:15]
the jury is still out
runspired [12:15 PM]
Time for me to drop my reworked slots rfc i see ;)
[12:17]
Also @sclaxton if you're in SV today I should help you understand the Ember Component bs Web Component model better
locks [12:17 PM]
bullshit?
[12:18]
bootstrap?
[12:18]
beatle's song? (edited)
machty [12:18 PM]
wat
knownasilya [12:19 PM]
```{{my-modal &default=(|data|
full modal override {{data.one}} {{data.two}}
)}}
{{my-modal
head=(|data|
my header
)
body=(|data|
my body
)
}}
```
interesting to see the readability issues, or how one indents and writes these, especially if multi lined
[12:21]
I'd probably do classic for full override
```{{#my-modal as |one two|}}
full modal override {{one}} {{two}}
{{/my-modal}}
```
(edited)
locks [12:22 PM]
why so many newlines @knownasilya
knownasilya [12:23 PM]
```{{my-modal head=(|data|
my header
<a>close link</a>
) body=(|data|
my body
<a>link here too</a>
)
}}
```
[12:23]
better?
[12:23]
:troll:
[12:23]
have fun reading that.. hopefully your editor can color it better then slack does
machty [12:24 PM]
how does bullshit pass the slackbot filter
mmun [12:24 PM]
im caremad
rwjblue [12:24 PM]
I'm carerage
machty [12:24 PM]
mmun is carestingonlaurels
mmun [12:24 PM]
what color do u wanna be machty? red or blue?
machty [12:25 PM]
plz tell me we're playing rocket league
mmun [12:25 PM]
we're playing photoshop
machty [12:25 PM]
you're gonna lose even if you have the popular vote
machty [12:26 PM]
uploaded this image: Pasted image at 2017-01-20, 12:25 PM
Add Comment
machty [12:26 PM]
i've already made it clear which color i am
mmun [12:26 PM]
that escalated quickly
knownasilya [12:27 PM]
looks like grey..
mmun [12:27 PM]
haha, i see now. it isn't a political thing
knownasilya [12:27 PM]
checkered
machty [12:27 PM]
@knownasilya I can't tell if that code is an example for the RFC, or comparing w yield-centric syntax
mmun [12:27 PM]
we aren't making templates great again
knownasilya [12:28 PM]
@machty both? haha
locks [12:29 PM]
people, https://www.youtube.com/channel/UCII0hP2Ycmhh5j8lS4cexBQ
YouTube
Red vs. Blue
Welcome to the Red vs. Blue YouTube Channel. Home base for the web's longest running series, Rooster Teeth's award-winning Red vs. Blue. SUBSCRIBE: http://bi...
(edited)
knownasilya [12:29 PM]
Your RFC should also address formatting fallback
locks [12:29 PM]
what's formatting fallback?
knownasilya [12:29 PM]
wrong words.. /faceslap
[12:31]
what is the recommended way to format your component with this new syntax that goes in and out of handlebars syntax
machty [12:31 PM]
i'm still laughing at this exchange https://gist.github.com/machty/68afad4c03109f36d4f4cffaae3c170b#file-gistfile1-txt-L6217-L6220
[12:32]
@knownasilya if i understand you correctly i think there's an example in the rfc
rwjblue [12:33 PM]
RFC should add "syntax highlighting" to drawbacks list
machty [12:33 PM]
confirm
rwjblue [12:33 PM]
(not a giant deal, since it would likely be a temp problem but something to mention nonetheless) (edited)
machty [12:34 PM]
i'll add that
locks [12:34 PM]
hey, wanna know a secret
machty [12:34 PM]
@knownasilya https://github.com/machty/rfcs/blob/nested-handlebars/text/0000-nested-handlebars-syntax.md#recursively-nestable-glimmerhandlebars-syntax
[12:34]
first example
[12:34]
has recursive nesting (edited)
locks [12:34 PM]
SH is already broken for ember templates
[12:34]
in most editors :P (edited)
rwjblue [12:35 PM]
@locks uhh, wat
[12:35]
"most" editors being which?
knownasilya [12:35 PM]
@machty need an example with multiple anon-components
rwjblue [12:35 PM]
because it works well in vim, emacs, webstorm, vscode, sublime text 2, at least (these are the ones I have used in the last 3 months)....
knownasilya [12:36 PM]
or inline-components, what's the name?
1 reply Today at 12:37 PM View thread
locks [12:36 PM]
I have a document _somewhere_ with this
[12:36]
for the tools page of emberwatch
knownasilya [12:36 PM]
not nested, but siblings
rwjblue [12:36 PM]
@locks ya, no biggie, just curious (we should side channel this to #topic-editors though)
2 replies Last reply today at 12:39 PM View thread
locks [12:36 PM]
yy
machty [12:37 PM]
added this Markdown (raw) snippet: nested af
{{x-foo
header=(|d|
I am a fragment {{d.title}}
<span>Woot</span>
)
body=(|d|
I am a fragment {{d.title}}
<span>Woot</span>
{{x-foo
header=(|d|
I am a fragment {{d.title}}
<span>Woot</span>
)
body=(|d|
I am a fragment {{d.title}}
<span>Woot</span>
)
footer=(|d|
I am a fragment {{d.title}}
<span>Woot</span>
)
}}
)
footer=(|d|
I am a fragment {{d.title}}
<span>Woot</span>
)
}}
Add Comment Collapse
machty [12:37 PM]
@knownasilya ^
knownasilya [12:38 PM]
yeah, add that
machty [12:38 PM]
i think i'm gonna add an appendix of sorts (edited)
[12:38]
random code snippets that reinforce the RFC and tickle the imagination
rwjblue [12:38 PM]
ohhh, can we add a new subheading to RFC's?
knownasilya [12:38 PM]
tickle the imagination, what a slogan
rwjblue [12:38 PM]
"Ticklers"
knownasilya [12:39 PM]
lol
locks [12:39 PM]
that's against the CoC @rwjblue
[12:39]
and like shaving, you never go against the CoC
knownasilya [12:39 PM]
ToS?
rwjblue [12:39 PM]
locks I think that abbreviation is too then...
locks [12:39 PM]
I think about that every single time I see it
rwjblue [12:39 PM]
I was thinking of like a feather duster, where is your head at?
knownasilya [12:39 PM]
@machty need an example with using a block and anon-components
locks [12:40 PM]
how oblivious can you be
rwjblue [12:40 PM]
@machty nice :slightly_smiling_face:
knownasilya [12:40 PM]
like @rtablada posted
machty [12:40 PM]
set the channel topic: machty's component/yield RFC: https://github.com/emberjs/rfcs/pull/203
Backlog manually persisted here:
<https://gist.github.com/machty/68afad4c03109f36d4f4cffaae3c170b>
rwjblue [12:40 PM]
We should figure out a new name for the channel though
machty [12:40 PM]
not just yet
rwjblue [12:40 PM]
`#-machtys-musings`
2 replies Last reply today at 12:41 PM View thread
knownasilya [12:41 PM]
#machtys-ideas (edited)
locks [12:41 PM]
I already suggested #weaksauce
rwjblue [12:41 PM]
hmm, I wonder what the pluralization of @machty is actually
locks [12:41 PM]
it's @machty
[12:42]
it's also the past tense of the verb @machty (edited)
machty [12:48 PM]
uploaded this image: Pasted image at 2017-01-20, 12:48 PM
Add Comment
machty [12:48 PM]
it even conveniently highlights the closing curlies
[12:48]
:troll:
rwjblue [12:48 PM]
lol
mmun [12:50 PM]
@machty if your rfc lands, do you envision people will stop using {{#my-component}}block{{/my-component}} and migrate to lambda attrs for everything?
machty [12:51 PM]
maybe the result is that "control-flow-y" components stick w positional params + traditional default block (edited)
mmun [12:51 PM]
let me refine my question
[12:52]
do we expect people to use both plain-old-blocks and lambda attrs on a single component (edited)
machty [12:52 PM]
i don't think so
[12:52]
i hope not
mmun [12:52 PM]
power-select is currently designed this way
knownasilya [12:52 PM]
```{{each users &default=(|data| <p>{{data.name}}</p>)}}
```
(edited)
machty [12:54 PM]
yeah i don't think each is a good candidate for this new syntax
[12:54]
but say if you're writing a calendar component and you wanna pass the `day-cell` component into it, then it's pretty good
[12:54]
since day-cell is just one of the things you might want to configure
mmun [12:55 PM]
fwiw, I think most people think of each & if as built-in syntax and it's totally fine to be different (edited)
[12:56]
in power-select, 90% of the time you just want to customize the text that is shown for each option (edited)
[12:56]
so the default block is optimized for that
knownasilya [12:56 PM]
yeah ^
mmun [12:57 PM]
i would even be mad if there was a version of power-select that was attrs-only though. i see it as a minor style thing. (edited)
machty [12:57 PM]
i actually disagree with that
knownasilya [12:57 PM]
```{{power-select options=options
selected=selected
onchange=(action (mut selected))
selectedItemComponent=(|data| <span class="flex">{{data.name}}</span>)
itemDisplayComponent=(|data| {{data.name}})
}}
```
(edited)
machty [12:59 PM]
i think because the present situation limits you to only one lambda block (the main/default), component authors have had to choose which overridable slot is best represented as the default, and all else is relegated to being overridable by attrs (that either point to raw values or (component)s)
knownasilya [12:59 PM]
or is it {{data.item.name}}..
[12:59]
@machty I agree
[12:59]
and it's usually a relative decision..
machty [12:59 PM]
whether we introduce the yield-centric slots RFCs that people have submitted or my RFC, people will start thinking differently / more creatively
mmun [1:00 PM]
what's the part you disagree with?
[1:00]
i agree with what you said 100%
machty [1:01 PM]
i disagree that it's obvious for ember-power-select that assume that the search results be the "winner"
[1:01]
who sits on the default block throne
[1:01]
it's just that there's been no other way to think about it in the past
mmun [1:02 PM]
i agree. i was just describing the status quo above. didn't mean to suggest it is great.
[1:02]
default/inverse blocks work very well for if/each but not for components. same as positional params. it's probably not a coincidence! (edited)
[1:05]
```{{let liWrapper=(|item| <li>{{yield item}}</li>)}}
{{#each-wrapper items wrapper=liWrapper as |item|}}
{{item.name}}
{{/each-wrapper}}
```
(edited)
[1:05]
i can sorta imagine situations where you might want to use both plain-old-blocks and lambdas
[1:06]
mostly for when you're trying to emulate something that should feel like an each/if
[1:06]
but typical application components I can see myself using lambdas only
machty [1:30 PM]
this rfc's gonna be bad for my health
locks [1:31 PM]
mine too
[1:31]
we're in this together now
machty [1:31 PM]
lol are we? i can't tell if i've convinced anyone but myself
knownasilya [1:32 PM]
I like it :slightly_smiling_face:
mmun [1:33 PM]
i'm interested to get feedback from ed and kris
machty [1:33 PM]
moving it into FCP
locks [1:34 PM]
I'll merge
knownasilya [1:34 PM]
lol
locks [1:35 PM]
what about `let` :(
knownasilya [1:35 PM]
yeah both
[1:35]
:+1::+1:
[1:38]
solution to big inline blocks..
rwjblue [1:38 PM]
@machty hmm, I think I told you I am convinced of the larger point?
[1:38]
IMO the important part is support for nesting, and a way to invoke passed blocks
[1:39]
your proposal seems fine as far as it goes, but there are many details still to be fleshed out
knownasilya [1:39 PM]
```{{let itemDisplay=(|data| <span class='item'>{{data.name}}</span>)}}
{{power-select ... itemDisplayComponent=itemDisplay}}
more forms
{{power-select ... itemDisplayComponent=itemDisplay}}
more forms
{{power-select ... itemDisplayComponent=itemDisplay}}
```
mmun [1:40 PM]
i think it's important even to just rally the community around https://embercommunity.slack.com/archives/topic-forms/p1484937536003344 instead of a slot-based solution
rwjblue
IMO the important part is support for nesting, and a way to invoke passed blocks
Posted in #topic-formsToday at 1:38 PM
(edited)
locks [1:40 PM]
I'm trying not to troll with ruby's symbol to proc short hand (edited)
rwjblue [1:41 PM]
@mmun confirm (edited)
locks [1:41 PM]
I also agree with the need for the primitives
rwjblue [1:41 PM]
that part alone was a big AHA for me
machty [1:41 PM]
@knownasilya confirm, slot syntax doesn't solve the use case of passing the same block to multiple components (edited)
rwjblue [1:41 PM]
though I haven't _really_ done react so hadn't been exposed to JSX specifics much
machty [1:50 PM]
set the channel topic: component/yield RFC: <https://github.com/emberjs/rfcs/pull/203>
Backlog manually persisted here:
<https://gist.github.com/machty/68afad4c03109f36d4f4cffaae3c170b>
sclaxton [1:53 PM]
I like the arbitrary nesting of template as data, but worried it sacrifices our current model of template as semantic markup at the altar of consistency (cf. my comment on @machty’s rfc)
[1:53]
it certainly makes things more flexible, but also less structured
[1:53]
which makes sense, since the two are usually at odds
[1:54]
but this seems like lots of yin and no yang, mang (edited)
knownasilya [1:55 PM]
I don't think it's just for consistency, that's secondary really
sclaxton [1:55 PM]
it was most of the RFC heh
knownasilya [1:55 PM]
yeah, maybe some wording has to be changed about why it's usefuly, not being so defensive
locks [1:55 PM]
I'm sensing different definitions of consistency
sclaxton [1:56 PM]
“impedance mismatch” = a consistency argument
[1:56]
and “impedance mismatch” was thrown around a lot in the RFC
knownasilya [1:57 PM]
@machty might be worth mentioning the let rfc as a tag along (edited)
[1:57]
or something that would work well together
sclaxton [1:57 PM]
I 100% percent agree it’s useful
[1:58]
but lots of things are useful
[1:58]
I’m just not convinced I want us to go full template-as-data route
locks [1:59 PM]
that's what templates are
machty [1:59 PM]
i ramped defensiveness up to 9
sclaxton [2:00 PM]
no currently templates are more markup than data
[2:01]
by data I mean stuff that you can pass around as arbitrarily as primitive data
machty [2:17 PM]
added an examples section https://github.com/machty/rfcs/blob/nested-handlebars/text/0000-nested-handlebars-syntax.md#appendix-examples
[2:18]
I feel like nothing that is bad/missing about react is due to the first-class-everything-is-a-component API
[2:19]
the lack of conventions in React that hurt the most surround state mgmt/context/etc
sclaxton [2:20 PM]
agree
[2:21]
but reacts more functional programming model in general is more suited to that API (edited)
machty [2:21 PM]
what about ember/glimmer isn't? (other than we have yet to embrace it)
sclaxton [2:22 PM]
I mean we could become react?
knownasilya [2:22 PM]
@sclaxton you can pass them around, see ember-elsewhere and any other addons that use a service to move components from one place to another
sclaxton [2:23 PM]
pass them around like primitive data
knownasilya [2:23 PM]
pretty much there, like 85%
[2:24]
arbitrary percentage lol
sclaxton [2:24 PM]
I’d say 40%
[2:24]
maybe
[2:24]
anonymous blocks + this RFC would get us to 90% tho haha (edited)
[2:26]
and moving things from one place to another in the dom has nothing to do with passing around template like you would primitive data
[2:27]
that’s just an application of being able to pass it around
[2:27]
so it guess it has something to do , but yah, just an application
knownasilya [2:28 PM]
```{{#my-comp someOtherComp=(component 'my-comp-extension') as |ui|}}
{{other-comp comp=ui.someOtherComp}}
{{/my-comp}}
```
looks like passing data around..
sclaxton [2:28 PM]
yep it is
[2:28]
but with arbitrary data you can pass it as literals
knownasilya [2:28 PM]
shown as block to avoid making multiple tempaltes, obviously a convoluted example
sclaxton [2:28 PM]
which is what anonymous blocks would essentially guess
[2:28]
passing template literals
[2:30]
@machty we also still maintain a strict separation between template and js
[2:30]
which makes treating template fully as data more painful for us than for react
[2:31]
also our templating lang isn’t a superset of a turing complete programming language (edited)
[2:31]
list goes on
locks [2:31 PM]
thank god
sclaxton [2:32 PM]
same
[2:32]
I think there are a number of reasons why template as data works better for react than it would for us
[2:33]
their baked in focus on immutability is another reason (edited)
knownasilya [2:35 PM]
nothing about immutability in react is baked in..
machty [2:35 PM]
added an example integrating w `let` RFC: https://github.com/machty/rfcs/blob/nested-handlebars/text/0000-nested-handlebars-syntax.md#using-in-conjunction-with-let-rfc /cc @cowboyd
knownasilya [2:35 PM]
wish it was, it's pretty annoying
sclaxton [2:36 PM]
well I guess I mean if you’re using immutable.js
machty [2:36 PM]
@sclaxton i don't think anything i'm suggesting breaks the strict separation b/w js/hbs
sclaxton [2:36 PM]
like they support immutability first clsas
machty [2:37 PM]
Glimmer/hbs is still declarative even if we make templates first class values that can be passed around
knownasilya [2:37 PM]
yeah and immutable.js is probably more confusing API wise then ember-data :confused:
sclaxton [2:37 PM]
@machty it doesn’t but I was just saying that makes something liek this easier for react
machty [2:37 PM]
i think that's only because we simply haven't developed such features
[2:37]
it's not fundamentally "easier" for react
[2:37]
we just haven't adopted that pattern yet
[2:37]
it doesn't even make "more sense" for react
sclaxton [2:38 PM]
template being a superset of turing complete language doesn’t make it easier? (edited)
[2:39]
and the fact that that turing complete language happens to be the language as your js component
[2:42]
I have a hard time believing it would be as easy for us as react just because of the properties of JSX
[2:43]
vs the properties of HBS
[2:43]
but also I’m majorly playing devils advocate here, fyi (edited)
samselikoff [2:46 PM]
btw, i’ve personally needed “template-as-data” two or three times in the past two weeks, and i resort to some data-catcher nonsense to get it
knownasilya [2:46 PM]
Feel the same way ^
samselikoff [2:47 PM]
```{{yield (
subnav-item=(component 'data-catcher' on-insert=(action 'registerSubnavItem'))
)}}
```
sclaxton [2:47 PM]
interesting
[2:47]
curious about your use case
samselikoff [2:47 PM]
then the component can `{{each}}` over the data itself
sclaxton [2:47 PM]
could it have also been solved with named slots + contextual components
samselikoff [2:48 PM]
would have to think more on that.
[2:48]
```{{#topbar.app-nav as |nav|}}
{{nav.item routeName="app-nav.one-fish" label="One fish"}}
{{#nav.subnav label="Two fish" as |subnav|}}
{{subnav.item routeName="app-nav.two-fish.black-fish" label="Black fish"}}
{{subnav.item routeName="app-nav.two-fish.blue-fish" label="Blue fish"}}
{{subnav.item routeName="app-nav.two-fish.old-fish" label="Old fish"}}
{{subnav.item routeName="app-nav.two-fish.new-fish" label="New fish"}}
{{/nav.subnav}}
{{nav.item routeName="app-nav.red-fish" label="Red fish"}}
{{nav.item routeName="app-nav.blue-fish" label="Blue fish"}}
{{/topbar.app-nav}}
```
(edited)
[2:48]
it’s basically if I have something like this, and I want to make `<app-nav>` use this listing to make a desktop and mobile version of the nav
[2:48]
you could ask the caller to specify all this in a JS array
[2:48]
but you can see that it’s really more appropriate for this to be in the template
[2:49]
it’s really a data structure
[2:49]
and i just want to capture the data structure, massage it and display it in a certain way
sclaxton [2:50 PM]
that’s what I’m really interested in, what important use cases does slots + contextual components miss out on
mmun [2:50 PM]
block lambdas gives you an obvious solution for this
sclaxton [2:50 PM]
werd
mmun [2:50 PM]
vs. a dynamic slots approach
sclaxton [2:51 PM]
that’s another thing I wonder about, are slots and lambdas interchangable? (edited)
mmun [2:51 PM]
```items=(array
(|| Red fish)
(|| Blue fish)
)
```
sclaxton [2:51 PM]
use case wise
samselikoff [2:51 PM]
`<app-nav>` component basically ends up doing something like this
```{{#each item.subnavItems as |item|}}
{{app-nav/mobile-nav-item navItem=item
on-click=(action 'closeMobileNavAndNavigate')}}
{{/each}}
```
[2:52]
yah but
[2:52]
don’t just want an array. what if they want to add an `{{fa-icon}}` as their label
[2:52]
```{{#nav.item routeName="app-nav.red-fish"}}
Red fish {{fa-icon 'fish'}}
{{/nav.item}}
```
(edited)
[2:52]
thats why i think it belongs in template
machty [2:54 PM]
@sclaxton i definitely don't want hbs/glimmer to be turing complete. i'm proposing making it more powerful within the bounds of declarative / side-effect free constraints
[2:56]
there are features that demonstrate the power of the declarative Glimmer model (where we teach Glimmer where data is coming from and how it updates) that we are not taking advantage of because features are missing
[2:56]
the features i'm proposing my Glimmer flex its power even more than it already does
[2:56]
without breaking any fundamental mental models / side-effect-free / declarative foundations
sclaxton [2:59 PM]
I mean this breaks this major mental model of “a component is like some custom markup that exists within the structure of my plain html document" (edited)
[2:59]
but maybe that mental model isn’t important to us anymore? (edited)
[2:59]
that’s what I’m trying to gauge with my devils advocate bull ish (edited)
slackbot Custom Response [2:59 PM]
:explicitwarning: We'd love for this to remain an awesome place for all Emberers. Helps us out by editing that message. :point_up: https://github.com/cromwellryan/embercommunity-slack-guidelines/blob/master/CodeOfConduct.md
machty [3:03 PM]
```{{let foo=(|d|
Hello {{d.a}}, {{d.b}}, and {{d.c}}!
)}}
<my-component header={{foo}} body={{foo}} />
```
[3:03]
the inline syntax examples that i lead with are just a syntactic nicety that expresses the same as the above
sclaxton [3:04 PM]
I like this better
[3:05]
but I still feel like we lose a little of the structure that’s nice with current components
machty [3:05 PM]
(this also happens to be an example of a use case left unsolved by slot syntax: passing the same block to multiple attrs / components)
sclaxton [3:07 PM]
not sure what you mean by “slots can’t pass the same block to multiple attrs/components"
machty [3:07 PM]
```{{#some-component}}
This is the default, un-named block
{{:block-a as |block|}}
This is block {{block}}
{{:block-b as |block|}}
This is block {{block}}
{{/some-component}}
```
[3:08]
if i wanted to pass the exact same thing to block-a and block-b i would need to duplicate code
[3:08]
the entire block would need to be duplicated (edited)
sclaxton [3:08 PM]
why can’t you use `let` the same way you did in your example
machty [3:08 PM]
with the `let` approach i can define once, pass to both
[3:09]
oh, well, you could
sclaxton [3:09 PM]
I really like the power of let + lambdas
[3:09]
like 100%
[3:10]
jury is still out on slot vs machty components (edited)
machty [3:11 PM]
:+1:
sclaxton [3:12 PM]
discussion has been great tho. so even if this rfc doesn’t make it, was def worth
machty [3:12 PM]
i feel that way too
[3:13]
i could make vague complaints about the cognitive dissonance (as you described) that i feel a lot about ember APIs, but nothing like an RFC to get people to really think about it / address it (edited)
machty [3:21 PM]
set the channel topic: component/yield RFC: https://github.com/emberjs/rfcs/pull/203
Backlog manually persisted here:
<https://gist.github.com/machty/68afad4c03109f36d4f4cffaae3c170b>
rwjblue [3:22 PM]
why you keep doing that?
[3:22]
to notify of logging?
jrowlingson [3:23 PM]
i think thats against the slack TOS
rwjblue [3:23 PM]
not sure, I think bots are against the ToS
[3:23]
he is doing it manually
machty [3:23 PM]
my last attempt to set it made it include a closing angle bracket in the link
rwjblue [3:23 PM]
unless they suggest that copy / pasting is against ToS
machty [3:23 PM]
i think there's a bug with updating the header and preserving a link that was already in there
rwjblue [3:24 PM]
which is pretty WAT
[3:24]
@machty weird?
machty [3:24 PM]
sorry for the noise
rwjblue [3:24 PM]
haha, its all noise!
[3:24]
like that rock and roll the kids listen to these days
[3:25]
:stuck_out_tongue:
----- Today January 21st, 2017 -----
locks [7:14 AM]
https://www.sitepoint.com/using-inline-partials-and-decorators-with-handlebars-4-0/
SitePoint
Using Inline Partials and Decorators with Handlebars 4.0
Ryan Lewis teaches you how to use Inline Partials and Decorators in your own projects employing Handlebars 4.0.
Jan 27th, 2016 at 8:00 AM
[7:17]
hbs 4 is _whack_
knownasilya [8:47 AM]
sure is wack..
locks [8:51 AM]
did one of you link to https://www.youtube.com/watch?v=GXcDQK678_E ?
YouTube Ember Videos
EmberCamp London 2015: : The Hidden Power of HTMLBars by Matthew Beale
[8:51]
i's let-related
locks [8:53 AM]
uploaded this image: Screen Shot 2017-01-21 at 13.52.36.png
Add Comment
rwjblue [10:38 AM]
seems a bit O_o, but we could definitely leverage the syntax for `{{let-block` if we wanted to...
[10:41]
```{{! define the block }}
{#*inline "content-block"}}
My new content
{{/inline}}
{{> content-block}} {{! render it!}}
```
machty [11:50 AM]
Wow didn't know about that
rwjblue [11:52 AM]
@machty well, glimmer is only using Handlebars 3, but @tbieniek and locks have been working on upgrading to Handlebars 4
[11:53]
The blocker to landing the Handlebars 4 PR is that we are going to explicitly throw when we see these inline partials, decorators, etc
[11:54]
but it would be easy to fiddle with things to see about it actually working
locks [12:16 PM]
It's not recursive, is it?
machty [3:07 PM]
breaking my brain imaging how it could be
locks [4:39 PM]
And isn't your rfc?
[4:39]
I think I mean nesting, but more than one level
machty [5:15 PM]
i guess it isn't that brain breaking to imagine how the inline partials could be nested
machty [5:21 PM]
(my rfc definitely is)
machty [5:26 PM]
https://github.com/wycats/handlebars.js/blob/master/spec/partials.js#L328
[5:26]
https://github.com/wycats/handlebars.js/pull/1290
[5:26]
i still haven't confirmed that i've seen an inline partial _in_ an inline partial (edited)
[5:26]
this are close
[5:27]
but still no inline within inline
[5:28]
> After thinking about it a lot (this is kind of a brain-twister), I've come to the conclusions that partial-blocks should be treated like function-closures:
[5:28]
welcome to the club
mmun [5:32 PM]
man it really frustrates me how much syntax landed without cooperation of ember
locks [5:45 PM]
is hbs still string-based?
machty [5:47 PM]
probz
[5:47]
that repo's weird
[5:47]
it houses both the gold standard of the specification while also providing the javascript implementation
sclaxton [5:51 PM]
@mmun didn’t you start a separate hbs spec repo?
[5:51]
what’s the status on that
locks [5:52 PM]
something something mustache/spec
locks [5:52 PM]
is the maintainer of mustache :skull:
sclaxton [5:52 PM]
I think this was a fork of the mustache spec
machty [5:52 PM]
@sclaxton https://github.com/emberjs/rfcs/pull/203#issuecomment-274288879
[5:53]
this guy's (and i can only assume everyone-else-on-the-planet's) gut reaction is that i'm proposing callback hell
[5:53]
i wonder if there's a way your slot syntax would help
[5:53]
your slot syntax and my proposed component-centric semantics (edited)
locks [5:53 PM]
because people pass 20 actions to components
sclaxton [5:54 PM]
tru
mmun [5:54 PM]
Yes. Its on thr back burner
locks [5:54 PM]
and either every single attribute of a model, or the model itself
sclaxton [5:54 PM]
^this is what I think slots might discourage
[5:54]
which is a huge win
locks [5:54 PM]
meh
sclaxton [5:54 PM]
or machty’s rfc
[5:54]
either one (edited)
mmun [5:54 PM]
Wow its on callback hell at all
[5:55]
Blocks are immediately invoked.
sclaxton [5:55 PM]
why meh @locks ?
mmun [5:55 PM]
Guess i should read his comment first tho
machty [5:55 PM]
i suddenly got extremely confused about what people are talking about
locks [5:55 PM]
@sclaxton you're either overestimating or underestimating people ;P
sclaxton [5:55 PM]
probably tru
[5:56]
but it would at least provide a path to pass in less attrs
locks [5:56 PM]
callback hell -> rightwards drift?
machty [5:56 PM]
@sclaxton in my mind, blocks and names blocks are attrs / passed-in-data all the same, just that we've sneakishly put them in a separate namespace so that they don't appear to be
[5:57]
hence `hasBlock.hbs` and `hasBlock.js` RFC and all the unforeseen use cases that come out of the woodwork when we try and hide useful data from people (edited)
sclaxton [5:57 PM]
mmm I disagree that they’re all attrs
[5:57]
I think `{{component}}` has blurred that line
[5:58]
which is either good or bad
[5:58]
I think blocks shouldn’t be accessible for inspection in js
[5:58]
and attrs should
machty [5:58 PM]
:rage4:
sclaxton [5:59 PM]
I could be convinced otherwise :slightly_smiling_face:
mmun [5:59 PM]
I agree with machty strongly :p
sclaxton [5:59 PM]
but that’s just my current thinking
[6:00]
so we should be able to do arbitrary logic manipulating blocks?
[6:00]
in js
locks [6:00 PM]
people already do
mmun [6:00 PM]
It should work like ruby.
sclaxton [6:01 PM]
I mean true, but should they was the question
mmun [6:01 PM]
You can hold on to a block but if you dont satisfy the invariants you're gonna get exceptions. This the price we pay for using a dynamic language
sclaxton [6:01 PM]
what’s the point of logic-less templates if you can do arbitrary logic to play around with blocks
locks [6:01 PM]
they're not logic-less
[6:02]
I need to pester yehuda to talk about this
mmun [6:02 PM]
That is a nonsequtior
sclaxton [6:02 PM]
logic-limited
new messages
[6:02]
hmmm is it?
mmun [6:02 PM]
Logic is not a factor.
[6:02]
Declarativeness is the only factor
sclaxton [6:02 PM]
ok true
[6:03]
I guess my gut is telling me allowing block manipulation in js would break some amount of declarativeness?
mmun [6:03 PM]
Are you familiar with LocalJumpError in ruby?
sclaxton [6:03 PM]
need to think more tho
[6:04]
like you’re moving template related concerns into js
mmun [6:04 PM]
https://ruby-doc.org/core-2.2.2/LocalJumpError.html
ruby-doc.org
Class: LocalJumpError (Ruby 2.2.2)
Class : LocalJumpError - Ruby 2.2.2
[6:04]
The second example is the relevant one
sclaxton [6:04 PM]
so to understand how a template renders you have to go to both js and hbs no?
[6:05]
you’re right, I said logic when I meant declarative lol
[6:05]
oops
mmun [6:06 PM]
1. No one is suggesting that blocks be mutable
sclaxton [6:06 PM]
but you could swap out blocks and stuff no?
[6:07]
if they’re just attrs
[6:07]
not actually mutate
[6:07]
but reassign
mmun [6:07 PM]
Yes you could
locks [6:07 PM]
as you can now
sclaxton [6:07 PM]
thats seems lame
[6:07]
you can mutate components attrs
[6:07]
not bloks
mmun [6:08 PM]
Yes it is but i dont follow your argument
machty [6:08 PM]
added this Markdown (raw) snippet: machty semantics with sclaxton syntax
sclaxton syntax: new slot syntax (rather than nested JSX-y machty syntax)
machty semantics: the named slots actually get passed in as attrs, and are renderable via {{component}}
{{#x-foo other=data
:header as |a|}}
Add Comment Click to expand inline 28 lines
locks [6:08 PM]
and you can manually append components
machty [6:08 PM]
@sclaxton let us smoke a peace pipe on ^
mmun [6:08 PM]
Why are you introducing a JS file when you can do itwithin a template?
sclaxton [6:08 PM]
@mmun i’m just saying that’s why I don’t think blocks should be attrs? (edited)
locks [6:08 PM]
what's : again
machty [6:08 PM]
https://github.com/sclaxton/rfcs/blob/master/text/0000-named-blocks-and-yields.md
mmun [6:09 PM]
Your argument doesnt make sense to me. You can make a CP that toggles between two passed in attr values
[6:09]
You can also just do this logic in tge template which is preferable (edited)
sclaxton [6:10 PM]
right, but we’d be providing both paths
locks [6:10 PM]
I want to reiterate that we already do
mmun [6:10 PM]
That is a fundamental part of ember components and has nothing to do with the values being blocks or not (edited)
[6:11]
Why special case blocks
sclaxton [6:11 PM]
hmm I think mb I just don’t have a clear picture of machy meant by all blocks should be attrs
[6:11]
so we’re on different pages
mmun [6:13 PM]
I hope everyone agrees that keeping declarative view logic in the template is desirable when possible (edited)
sclaxton [6:14 PM]
passing blocks and components the same way you pass data still doesn’t sit well with me (edited)
[6:14]
even tho I fully recognize it’s very useful
[6:14]
like VERY
mmun [6:15 PM]
Lol
machty [6:15 PM]
that viewpoint only makes sense to me if you think `header=(component ...)` is a bad pattern (edited)
sclaxton [6:15 PM]
that’s what I’m saying
machty [6:15 PM]
oof
locks [6:15 PM]
if we want to turn handlebars into lisp, we need to get on board with code is data is code
sclaxton [6:15 PM]
I don’t think it’s a bad pattern per say
[6:16]
I think once you accept it, it leads to many useful patterns
mmun [6:16 PM]
You need to qualify what doesnt sit well with you
sclaxton [6:16 PM]
sure
mmun [6:17 PM]
And you should do so assuming there's no component.js file
sclaxton [6:17 PM]
it’s hard to tell when an attr is primitive data and when it is a piece of template
[6:17]
cause attrs are just attrs
mmun [6:18 PM]
I agree with that.
sclaxton [6:18 PM]
and if you have 20 attrs and they’re intermingling pieces of layout and primitive data it feels weird
mmun [6:19 PM]
Do you think its weird when you make an ajax call that you pass a primitive string URL and a callback?
locks [6:19 PM]
if you have 20 attrs you have other problems
mmun [6:19 PM]
Because this isnt any different
[6:19]
I suspect that you just dont like untyped languages :p
locks [6:20 PM]
but… with TS… you can… :D
machty [6:20 PM]
(having a convenient multiple-blocks + closed over scope API would put a downward pressure on the number of attrs that need to be passed in to otherwise express certain complicated components) (edited)
sclaxton [6:21 PM]
I feel like it’s different because attrs belong to both the js world and the template world but I feel like pieces of template should only belong to template world
[6:21]
does that make sense?
[6:21]
totally down to be convinced otherwise tho
machty [6:22 PM]
it seems like a healthy compromise that template blocks be accessible but read-only in JS
[6:22]
(which they would be w this RFC, and they are today with `attr=(component ...)`) (edited)
sclaxton [6:23 PM]
Maybe it’s not even which world they belong to, but being able to tell it’s a template
mmun [6:23 PM]
How is that a problem? There isnt to worlds. Only javascript.
sclaxton [6:24 PM]
hbs isn’t just js?
[6:24]
to users
mmun [6:25 PM]
If you want to believe that you must atleast allow for opaque values to escape the template layer and return.
[6:26]
I dont see any philisophical problem with that.
sclaxton [6:27 PM]
philosophically there is not
[6:27]
you’re right
[6:27]
theoretically this all makes sense
[6:27]
I guess I’m more worried about the attr soup @locks was talking about
machty [6:27 PM]
I'd like to see the mental model / coding hazards that occur due to letting JS have access to opaque template blocks generated from Hbs. Otherwise we're not gonna get anywhere with "it just feels like they should be separate"
mmun [6:28 PM]
https://embercommunity.slack.com/archives/topic-forms/p1485040817003670
machty
(having a convenient multiple-blocks + closed over scope API would put a downward pressure on the number of attrs that need to be passed in to otherwise express certain complicated components)
Posted in #topic-formsJan 21st at 6:20 PM
[6:28]
Can you unroll that for me? I didnt understand
sclaxton [6:28 PM]
if we make discourage the use of hierarchically structured template definition in favor of passing everything as an attr, that’s just more attr soup
machty [6:29 PM]
@mmun with the single-main template block that you can pass in today, any other snippets of DOM that you want to override can only be approximated by passing in a bunch of additional attributes (where a separate block would have just taken care of it) (which puts an upward pressure on attr count) (edited)
mmun [6:29 PM]
If you allow more {whatever} its {whatever} soup
sclaxton [6:30 PM]
I don’t agree
mmun [6:30 PM]
Blocks, attrs etc
sclaxton [6:30 PM]
in this instance
[6:31]
components mirror html’s hierarchical structure, which is suited to make nested structures readable
mmun [6:32 PM]
@machty is the subtext that high attr count is worse than medium attr + block count? (edited)
machty [6:32 PM]
and strings model arrays of characters; should they have special data-hiding semantics to separate them from references to Number?
[6:33]
@mmun no, that's a point that validates both @sclaxton's and my push for being able to pass multiple template blocks. just saying that regardless of whether template blocks live in their own namespace or are attrs, there will still be a downward pressure on attr count
sclaxton [6:33 PM]
plz convince me that html-style hierarchically structured templates aren’t that important, then I will agree with everything
mmun [6:34 PM]
Why is that a metric being considered
machty [6:34 PM]
@mmun because it's an argument against the idea that attrs=blocks necessarily means attr soup (edited)
[6:34]
@mmun it is a pressure in the opposite direction of attr soup (edited)
sclaxton [6:35 PM]
@machty agree w that
mmun [6:35 PM]
If you design your component poorly your going to have value soup no matter what
[6:35]
Regardless of attr soup
sclaxton [6:35 PM]
but still think html-like hierarchically structured templates are a boon
locks [6:35 PM]
I don't understand ^
mmun [6:35 PM]
The number of things you can use in your template is the same either way
sclaxton [6:36 PM]
@locks my thing?
locks [6:37 PM]
yes
machty [6:38 PM]
```{{#x-foo
headerTitle="..."
headerTagName=...
headerWat=...
...
}}
Look at me, i'm the special one who got to
use the default block API; watch me as i close
over {{foo}} {{bar}} and {{baz}}. Unfortunately
x-foo also renders a header and footer and those
have overrideable bits too, but those overridable
bits can only be passed in as additional attrs,
like `headerTitle=` `headerTagName=` `headerWat=`.
But if we could just pass in multiple blocks w
closed over scope (regardless of whether we go
w machty's / sclaxton's approach), so many
of those attrs can go away.
{{/x-foo}}
```
[6:38]
@sclaxton you haven't responded to my experiment combining your syntax with my semantics
[6:39]
which maintains all the hierarchically structured syntax (as per your designs) (edited)
sclaxton [6:39 PM]
```{{thing}}
{{child}}
{{grand-child}}
{{/child}}
{{/thing}}
```
[6:39]
^ @locks html-like hierarchically structured template (edited)
[6:40]
basically open/close tags
[6:40]
it makes hbs seem like an html-enhancement language, which I think is a valuable way to think of it
mmun [6:40 PM]
So you punt on being able to pass a dynamic amount of blocks e.g. the column case?
machty [6:41 PM]
@mmun thanks for reminding me. yes. i do. and that sucks. i keep forgetting that important use case. and it is important (edited)
sclaxton [6:41 PM]
@machty I need to think about that a little more
[6:41]
gotta bounce tho
mmun [6:41 PM]
Im 2% battery. Good chat ttyl
sclaxton [6:42 PM]
also, sorry I keep bouncing around arguments. having trouble expressing what it is about moving wholesale to template passing via attrs that bothers me
mmun [6:43 PM]
I feel like witg both named blocks and block lamdas everyone would be happy. Cant say if its too much to add tho yet (edited)
sclaxton [6:43 PM]
but I think the loss of html-like hierarchy is a good distillation of it?
locks [6:43 PM]
I don't see how it is, so I think I'm missing something
mmun [6:43 PM]
You must not like yield either then?
machty [6:43 PM]
yeah, i don't think passing in code via `<div>child nesting</div>` is more "hierarchical" / "structural" than passing multiple hierarchies in as attrs (edited)
[6:44]
certainly that is the convention and shared understanding
[6:44]
but i'd like to change that because it's not actually correct
sclaxton [6:49 PM]
How does yield break the hierarchy?
machty [6:49 PM]
yeah i didn't understand that comment either
mmun [6:54 PM]
nevermind
[6:54]
https://embercommunity.slack.com/archives/topic-forms/p1485042185003737
this is a dangerous constraint in the general case
sclaxton
but I think the loss of html-like hierarchy is a good distillation of it?
Posted in #topic-formsJan 21st at 6:43 PM
[6:55]
it limits you from reusing a block
sclaxton [6:55 PM]
How so?
[6:56]
And @machty it basically marks hierarchy with parens for blocks rather than mustache tags
locks [6:57 PM]
you have to make a component if you want to use in a sibling "html scope" (edited)
sclaxton [6:58 PM]
Don't follow
mmun [6:58 PM]
how do you pass the same block to multiple components
sclaxton [7:00 PM]
Same way you would with attrs?
[7:00]
What case is that possible?
[7:01]
Or how does the invariant of open/close tag hierarchy limit that?
mmun [7:01 PM]
```{{let block=(|| ...)}}
{{my-component block=block}}
{{my-component block=block}}
```
sclaxton [7:01 PM]
Also not sure how that's invariant lol
[7:02]
*an invariant
[7:02]
And that wouldn't be possible with current block syntax?
mmun [7:03 PM]
What do you mean current?
[7:03]
anyways, I think that what is needed is a "test suite" of use cases.
sclaxton [7:04 PM]
I think we're misunderstanding each other again lol
mmun [7:04 PM]
I personally don't feel good about strongly optimizing for the singular, named block case but I'd like to hear other people's thoughts.
machty [7:04 PM]
i understand
[7:04]
i shall try to mediate
[7:04]
because i am not tapping a mobile keyboard at dinner :slightly_smiling_face:
mmun [7:05 PM]
I think it's fine for people to say that the multiple columns case is not important to them, but the community should reach consensus
[7:05]
maybe I am over-rotating on it. (edited)
machty [7:05 PM]
agree, just that it's good to make it clear
[7:05]
i should add an example though
[7:05]
so that people will better understand what they'll miss
[7:05]
or maybe you should write it
mmun [7:06 PM]
I'm scared to comment on the rfc
machty [7:06 PM]
lol i understand that
mmun [7:06 PM]
i am too sensitive
[7:06]
:cry:
machty [7:06 PM]
last I heard, @sclaxton liked the idea of lambda block in conjunction with let
[7:07]
and that you'd just reference that lambda in multiple slots if you wanted to use it in multiple places
[7:07]
it just seems like such overlap to introduce both
mmun [7:07 PM]
yeah i hear you 100%
[7:08]
i can only imagine the amount of :confused: emojis we'd get with a dual style rfc
machty [7:10 PM]
also @sclaxton i think you're gonna have to come up with a angle-bracket centric syntax for your RFC since that's the direction things are headed
[7:10]
i'd be curious to see what that'd look like
mmun [7:11 PM]
the rust community has dealt with really hard syntax+semantics issues as well
[7:11]
specifically around higher kinded types
sclaxton [7:11 PM]
Id want to wait for the black param syntax for angle brackets to settle a bit
mmun [7:11 PM]
people have wanted them for _years_ but no one has really submitted a complete design
sclaxton [7:11 PM]
*block
locks [7:11 PM]
you can edit Slack messages
mmun [7:12 PM]
the thing I appreciate about that rust community is that people generally try to work together and understand eachother's constraints
[7:12]
I hope that happens with this RFC. (edited)
locks [7:12 PM]
@machty I don't think there should be an angle brackets syntax
machty [7:13 PM]
yeah
[7:13]
i dunno
[7:13]
as i've mentioned i really don't give 3 damns about angle bracket
locks [7:13 PM]
and that's web components territory :dash:
mmun [7:14 PM]
it makes little sense to discuss the new block stuff with respect to angle bracket components in an RFC today. I think it could be explored casually out of RFC. (edited)
[7:16]
the people who want angle bracket components should be speaking up in the RFC (and writing their own RFC! soon!!!)
locks [7:16 PM]
sure, when there's an rfc :P
machty [7:19 PM]
i think i brought up angle bracket because we're both proposing new syntaxes that don't exist in classic HTML, where the whole construct of "hierarchical" originated and that we are trying to emulate, but the slot syntax doesn't look anything like that and can't really be approximate with html (without doing the WC spec style of nesting slot definitions in the "main block") (edited)
locks [7:20 PM]
that's what I was thinking
machty [7:20 PM]
if what we're proposing can't be expressed in HTML than it's totally a matter of opinion whether one syntax looks more hierarchical than the other
sclaxton [7:29 PM]
Slot syntax delineates hierarchy with mustaches tags
[7:29]
Yours with parens
[7:29]
Mustaches tags are closer to html open/close tag hierarchy imo
[7:30]
And in your syntax all components are all self close
[7:30]
Which I guess is fien
[7:31]
But still stuff that's inside isn't actually going in between the open close tags
[7:31]
Like html
[7:31]
And slots
machty [7:37 PM]
i think we understand each other. hoping we can switch to trying to convince each other based on other tradeoffs
sclaxton [7:40 PM]
I agree, but is it not clear to you that slot stays closer to html style hierarchy structure?
locks [7:41 PM]
https://embercommunity.slack.com/archives/topic-forms/p1485044371003809 crystal clear imo
machty
i think i brought up angle bracket because we're both proposing new syntaxes that don't exist in classic HTML, where the whole construct of "hierarchical" originated and that we are trying to emulate, but the slot syntax doesn't look anything like that and can't really be approximate with html (without doing the WC spec style of nesting slot definitions in the "main block")
Posted in #topic-formsJan 21st at 7:19 PM
machty [7:41 PM]
i guess
[7:41]
but yeah ^^
[7:41]
we're both in fantasy syntax land
[7:41]
i see what you're saying i just don't think it's all that compelling given other more important tradeoffs
locks [7:42 PM]
I'm on that side of the fence as well
sclaxton [7:46 PM]
I don't see the trade offs you have mapping to actual use cases tbh
[7:46]
The trade offs in your rfc are all about how attr nesting will unify the api
[7:48]
But a unified APIs usefulness is also not compelling to me on its own
[7:48]
Both solve usecases
[7:48]
That are wanted
[7:49]
Yours unifies API, slots sticks to current API conventions more closely
[7:49]
To be compelled about your syntax I'm going to need something more concrete than a unified api
machty [7:50 PM]
sounds good
[7:50]
```{{x-table items=users
columns=(array
(hash
name="ID"
template=(|data|
{{data.user.id}}
)
)
(hash
name="Username"
template=(|data|
{{data.user.username}}
)
)
(hash
name="Last Active"
template=(|data|
{{moment data.user.last_active}}
)
)
(hash
name="Actions"
template=(|data|
{{link-to 'Edit' 'user.edit' data.user.id}}
{{link-to 'View' 'user.show' data.user.id}}
{{link-to 'Delete' 'delete-user' data.user.id}}
)
)
)
}}
```
[7:50]
changing topics, need help fleshing out some things
[7:50]
(`[]` array literal and `(asd=123)` hash literal syntax would be nice here)
mmun [7:51 PM]
yeah
locks [7:51 PM]
no commas
[7:51]
it'll trip up JS devs, but it's for the best :P
machty [7:51 PM]
here's an example of dynamic/array template blocks
[7:52]
(this could be approximated with slot syntax if we also passed in an array of column slot names) (edited)
[7:52]
but one thing that's kinda lame is `{{data.user.username}}`
[7:52]
a lameness that wouldn't be present with positional block params
[7:53]
just conceding that for yall so that i don't come off so hard-nosed
mmun [7:53 PM]
bless your soul
machty [7:54 PM]
(another thing i don't like about slot syntax is you'd probably want/need API for getting all the names of slots passed in) (edited)
locks [7:55 PM]
:thinking_face:
[7:55]
since they're not passed as attrs, it'd have to be a special hing
machty [7:55 PM]
exactly
[7:56]
there are strong parallels between my thinking and the extensible web manifesto
mmun [7:56 PM]
I can totally see a slot syntax on the invoking side for the column use case
[7:56]
but the yielding part is blurrier
sclaxton [7:57 PM]
column use case?
machty [7:57 PM]
my example above
mmun [7:57 PM]
ok i've had enough. i'm gonna write in words the use cases :stuck_out_tongue:
sclaxton [7:58 PM]
:raised_hands:
mmun [8:09 PM]
https://usecanvas.com/ember/use-cases-to-consider-for-slotsblocks/1weaFXebNLNPon5boB2RdX
Canvas
Use cases to consider for slots/blocks
Static Slots. Notable examples. ember-power-select has several slots that can be filled if the user provides a component to a specific attribute. Otherwise, a default implementation will be used for the slot. Dynamic Slots. Notable examples. ember-table.
[8:10]
@sclaxton can you see that?
locks [8:10 PM]
table components are kinda dreadful atm
mmun [8:10 PM]
yep
[8:11]
I can flesh that doc out some more later, but am I capturing all the high level use cases?
sclaxton [8:19 PM]
Yeep
[8:19]
Well I don't know about all
[8:19]
But the ones that I've heard about most (edited)
mmun [8:22 PM]
I don't see how the column use case can be handled without treating blocks as data. At the very least you need to be able to index into an array of blocks. (edited)
[8:23]
I welcome strawmen though :slightly_smiling_face:
machty [8:31 PM]
you could do it by also passing in an array
[8:31]
with config including slotName
mmun [8:32 PM]
oh, that's good
machty [8:32 PM]
is it?
[8:33]
what if you also want to pass a template for the header
mmun [8:33 PM]
well i don't love it (because i hate naming things) but it answers my question (edited)
machty [8:33 PM]
yeah
machty [8:55 PM]
```{{x-table items=users
columns=(array
(hash
headerTitle="ID"
cellSlotName="idTemplate"
)
(hash
headerTitle="Username"
cellSlotName="usernameTemplate"
)
(hash
headerSlotName="lastActiveTemplate"
cellSlotName="lastActiveTemplate"
)
(hash
headerTitle="Actions"
cellSlotName="actionsTemplate"
)
)
:idTemplate as |data|}}
{{data.user.id}}
{{:usernameTemplate as |data|}}
{{data.user.username}}
{{:lastActiveTemplate as |data|}}
{{moment data.user.last_active}}
{{:lastActiveHeaderTemplate as |data|}}
Last Active {{clock-emoji}}
{{:actionsTemplate as |data|}}
{{link-to 'Edit' 'user.edit' data.user.id}}
{{link-to 'View' 'user.show' data.user.id}}
{{link-to 'Delete' 'delete-user' data.user.id}}
{{/x-table}}
```
(edited)
machty [9:26 PM]
most people would probably move `columns` to JS (controller/component) (edited)
[9:26]
rather than dabble with `(array)` and `(hash)`
[9:26]
which would work
machty [9:47 PM]
Added the table example to the RFC, including comparison w slot syntax
[9:47]
https://github.com/machty/rfcs/blob/nested-handlebars/text/0000-nested-handlebars-syntax.md#example-table
[9:47]
there's definitely tradeoffs
[9:47]
going into it i thought the template block attrs approach would win on all counts but that's not the case
[9:48]
(i still prefer it with my bias and all, but) slots at least seem "easier", even with some of the repetition of passing slot names around
mmun [10:09 PM]
I have thrown a :wrench:
machty [10:10 PM]
i threw it back
[10:10]
look out
mmun [10:15 PM]
Hahaha
[10:18]
I made my comment more neutral
mmun [10:29 PM]
Do you consider it a _blocker_?
machty [10:31 PM]
no idea
----- Yesterday January 22nd, 2017 -----
locks [4:00 PM]
http://handlebarsjs.com/partials.html what is going on in the "dynamic partial" section
rwjblue [4:01 PM]
locks it is using a helper to get the partial name
[4:01]
`{{> (whichPartial) }}` invokes the `whichPartial` helper
locks [4:05 PM]
so `whichPartial` can't be a variable?
rwjblue [4:11 PM]
inside paren like that makes it a helper invocation
[4:11]
mmun can confirm though
locks [4:12 PM]
sorry, I meant: can't you `{{> someVariable}}` and switch the variable when you want to switch the partial
rwjblue [4:20 PM]
@locks no, I don't think so, because that is going to make a literal partial named `someVariable`
[4:20]
AFAICT
locks [4:21 PM]
huh
machty [10:50 PM]
https://github.com/emberjs/rfcs/pull/203#issuecomment-274394166
[10:51]
@sclaxton have you already started on such a polyfill?
sclaxton [10:52 PM]
it’s essentially done
[10:52]
just covering final acceptance test cases (edited)
machty [10:52 PM]
that's awesome
sclaxton [10:52 PM]
looking forward to publishing
[10:53]
I also really want to somehow fork ember-twiddle to use the polyfill so people can play around with and share example via that interface (edited)
machty [10:53 PM]
same here
[10:53]
i forget the limitations of ember twiddle
sclaxton [10:53 PM]
no addons :disappointed:
machty [10:53 PM]
i think it might not be possible ?
[10:53]
naw twiddle lets you do addons (edited)
[10:54]
but there are some other limitations
sclaxton [10:54 PM]
not broccoli based (edited)
machty [10:54 PM]
yeah that sounds right
sclaxton [10:54 PM]
like it can’t modify the build
machty [10:54 PM]
i couldn't get Emblem to compile
sclaxton [10:54 PM]
cause there is no broccoli build
machty [10:54 PM]
yeah
sclaxton [10:54 PM]
cli is essentially implemented as an ember service
[10:54]
it’s be very easy to monkey patch my polyfill in the service tho
machty [10:55 PM]
i think it'll be fine if there's an examples repo
sclaxton [10:55 PM]
wish there was a non fork path tho
machty [10:55 PM]
and people see that it's live code and they can fork and play around with it
[10:55]
yeah
[10:55]
same
sclaxton [10:56 PM]
this is such a great use case for twiddle ugh
[10:57]
but yeah, either I’ll fork and temporarily deploy the fork under some other domain, or yeah just have an example repo
[10:58]
the idea of getting it to work via twiddle interface has incepted my brain, so tbh I’ll probably just do it, even tho it’s overkill (edited)
machty [10:58 PM]
how?
sclaxton [11:00 PM]
i think it should be pretty trivial to fork, monkey patch, deploy to aws
machty [11:00 PM]
hah
[11:00]
gotcha
sclaxton [11:01 PM]
just asked @gaurav0 about it to get his thoughts
machty [11:25 PM]
it would be extremely badass if you got that working
[11:27]
not that this is a blocker but one thing that i'm not sure there's a good solution for is ambiguous helper/property syntax
[11:28]
`{{maybehelper}}`
[11:28]
the polyfill would have to pass that in
[11:28]
eh i guess that's fine it'd still find the helper
sclaxton [11:33 PM]
hmm what do you mean by pass that in?
[11:35]
the polyfill for slots essentially just parses the named slot syntax with a forked hbs parser, transforms that to valid current hbs syntax, writes the transformed hbs back to the template broccoli tree which is then parsed by the normal template preprocessors (edited)
[11:36]
it totally sidesteps anything ember specific
[11:36]
just an hbs transform
machty [11:46 PM]
how do you transform named slots to valid hbs syntax?
[11:46]
i think our syntaxes might demand different approaches but still seems like i'm not grokking something
sclaxton [11:50 PM]
I transform it to un-named multiple yields that yield a `slotName` and a hash of block params to a block with an if/else chain that conditionally renders the corresponding named slot block based on `slotName`
[11:50]
see this example https://github.com/emberjs/rfcs/pull/72#issuecomment-219174876
machty [11:51 PM]
yeah
sclaxton [11:51 PM]
that comment sparked the whole thing haha
machty [11:51 PM]
makes sense
[11:51]
looks like angular's first router
sclaxton [11:52 PM]
?
machty [11:52 PM]
i just remember ng-route v1 just being switch statements
sclaxton [11:52 PM]
yah basically a switch
[11:54]
the hardest part was grokking the hbs ast tbh
[11:55]
writing the transforms with the hbs ast visitors was pretty mechanical (edited)
[11:55]
actually hardest part was testing lol I take it back
[11:55]
always testing
machty [11:56 PM]
i... am very unlikely to write tests for my polyfill
[11:56]
it's going to look like the homer simpson car
sclaxton [11:56 PM]
haha fair enough
[11:57]
I have a ast fixtures file that’s like a few thousand lines long :joy:
----- Today January 23rd, 2017 -----
machty [12:04 AM]
set the channel topic: Backlog manually persisted here:
<https://gist.github.com/machty/68afad4c03109f36d4f4cffaae3c170b>
machty [12:04 AM]
(figured it was a bit pompous to just have my rfc linked here) (edited)
sclaxton [12:42 AM]
@machty just published the repo if you wanna take a look https://github.com/sclaxton/ember-cli-named-block-slots-polyfill
[12:44]
will likely publish the addon sometime this week
mmun [1:36 AM]
it's kinda interesting that this polyfill is basically what rust does for closures (edited)
[1:36]
it converts them into anonymous structs
[1:41]
if we added named block params to machty's solution i would be willing to accept it. the `data.` is too onerous for me. they're already implemented in glimmer anyways. that still leaves the issue of component vs. yield but it is a much smaller concern because you don't have to worry about postional vs named. (edited)
sclaxton [1:47 AM]
?
[1:48]
what does `data.` refer to?
[1:48]
oh
[1:48]
I gotcha
[1:50]
but yes, `data.` feels boiler platey
mmun [1:53 AM]
the syntax in your rfc is a non-starter for me because it doesn't handle a dynamic number of blocks (edited)
sclaxton [1:53 AM]
@mmun did you get over the fact that machty’s solution doesn’t really fit into vanilla hbs semantics?
mmun [1:54 AM]
well it doesn't _not_ fit into them. we're really far ahead of handlebars in terms of composition
[1:55]
my concern is that it's a lot of syntax to add without semantics. i think we need to figure out the semantics for vanilla hbs
sclaxton [1:55 AM]
I guess it would if you added self-closing block helpers to vanilla hbs?
[1:55]
which is as much work as you would have to do for my syntax change as well
[1:56]
mb less
[1:56]
but def hear you on the dynamic slots
[1:56]
that’s why my read me says “a first pass” heh
[1:56]
been doing some thinking on the dynamic case
mmun [1:57 AM]
even if you use machty's array-of-string-names solution to pass an arbitrary number of named blocks, you still can't pass a _dynamic_ amount
sclaxton [1:57 AM]
I think I may have a solution to that
[1:57]
it’s a little wild
[1:57]
but so is everything lately lol
mmun [1:58 AM]
e.g. your table may have a variable amount of columns depending on how many fields are on your records
sclaxton [1:58 AM]
oh yeah, I don’t have a solution to that yet
[1:58]
lol
mmun [1:59 AM]
it pains me when people want to add a lot of syntax
sclaxton [1:59 AM]
it is painful
mmun [1:59 AM]
vs. adding one primitve that is reusable
[2:01]
when i say "a lot of syntax" what i meant is that there is a product of syntaxes occuring because the new piece of syntax requires a variant of many several existing syntaxes (edited)
[2:01]
namely :block-a, yield:block-a, hasBlock:block-a, etc
[2:01]
where does it end?
[2:01]
does foo-bar:block-a mean something?
sclaxton [2:02 AM]
yes haha
[2:02]
but yeah, perhaps going back to full dynamic slots is preferable
mmun [2:03 AM]
I think there is a very strong syntax argument for it.
[2:03]
There's more to it than that obviously (edited)
sclaxton [2:03 AM]
I just decided to implement this static since that was the main piece of feedback on the other RFCs
[2:03]
and it seemed like that’s where the core team was headed thought wise at the time
[2:04]
from their comments
mmun [2:04 AM]
It also pains me when people suggest content-for
sclaxton [2:04 AM]
yeah no
[2:04]
pls
mmun [2:04 AM]
It's an ok solution but doesn't really support multiple blocks well and requires a funky {{yield} to kick off the side-effects.
[2:04]
we need to document this in a single place.
[2:04]
hmm i kinda recall your rfc mentioned that
[2:05]
what are "full dynamic slots"? wanna make sure i'm on the same page
sclaxton [2:07 AM]
```{{#my-component}}
Good Morning!
{{slot "header"}}
Hello!
{{slot "footer"}}
How Are You?
{{/my-component}}
```
[2:07]
with like `{{yield to="header"}}` in the component def
mmun [2:08 AM]
that requires syntax changes
sclaxton [2:08 AM]
true
mmun [2:09 AM]
hope no-one has a helper called slot either O_o
sclaxton [2:09 AM]
yeah that’s the other thing
[2:09]
you could use some sort of control character to mark a slot section instead
[2:10]
not sure about the exact syntax for that
[2:10]
but that’s the general idea of what I meant by fully dynamic
mmun [2:11 AM]
```{{#my-component}}
Good Morning!
{{*slot "header"}}
Hello!
{{*slot "footer"}}
How Are You?
{{/my-component}}
```
[2:11]
at best it will look something like this
sclaxton [2:11 AM]
I mean adding syntax sucks, but if it’s the right syntax, then it I think it just has to be done
[2:12]
whether this is the right syntax is the quesiton
[2:12]
this = named slots
[2:12]
but yeah, i’m ok with appending a control character
mmun [2:12 AM]
haha, you have no choice
sclaxton [2:13 AM]
or maybe just the control character
[2:13]
unless you make “slot” itself reserved heh
mmun [2:13 AM]
I prefer the lambdas because they are flexible in obvious ways
[2:13]
you want an array of them? ok do it.
sclaxton [2:13 AM]
I mean, I think lambda and named slots are orthogonal no?
[2:13]
you can have both
[2:14]
it’s more like machty’s components + lambdas vs. slots
[2:14]
since machty’s stuff requires lambda’s bassically
mmun [2:14 AM]
you are technically correct but it is cognitive dissonance to be ok with two solutions for this problem but no to be ok with two solutions for component & yield
sclaxton [2:15 AM]
by lambdas do you mean machty’s entire rfc?
[2:15]
or just anon blocks?
mmun [2:15 AM]
generally the latter
[2:16]
but sometimes referring to machty's particular flavor
sclaxton [2:16 AM]
kk
mmun [2:16 AM]
the `data` hash is just tooooo clunky for me
[2:16]
it's as if python named args were given as a hash
[2:17]
it needs more language support (named block args) to satisfy me (edited)
[2:18]
handlebars already has a notation for it
[2:18]
`@foo`
sclaxton [2:18 AM]
ah word
mmun [2:18 AM]
that is _exactly_ the original purpose of `@foo`
[2:18]
to be a named block argument
[2:18]
kinda funny to come full circle
[2:19]
the original issue is that the binding was implicit so that you couldn't rebind it and you would get owned when nesting
[2:20]
```{{#each doctors}}
{{log @item.name}}
{{#each @item.appointments}}
{{log @item.time}}
{{! uh oh, how do you access the doctor? }}
{{/each}}
{{/each}}
```
(edited)
[2:20]
^ handlebars 2.0, pre-block params
sclaxton [2:21 AM]
i c
mmun [2:22 AM]
```{{#each doctors as |item=doctor|}}
{{log doctor.name}}
{{#each doctor.appointments as |item=appointment|}}
{{log appointment.time doctor.location}}
{{/each}}
{{/each}}
```
[2:22]
or maybe
```{{#each doctors as |@item=doctor|}}
{{log doctor.name}}
{{#each doctor.appointments as |@item=appointment|}}
{{log appointment.time doctor.location}}
{{/each}}
{{/each}}
```
sclaxton [2:23 AM]
prefer latter
mmun [2:23 AM]
yeah
sclaxton [2:23 AM]
easier to scan
mmun [2:23 AM]
confirm
[2:24]
so that looks good in the edge case where you need to rebind
[2:24]
what do you think about
```{{#each doctors}}
{{log @item.name}}
{{/each}}
```
```{{#each doctors as |@item|}}
{{log @item.name}}
{{/each}}
```
```{{#each doctors as |@item=|}}
{{log @item.name}}
{{/each}}
```
(edited)
sclaxton [2:25 AM]
argh
mmun [2:25 AM]
the first is just too messed up imo
sclaxton [2:25 AM]
don’t like first heh
mmun [2:26 AM]
(which is the semantics that hbs supports today) (edited)
sclaxton [2:27 AM]
also side note, but I kinda wish we could change `as` to `with`
[2:27]
so it makes for sense for non-iterator like block helpers (edited)
[2:28]
or mb just allow both
[2:28]
but probs not allow both
mmun [2:29 AM]
well
[2:29]
with lambdas... :troll:
sclaxton [2:30 AM]
tru
[2:30]
damn, I’m so close to being ok with machty’s rfc
mmun [2:30 AM]
nah don't be
[2:30]
if you believe in your idea keep pushing it :smile:
[2:32]
in jsx, its very nice that there is a `children` array generated automatically and you dont have to pass everything as props (edited)
sclaxton [2:32 AM]
right
mmun [2:32 AM]
otherwise
```<MyDiv><span><b></b></span></MyDiv>
```
would be... oh god (edited)
sclaxton [2:33 AM]
don’t do it
mmun [2:34 AM]
```<MyDiv children={function() {
return <span children={function() {
return <b />;
}} />;
}} />
```
(edited)
sclaxton [2:36 AM]
which is kind of what we’re moving to
[2:36]
with machty’s rfc (edited)
mmun [2:36 AM]
not exactly!
[2:37]
it's somewhere in between
sclaxton [2:37 AM]
fair
mmun [2:37 AM]
```<MyDiv children={<span><b></b></span>} />
```
(edited)
[2:38]
its only for ember components that you would be passing by props
[2:39]
I still am torn about using parens for delimeters
sclaxton [2:40 AM]
so here’s my current thinking, slots optimize (readability wise mostly I guess but that’s a matter of taste so meh) for the case where you have information about the blocks you expect for the components, machty components + lambdas optimize for the case where you don’t have that information
mmun [2:40 AM]
I think having both slots + lambdas would be nice (edited)
sclaxton [2:40 AM]
so why not optimize for both
[2:41]
the cognitive dissonance will exist probably
[2:41]
but it’s just a question of how much would it exist
mmun [2:42 AM]
i think elixir has both named blocks and lambdas (edited)
sclaxton [2:42 AM]
like why pass in stuff as attrs when you up front know the names of the blocks you’re passing
[2:43]
I think the use case optimization would be the guide to help people through the cognitive dissonance
mmun [2:45 AM]
have you looked at elixir?
sclaxton [2:45 AM]
not really in depth
mmun [2:45 AM]
```iex> if(false, [do: :this, else: :that])
:that
```
(edited)
sclaxton [2:46 AM]
insteresting
mmun [2:46 AM]
if takes a map of do/else
[2:46]
not unlike your named blocks
sclaxton [2:49 AM]
also lambdas would curb the need for dynamic slots?
[2:49]
basically the dynamic use cases could be handled with lambdas
[2:49]
static use cases with static named slots (edited)
mmun [3:23 AM]
yep
[3:24]
add-on authors will need to pick one though
sclaxton [3:24 AM]
why not mix and match?
[3:24]
what if some of your blocks are dynamic in nature
mmun [3:24 AM]
i mean for each "slot" they will need to pick whether they will support lambda/slot/both
[3:25]
and lambdas are applicable in more cases, i.e. a more generic solution (edited)
[3:25]
so i fear for slots :stuck_out_tongue:
sclaxton [3:26 AM]
not sure I follow why they would tend to go whole sale to one
[3:26]
but yeah, there is a choice
[3:27]
it feel like having both would be nice tho
mmun [3:27 AM]
different ppl will design components differently
sclaxton [3:27 AM]
idk mb not
[3:27]
yeah i feel
mmun [3:28 AM]
i would be sad if `{{yield to=(or header 'header')}}` became a thing
sclaxton [3:28 AM]
which is why static slots are good yeah?
mmun [3:29 AM]
it's not an argument for either solution
sclaxton [3:29 AM]
or static named yields rather
[3:29]
cause it prevents logic with yields
mmun [3:29 AM]
that doesn't make a difference
sclaxton [3:29 AM]
oh, what’s undesirable about your example then?
mmun [3:30 AM]
{{#if header}} {{yield one way}} {{else}} {{yield the other way}} {{/if}}
sclaxton [3:30 AM]
I mean can you not already do that?
mmun [3:30 AM]
actually you cant
[3:30]
but that's not the point
sclaxton [3:30 AM]
wait really why can’t you?
mmun [3:31 AM]
huh
[3:31]
you can't to=dynamicThing
[3:31]
must be a string literal
[3:31]
it is treated special at compile time
sclaxton [3:31 AM]
oh ok
[3:31]
makes sense
mmun [3:31 AM]
but that's orthogonal
[3:31]
it could work in theory
[3:31]
or with the #if
[3:32]
the point is that component users will complain/bikeshed to the component authors
[3:32]
about what should be a slot vs. lambda
[3:32]
and component authors will be like "f this, i'll just support both"
sclaxton [3:32 AM]
i see
[3:32]
yeah
[3:36]
so it seems like it’s impossible to have the flexibility we desire while also maintaining the html-like hierarchy I think is important (edited)
[3:38]
the only reason I like slots is because it’s closer to maintaining that
[3:38]
while also allowing to do some things we want to do
[3:40]
being html-like in structure is part of the spirit of handlebars, what makes handlebars what it is, e.g. one of the first first sentences on the handlebars.js home page is “Handlebars templates look like regular HTML, with embedded handlebars expressions." (edited)
[3:41]
if we’re going to get rid of that, we might as well move to another templating language
[3:41]
or just fork completely from hbs
[3:41]
to like ember handlebars or something
[3:41]
ehbs
sclaxton [3:47 AM]
or mb I’m overstating because I’m conflating block helpers with components
[3:48]
since we’re not actually making hbs un-html-like structurally, we’re making components un-html-like structurally (edited)
sclaxton [4:07 AM]
but argument still stands, I wish we could keep components html-like in structure when possible, i.e. in the non-dynamic case (edited)
locks [5:15 AM]
> +Jimmy Bishop Deja vu is a direct alteration of your current timeline by STS 4D beings. /end
[5:16]
just wanted to paste this youtube comment so we realize what these discussions could have been
[5:16]
@sclaxton I'm very confused by your argument
sclaxton [5:24 AM]
@locks removing yield for components means we remove html-like nesting of block *literals* for components (edited)
[5:25]
instead nesting of block literals occurs within attrs definitions (edited)
[5:28]
it might seem like a subtle and trivial change, but it’s a pretty big break from the spirit of the current syntax and semantics of ember components which are from an invocation point of view just handlebars block helpers (edited)
locks [5:29 AM]
but… that happens already
sclaxton [5:29 AM]
it doesn't
[5:29]
block *literals*
[5:29]
that’s why I bolded literals
[5:29]
sure right now we pass in components
[5:30]
but that’s not a literal, so it doesn’t really feel like your nesting in the attrs rather than within open/close tags (edited)
locks [5:30 AM]
that sounds extremely arbitrary
[5:31]
and isn't this why people use ember-elsewhere
sclaxton [5:32 AM]
not sure what ember-elsewhere has to do with this
[5:32]
I’m just saying that nesting literals in attrs breaks the “it looks like regular html” promise of handlebars
[5:33]
cause it doesn’t look like regular html at all
[5:33]
if we want to break that description of embers version of handlebars + components, then fine
locks [5:33 AM]
nothing inside `{{}}` does
sclaxton [5:34 AM]
but as of now you don’t put html literals inside of `{{}}`
[5:34]
so there’s a clear separation
[5:35]
when you’re in `{{}}` you know you’re out of html land
[5:35]
not so in the new syntax
[5:38]
let me phrase the argument like this: right now curlies are self contained and define the boundary between “just html” and hbs syntax, they also nest like child html literal content like html does, with hierarchical open/close tags. With the new syntax machty proposes, there is no such separation between hbs syntax and html literals and there is no such html like nesting of child html literal content.
[5:39]
that’s not arbitrary
locks [5:39 AM]
did you see the inline partial/decorator link I posted the other day?
[5:39]
you still have the boundary ¯\_(ツ)_/¯
sclaxton [5:40 AM]
explain
[5:40]
ples
locks [5:41 AM]
`{{…}}` is handlebars, `(|| …)` is html (edited)
sclaxton [5:41 AM]
you have nested boundaries sure
[5:41]
but that’s harder to grok than just a simple single curly boundary
[5:41]
imo
locks [5:42 AM]
html has no concept of lambdas
[5:42]
so yes, it would be
sclaxton [5:42 AM]
it would be what?
locks [5:42 AM]
harder to grok
sclaxton [5:43 AM]
i mean I’m saying nested boundaries are harder to grok than just a single level `{{}}` boundary, not really the lambdas themselves (edited)
locks [5:44 AM]
we only have nested boundaries because we're introducing lambdas
sclaxton [5:44 AM]
right
[5:44]
but without lambdas you can’t do machty’s thing
locks [5:45 AM]
I don't see anything in the rfc about removing yield
sclaxton [5:45 AM]
so there’s not even a discussion without lambda
[5:45]
oh well, the whole rfc was like “why not yield"
[5:45]
didn’t explicitly say remove it, but it basically did haha (edited)
locks [5:45 AM]
"why not extend the semantics of yield"
sclaxton [5:46 AM]
yield becomes pretty moot once you do the rfc
locks [5:46 AM]
@machty just didn't use as many words
sclaxton [5:47 AM]
and if we don’t remove yield, having nested literals in the attrs and in a classic nested block would be even more confusing (edited)
locks [5:47 AM]
why
[5:48]
it's the same concept
sclaxton [5:48 AM]
because then you have some blocks stuck in the open tag of your component but a special other block in between the tags?
[5:49]
how do you decide when to use the special block between the tags and when to put everything in attrs
locks [5:49 AM]
how do you decide nowadays
sclaxton [5:49 AM]
well you don’t have literal blocks in attrs haha
[5:49]
so it’s not as bad
locks [5:50 AM]
you have `(component)`, it's the same?
sclaxton [5:50 AM]
it’s not
[5:50]
you can’t put html literal content into an attr
[5:50]
so when you need to do that you put in the nested block (edited)
locks [5:51 AM]
```{{let lol (|| <h1>Hello World</h1>)}}
```
there :P
[5:51]
look, we're not going to get anywhere
[5:52]
I'm just not getting it
[5:52]
so I'll spare you having to put up with me
[5:52]
I shall await more discussion from y'all
sclaxton [5:53 AM]
haha sorry if I’m not able to communicate clearly, or if my ideas just don’t make sense :confused:
[5:53]
both are v possible
locks [5:53 AM]
I think you're arguing a strawman, but I don't know how to articulate why
[5:54]
to me `(component)` and `(|| )` are interchangeable
[5:54]
the actual template just isn't colocated
sclaxton [5:54 AM]
ah, but to me they’re very different
locks [5:54 AM]
and it's much nicer than inline decorator/partial syntax that hbs has
sclaxton [5:54 AM]
readability wise
locks [5:54 AM]
imo inline partials in hbs already break your semantics
sclaxton [5:55 AM]
that may be
[5:55]
which sucks
[5:55]
:confused:
locks [5:55 AM]
they don't allow nesting though
sclaxton [5:55 AM]
I’d have to read up on inline partials
locks [5:55 AM]
which is the powerful bit
sclaxton [5:55 AM]
ah, yeah then that’s better I think
[5:56]
but having html in curlies currently does hurt my arguments haha
locks [5:57 AM]
http://handlebarsjs.com/partials.html
[5:57]
it's not inside the curlies, but it looks hella clunky
sclaxton [5:58 AM]
my argument is based on the idea that being able to glance at a template and get a good idea of what the output html might look like is a very good property to have for a template language
locks [5:58 AM]
(hbs doesn't have the concept of components)
sclaxton [5:58 AM]
you can argue that this is already broken by being able to pass components, sure
[5:59]
but I don’t think that’s a good argument for breaking it more
locks [5:59 AM]
by passing components, and by curly components themselves
[5:59]
`{{hello-world}}` gives you no idea what the HTML is going to look like
[6:00]
(neither would `<hello-world>` tbf)
sclaxton [6:00 AM]
right but if you nest like html, you have some idea of the structure still (edited)
[6:00]
or like the “intended” idea of the structure
[6:00]
idkkkk
locks [6:00 AM]
by that reasoning, passing lambdas is better than passing components
[6:00]
since the template is colocated
sclaxton [6:00 AM]
now i’m sounding bullshitty to myself lol
locks [6:01 AM]
fwiw, I think `yield` still has a role
sclaxton [6:02 AM]
putting html literals in an attr doesn’t communicate that it’s a logical child of the component like nesting it between the tags does imo
[6:03]
but yeah, this is getting to be a “be like html cause we should” kind of argument
[6:03]
so
locks [6:04 AM]
I need to reread the html container spec
[6:04]
it didn't make much sense the first times (edited)
sclaxton [6:05 AM]
I think it’s inevitable that some people will think will think maintaining html nesting syntax for component child content is important and some won’t and I likely won’t be able to convince anyone that doesn’t think it’s important that it is, since it’s mostly a “spirit of the syntax” bullshitty sounding argument (edited)
locks [6:14 AM]
I was reading the backlog, and now I want to do inline `each` :troll:
[6:16]
https://embercommunity.slack.com/archives/topic-forms/p1485155499004051 I don't see how this conveys nesting
mmun
```{{#my-component}}
Good Morning!
{{*slot "header"}}
Hello!```
Show more…
Posted in #topic-formsToday at 2:11 AM
sclaxton [6:16 AM]
it’s content that appear between the open and close tag. slots are just “positional nesting” where you mark the position with the slot section. attrs also conveys nesting just fine, just not in a way that’s as inline with html and current handlebars (edited)
[6:17]
of the component
[6:17]
and inline each passing a lambda? lolll
[6:17]
savin those key strokes
locks [6:21 AM]
it's weird that the slots are neither block nor inline (edited)
sclaxton [6:22 AM]
it was meant to mirror
```{{#if something}}
{{! stuff }}
{{else if somethingElse}}
{{! other stuff }}
{{else}}
{{! more stuff }}
{{/if}}
```
[6:23]
they’re just sections, not a standalone entity
locks [6:24 AM]
but
[6:24]
html
[6:24]
:D
sclaxton [6:24 AM]
but they’re in curlies so they don’t have to be heh
[6:25]
and if/else is a well understood, well used structure, so I think it works
locks [6:25 AM]
so are lambdas
[6:25]
both curlies and well understood/used
[6:25]
:D
sclaxton [6:25 AM]
I’m not arguing against lambdas I dont think
[6:25]
well yes i am essentially haha
[6:27]
I like lambdas tho
[6:27]
I just also don’t like losing the html-ness
[6:27]
so i’m torn
[6:27]
not even html-ness really
[6:27]
more like the handlebars-ness
[6:28]
I’m totally cool if we just fork the template lang tho
locks [6:28 AM]
it's not like we 1:1 it
[6:28]
now or ever
sclaxton [6:28 AM]
syntax wise we do no?
[6:28]
semantics wise we don't
locks [6:28 AM]
so it's a matter of picking your poison
[6:29]
changing semantics is a silent failure
sclaxton [6:29 AM]
or actually not sure if that’s the way to phrase it
locks [6:29 AM]
much more insidious
sclaxton [6:30 AM]
I think our semantics changes are additive (edited)
[6:30]
so it’s not like we’re changing semantics
locks [6:32 AM]
and looking at the latest changes, imo hbs forked it for us xD
sclaxton [6:32 AM]
in hbs `{{yield}}` is a helper that outputs something in ember hbs `{{yield}}` outputs the block passed into the block helper corresponding to the component `{{yield}}` is called in
[6:32]
so we’re just specifying what `{{yield}}` outputs in a special way (edited)
[6:34]
and yeah true, the decorators stuff is weird
locks [6:34 AM]
we :scissors: context switching
sclaxton [6:35 AM]
ok, off to sleep
[6:35]
feel sorry for the ppl who choose to catch up on this :joy:
locks [6:35 AM]
no sleep for topic-forms
sclaxton [6:36 AM]
when was the last time forms were discussed?
[6:36]
in the non-platonic sense (edited)
locks [6:37 AM]
who knows :D
locks [6:50 AM]
(nigh night)
====================================
====================================
machty [3:00 PM]
i'm getting salty about positional / named params again
machty [3:01 PM]
uploaded this image: Pasted image at 2017-01-30, 3:01 PM
Add Comment
rwjblue [3:01 PM]
@machty :kissing_cat:
machty [3:01 PM]
what does that even mean
[3:06]
@rwjblue @mmun i'll wait yalls cue to share w the higherups
[3:06]
w the illuminati
rwjblue [3:06 PM]
haha
[3:07]
@machty trying to finish some pretty annoying stuff ATM, I'll re-read fully this evening for sure though
machty [3:07 PM]
no worries
mmun [3:07 PM]
how many times can one man call his own rfc invalid
machty [3:07 PM]
is he a man or a god
rwjblue [3:09 PM]
lol
machty [3:10 PM]
can god submit an RFC so controversial that she is unable to approve it
miguelcobain [3:11 PM]
The omnipotence paradox.
machty [3:12 PM]
can god beat herself at an armwrestle
[3:12]
preeeetty dumb paradox
miguelcobain [3:12 PM]
I think it makes sense.
[3:13]
It basically proves that omnipotence can't exist.
rwjblue [3:13 PM]
or that our logic is flawed :wink:
machty [3:14 PM]
or omniscience
[3:14]
both
[3:14]
can't simultaneously know the future and maintain the ability to change it (edited)
rwjblue [3:14 PM]
ok everyone, please slowly step back from the religion.....
machty [3:14 PM]
can we first decide which one is best?
[3:14]
anywho
rwjblue [3:14 PM]
lol
[3:15]
Obviously, I'm the best
machty [3:15 PM]
while(stack.pop()) {}
rwjblue [3:15 PM]
haha, I read that as `stack.poop()` :stuck_out_tongue:
machty [3:15 PM]
while(stack.:poop:) {} (edited)
rwjblue [3:15 PM]
poopin' on the stacks
machty [3:16 PM]
yeah anywho named args are the shiz
[3:16]
they compose/merge better
[3:16]
lots of yield patterns involve passing a single `(hash bunch=of named=args)`
[3:16]
maybe Ember should just do the daring thing
[3:16]
and standardize on making that pattern nice?
rwjblue [3:17 PM]
firstly, I do not think it is not nice as written
[3:17]
it could however, be nicer
[3:17]
@machty you are ruminating about `(some=hash args=here)` as an alternative?
machty [3:18 PM]
yeah
[3:19]
kinda
rwjblue [3:19 PM]
hehe, ok
machty [3:19 PM]
it helps
rwjblue [3:19 PM]
one thing at a time boss
machty [3:19 PM]
more importantly is the section on forwarding blocks to inner components
[3:20]
anyway it's all in the doc
rwjblue [3:20 PM]
ya, reading
machty [3:20 PM]
i'm "salty" again because regardless of my RFC it felt like the positional/named arg problem kept coming up
rwjblue [3:20 PM]
well, the thing about salt is that it enhances flavor
machty [3:22 PM]
it also fends off rainbow table attacks (edited)
rwjblue [3:23 PM]
heheehehehehehehehehehehhee
[3:23]
@machty RE: ## Syntax Changes Must Be Upstreamed to Handlebars.js
[3:23]
I'm not sold on this as a hard constraint FWIW
[3:23]
IMO we are already planning on "breaking" this compat with `@foo`
[3:24]
(could be that I don't know what I am talking about there though) (edited)
machty [3:24 PM]
just trying to grease the wheels w the stubborn illuminati
[3:24]
"oh but did you think of..." "yes" (edited)
rwjblue [3:24 PM]
ya, I understand
[3:24]
just providing my opinions
[3:25]
RE: ## Syntax must be specified for {{curlies}} and <angle-brackets>
My current thought is to punt on `{{else}}` in GC...
machty [4:08 PM]
i wonder if the handlebars splat helper would be less controversial if we constrained it to only working with hashes generated from within handlebars templates
[4:08]
`{{x-foo ...=splatArgs}}`
[4:09]
if splatArgs is just a JS pojo, then when would glimmer know to update it?
[4:09]
hmm
[4:09]
i'm probably speaking nonsense
[4:09]
but if we similarly applied static constraints to the splat helper then maybe the problem would be simpler
[4:10]
if you generated a glimmer hash via `(hash a=123 b=456)` and then THAT was splatted at some point, i feel like we should be able to handle that efficiently
[4:10]
since it's not just a flattened POJO being passed at every layer (edited)
[4:11]
but just a bundled collection of named args that only needs to be flattened when when crossing the hbs/js layer
cowboyd [4:41 PM]
https://embercommunity.slack.com/archives/topic-forms/p1485807410005743
machty
maybe Ember should just do the daring thing
Posted in #topic-formsToday at 3:16 PM
[4:41]
yes.
[4:42]
I haven’t been able to follow the discussion super closely over the past week, but I feel like there is a deeper issue of data passing that needs to be solved.
[4:42]
how to receive and pass both named and positional arguments with each interface and let everything else decompose into that.
[4:42]
hmm, that sounds gross
mmun [4:44 PM]
something like `{{yield @thing=thing to=someComponentFactory}}` is what's in my mind
which mirrors glimmer component invocation: `<some-component @thing={{thing}} />` (edited)
cowboyd [4:48 PM]
what about `{{(componentFactory 'some-component') @thing=thing}}`?
mmun [4:49 PM]
it could be, but it would need some design work
[4:49]
the point of `{{yield @thing=thing to=someComponentFactory}}` is to unify blocks and components (edited)
cowboyd [4:50 PM]
right, but couldn’t you unify blocks and components just by rendering whatever was at the head of an expression?
[4:50]
I know this is crazy talk, but what if yield wasn’t a keyword
mmun [4:50 PM]
yes, that's all good
[4:51]
but then you need a way to talk about the blocks passed in the old fashioned way (edited)
cowboyd [4:51 PM]
yeah, like supposed the block passed in got bound to an attribute called `yield`
[4:52]
couldn’t you treat `yield` as just an attribute that was a lambda? or even `else` for that matter?
mmun [4:52 PM]
yehuda (mildly) suggested something like that
machty [4:52 PM]
easy there
mmun [4:52 PM]
there's two camps: should blocks need to be in a separate "sigil namespace" or not? (edited)
[4:53]
`{{if @default=@default @inverse=@inverse}}` (edited)
[4:54]
might be nice to take elixir's lead and use `do/else`
[4:54]
unless: `{{if @do=@else @else=@do}}`
[4:55]
that is actually what elixir's if desguars down to O_o (edited)
cowboyd [5:00 PM]
And named blocks would be bound to this sigil namespace automatically?
```{{#if-wat condition}}
True
{{@else}}
False
{{@wat}}
WAT
{{/if-wat}}
```
mmun [5:02 PM]
I'm not sure what you mean there. that syntax is very misleading
[5:02]
are those supposed to represent multiple blocks?
cowboyd [5:05 PM]
I’m trying to understand how those blocks are bound. so, inside the `if-wat`‘s template, I could say
```{{#if condition}}
{{yield to=@default}}
{{else}}
{{yield to=@else}}
{{/if}}
```
[5:05]
or more concisely `{{if condition @do=@default @else=@else}}`
mmun [5:06 PM]
ok here is a coherent proposal, albeit extremely bikesheadable (edited)
cowboyd [5:06 PM]
haha
mmun [5:06 PM]
```{{#unless leaving}}
hello
{{else}}
goodbye
{{/unless}}
```
is sugar for (very bikesheddable)
```{{#unless leaving}}
{{do:}}hello{{/do}}
{{else:}}goodbye{{/else}}
{{/unless}}
```
which is implemented as
```{{if do=else else=do}}
```
(edited)
cowboyd [5:08 PM]
That feels good.
mmun [5:09 PM]
Using glimmer components (obviously we would never impement unless/if like this),
```<ember-unless @condition={{leaving}}>
hello
{{else}}
???
Maybe there is no way to do {{else}} in glimmer components
</ember-unless>
```
is sugar for (very bikesheddable)
```<ember-unless @condition={{leaving}}>
{{do:}}hello{{/do}}
{{else:}}goodbye{{/else}}
</ember-unless>
```
which is implemented as
```<ember-if @condition=@condition @do=@else @else=@do>
```
(edited)
machty [5:09 PM]
this looks nice ^^ (edited)
[5:09]
https://embercommunity.slack.com/archives/topic-forms/p1485812997005792
mmun
the point of `{{yield @thing=thing to=someComponentFactory}}` is to unify blocks and components
Posted in #topic-formsToday at 4:49 PM
[5:10]
how does it unify?
mmun [5:10 PM]
new youtube channel
rwjblue [5:10 PM]
what happened to agreeing on the constraints? :smiling_imp: :troll:
machty [5:10 PM]
a block specifies of a block param and components get attrs?
[5:11]
@rwjblue what we're doing is essential compile-time optimizing needless discussions away (very poor analogy that will distract, please disregard) (edited)
mmun [5:11 PM]
i think what i said satisfies constraints.
[5:11]
and i agree that gathering constraints is the high order bit (edited)
machty [5:12 PM]
my document is pretty much done
[5:12]
i don't think these convos will affect it
mmun [5:12 PM]
that was my impression
machty [5:12 PM]
sorry, i'm still not getting it though
mmun [5:13 PM]
yeah, sorry I didn't make it clear how it unifies on the block side
machty [5:13 PM]
so if you do `{{x-foo someComponentFactory=(component...)}}` then a layout's `{{yield @thing=thing to=someComponentFactory}}` means...
[5:13]
`{{component someComponentFactory thing=thing}}`? (edited)
mmun [5:14 PM]
yes
machty [5:14 PM]
so how would you invoke that component in a named block way? (edited)
mmun [5:16 PM]
`{{#x-foo as |@thing|}} {{log @thing}} {{/x-foo}}`
[5:16]
with `{{yield @thing=thing}}`
[5:17]
with an option to rebind to avoid lexical issues in some cases `{{#x-foo as |@thing=thing1|}} {{log thing1}} {{/x-foo}}` (edited)
cowboyd [5:17 PM]
why not `{{@do @thing=thing}}`?
mmun [5:17 PM]
(although not strictly needed with `{{let}}`) (edited)
[5:18]
lol
[5:18]
yes, I like that too but one step at a time :stuck_out_tongue:
machty [5:20 PM]
yeah @cowboyd i know what you're saying but it's more of a future enhancement
[5:21]
i'm hacking named block params into my hacks
alexander-alvarez [5:21 PM]
the bleeding edge of ember sure is a mindscrew
mmun [5:22 PM]
it is basically ruby block kwargs
rwjblue [5:22 PM]
:joy:
machty [5:23 PM]
@mmun and the @ sigil is there for parity w how args will be passed into glimmer components?
mmun [5:23 PM]
the @ sigil disturbs me
[5:23]
I don't have a good answer for it in the whole picture
[5:23]
(curly components, glimmer components and block arguments)
machty [5:23 PM]
i mentioned the other day how maybe our syntax should unify positional params and named params
[5:23]
@samselikoff responded with "yuck"
[5:24]
but this is kinda what that is
mmun [5:24 PM]
is ruby yuck :cry:
[5:24]
kwargs4life
machty [5:24 PM]
i think something like that's fine so long as (like you said) we make sure to avoid scope pollution
[5:24]
i.e. just because a component layout does `{{yield namedArg=123 ...}}`, you should be able to remap that to another name
mmun [5:24 PM]
scope pollution is a problem with ruby kwargs as well, lemme see what they do (edited)
machty [5:25 PM]
yes, in which case you just don't use the destructure syntax (edited)
[5:25]
(but yes double check me on that)
mmun [5:25 PM]
interesting
machty [5:25 PM]
then you're back to our very favorite friend `d.data.title` :+1:
mmun [5:26 PM]
the purpose of @ for glimmer components is pretty fixed. it's intended to disambiguiate Embery-data-passing from HTMLy-attribute-setting. (edited)
machty [5:26 PM]
the cat emerged to the bag, went straight to the train and drove it away from the station
[5:27]
yeah, that seems good, just wondering if it needs to be `as |@wat|` vs `|wat=|` but confirm seems like a potentially nice opportunity to unify
cowboyd [5:27 PM]
in `{{#x-foo as |@thing=thing1|}}` how do you specify a default value?
mmun [5:27 PM]
default value was not on my radar :stuck_out_tongue:
machty [5:27 PM]
`{{let wat=(or @thing 'lol')}}`
mmun [5:27 PM]
machty for da save
[5:28]
you could do something like `(default @thing 'lol')` to be like `or` but more precise about `undefined` (edited)
samselikoff [5:28 PM]
i like kwargs
machty [5:28 PM]
if we go down this path and have to decide between remapping syntax and default value syntax, remapping should win
cowboyd [5:29 PM]
I agree
machty [5:29 PM]
or maybe it doesn't and the answer in that case is to just use single "pojo"/options arg (edited)
mmun [5:30 PM]
i'm kinda ok with that as long as the pojo args are called out
cowboyd [5:30 PM]
What made me think about it was the `|wat=|` syntax you proposed, which I like, but which also has a strong precedent for a value being on the right hand side, not a symbol used for binding. (edited)
mmun [5:30 PM]
|*d| or something (edited)
machty [5:30 PM]
@cowboyd exactly
[5:30]
tis weird
cowboyd [5:31 PM]
:troll: `|wat='default' as wat1|`
mmun [5:31 PM]
{{let foo = @bar}}
[5:31]
ahah nm we have a winner
[5:32]
`... as |wat='default' as wat1|`
cowboyd [5:32 PM]
trying to think of other ways to have the cake and eat it too....
[5:33]
`:` has precedent as rebinding in ember for properties
[5:33]
`|wat:wat1='default value'|`
mmun [5:33 PM]
I can live with that, and hope it will be needed sparingly.
[5:34]
I worry that fussing over the syntax will turn people off from the feature
[5:35]
`import * as t, { default as Foo }, { foo as bar } from 'foo-bar';`
[5:35]
you can make anything look gnarly in the worst case
[5:36]
what should the simple case look like?
[5:36]
|wat=|?
[5:36]
feels abrupt, but seems to work for ruby/python
[5:37]
should a goal be that you can copy and paste a block into a glimmer component file and have it work?
[5:38]
if so, that would suggest that we need to use |@wat=|
[5:38]
(I'm not really convinced that that should be a goal though, since blocks can close over other stuff anyways) (edited)
machty [5:38 PM]
uploaded this image: Pasted image at 2017-01-30, 5:38 PM
Add Comment
machty [5:39 PM]
added this Diff snippet: diff
diff --git a/tests/dummy/app/templates/application.hbs b/tests/dummy/app/templates/application.hbs
index ffcee84..362b40c 100644
--- a/tests/dummy/app/templates/application.hbs
+++ b/tests/dummy/app/templates/application.hbs
@@ -23,33 +23,33 @@
{{x-table
items=users
columns=(array
- (hash
+ (
headerTitle="ID"
- cell=(|data|
- {{data.item.id}}
+ cell=(|item=|
+ {{item.id}}
)
)
- (hash
+ (
headerTitle="Username"
- cell=(|data|
- {{data.item.username}}
+ cell=(|item=|
+ {{item.username}}
)
)
- (hash
+ (
header=(||
Last <strong>Active</strong>
{{clock-emoji tagName=''}}
)
- cell=(|data|
- {{moment-from-now data.item.last_active interval=1000}}
+ cell=(|item=|
+ {{moment-from-now item.last_active interval=1000}}
)
)
- (hash
+ (
name="Actions"
- cell=(|data|
- {{link-to 'Edit' 'editUser' data.item.id}}
- {{link-to 'View' 'showUser' data.item.id}}
- {{link-to 'Delete' 'deleteUser' data.item.id}}
+ cell=(|item=|
+ {{link-to 'Edit' 'editUser' item.id}}
+ {{link-to 'View' 'showUser' item.id}}
+ {{link-to 'Delete' 'deleteUser' item.id}}
)
)
)
Add Comment Collapse
machty [5:39 PM]
same code as before w 1) (a=1 b=c) hash literal syntax and 2) |asd=| named args
cowboyd [5:40 PM]
I was thinking that the other day @mmun, that it would be nice if you could do that. Basically have a component just be a block with a managed lifecycle. (edited)
[5:40]
and seemlessly upgrade from one to the other
mmun [5:40 PM]
that's pretty close to how glimmer-component is implemented in glimmer today (although it's not shipped) (edited)
cowboyd [5:41 PM]
similar to the way you can have a function be a component in JSX
mmun [5:41 PM]
the "layout" of a component is a block that is invoked with named args
[5:41]
which are referenced with `@foo`
[5:42]
I just want to expose the feature syntactically in `yield` / `as | ... |` (edited)
machty [5:42 PM]
yeah
[5:43]
i agree
cowboyd [5:44 PM]
@machty that is real nice ^^
machty [5:44 PM]
```{{#x-calendar}}
{{:day as |day= isToday=|}}
{{/x-calendar}}
```
[5:44]
is nicer than the lambda syntax
[5:44]
`cell=(|item=|`
[5:44]
specifically in that w lambda syntax and named args you get equal sign stacking ^
[5:44]
but it's not that bad
mmun [5:45 PM]
i dont disagree that slots are nicer 98% of the time
[5:45]
:stuck_out_tongue:
machty [5:45 PM]
yeah
mmun [5:45 PM]
i would feel especially good about it if they were equivalent to a block lambda (despite the feature not existing yet or ever) (edited)
cowboyd [5:46 PM]
yeah, I would think that one would desugar to the other
mmun [5:46 PM]
exactly
machty [5:46 PM]
what does that mean
[5:46]
being able to yield to attr lambda vs slot block? (edited)
cowboyd [5:46 PM]
it means that there is an equivalent form using lambdas
[5:46]
for every named block (at least the way I was thinking about it)
mmun [5:47 PM]
yeah, every named block is just setting an arg of the same name (edited)
cowboyd [5:47 PM]
```{{#x-calendar}}
{{:day as |day= isToday=|}}
{{/x-calendar}}
```
could also be invoked as
```{{x-calendar @day=(|day= isToday=| ....)}}
```
mmun [5:48 PM]
but you would never do that cuz its uglier (i don't strongly believe this, but just playing the part) (edited)
[5:48]
unless you were composing components and passing blocks through by reference (edited)
cowboyd [5:48 PM]
unless you were metaprogramming, in which ugly is beautiful :slightly_smiling_face:
machty [5:49 PM]
@samselikoff so what were you "yuck"ing the other day that's different from today?
samselikoff [5:49 PM]
I need to see the example
[5:49]
I forget I guess
machty [5:49 PM]
i think you heard the words "pollute scope" and vomited in your mouth
samselikoff [5:49 PM]
(I'm not as knee-deep in this as yall but maybe that's good, get someone looking at it fresh)
mmun [5:50 PM]
fwiw, this is exactly the thing yehuda proposed a couple days ago, except he didn't understand (or didn't like ? :disappointed: ) the issue i brought up about named blocks args (edited)
[5:50]
but i feel that is a very important part of the story
machty [5:50 PM]
praise the creator
mmun [5:50 PM]
if he is :-1: kwargs the whole thing kinda crumbles
machty [5:51 PM]
:+1:
mmun [5:51 PM]
maybe i will phrase it in terms of kwargs heh
machty [5:51 PM]
nice
[5:51]
maybe reference an old blog post of his
[5:51]
and his baby
mmun [5:51 PM]
lol
machty [5:52 PM]
it takes 1 part gaslighting, 2 parts incepting
mmun [5:52 PM]
you must be so tired taking care of your new baby
[5:53]
anyways, thanks for approving that rfc about kwargs
samselikoff [5:54 PM]
lol
mmun [5:54 PM]
tbh you can get really far using what I affectionately call machty's hack
machty [5:54 PM]
it's certainly good enough to try out these ideas
mmun [5:54 PM]
columns=(array 'slot-name-1' 'slot-name-2' ...)
machty [5:54 PM]
oh
[5:55]
by machty's hack you mean "what machty calls the slot-centric approach"
[5:55]
not machty's proposed syntax
mmun [5:55 PM]
yeah, i specifically i mean dynamically referencing static blocks
machty [5:55 PM]
yeah
[5:56]
it's a bit watsauce but whatevs
[5:56]
baby steps
mmun [5:56 PM]
yeah
machty [5:56 PM]
i don't have any dynamic use caes
[5:56]
(then again you don't know what you need til someone shows you)
mmun [5:56 PM]
it makes me care about the lambda case 99.99% less
machty [5:56 PM]
yeah sames
mmun [5:56 PM]
and if i were to revisit lambdas it would be for expressions first
[5:56]
rather than blocks
[5:57]
so that cowboyd can map to his dreams content
new messages
cowboyd [5:58 PM]
That’s really the actual use case I care about most anyhow :slightly_smiling_face:
FEB 3rd
machty [12:00 PM]
been reading up on elixir
[12:01]
one of the alleged shortcomings of slot syntaxes is that you can't pass an array of slots
[12:02]
hmm ok well i just jumped 10 steps ahead and answered my own dumb question
[12:03]
anywho i'll just say that keyword args in elixir is interesting
[12:03]
http://elixir-lang.org/getting-started/keywords-and-maps.html
[12:03]
they're just lists of tuples
[12:03]
merging new args over default args doesn't "overwrite" or "clobber" the old arg
[12:03]
the old arg is still in the list, but if you're looking up args by name, the newer one will show up
[12:04]
```iex(23)> new_args = [a: 5]
[a: 5]
iex(24)> default_args ++ new_args
[a: 1, b: 2, a: 5]
iex(26)> combined = new_args ++ default_args
[a: 5, a: 1, b: 2]
iex(27)> combined[:a]
5
```
[12:04]
trying to imagine if there's any value to bringing something like this to ember
[12:04]
`foo=(component 'x-foo' a=1 b=2 c=3)`
[12:04]
which is rendered as `{{component foo a=5}}`
[12:04]
so `x-foo` according to the classic Ember api gets args a=5 b=2 c=3
[12:06]
but maybe it also gets some special `@@args` arg of `(array (hash a=5) (hash c=3) (hash b=2) (hash a=1))`
[12:06]
(or reverse, i dunno)
[12:06]
can't tell whether or not this would/could be a zero-cost abstraction in glimmerland
[12:06]
and whether it'd provide any benefit?
[12:07]
for a moment i was thinking it might be useful for something like
[12:07]
```{{#x-table}}
{{@column as |c|}}
{{@column as |c|}}
{{@column as |c|}}
{{@column as |c|}}
{{/x-table}}
```
[12:09]
but then how would you express header templates?
[12:12]
```{{#x-table}}
{{@header as |c|}}
ID
{{@column as |c|}}
{{c.id}}
{{@header as |c|}}
Name
{{@column as |c|}}
{{c.first_name}} {{c.last_name}}
{{@header as |c|}}
Email
{{@column as |c|}}
{{c.email}}
{{/x-table}}
```
[12:15]
Maybe it'd even be possible to leave out a few header templates or allow for some flexibility
miguelcobain [12:16 PM]
@machty your mental diarrheas are so awesome. Please keep them coming.
[12:16]
(not trolling)
machty [12:17 PM]
it'd be up to `x-table` to decide if/how to handle uneven / missing templates
[12:18]
the idea is it'd be cool to be able to loop through all args
[12:20]
```{{#each @@args as |@name @block|}}
{{#if hasBlock @block}}
{{yield (hash lol=123) to=@block}}
{{/if}}
{{/each}}
```
[12:23]
(btw if you're wondering about all the `@`s, it's seeming more and more likely that it'll be part of the block and generic glimmer attrs syntax)
[12:26]
elixir again:
[12:26]
```iex(30)> IO.inspect do
...(30)> else
...(30)> 0
...(30)> else
...(30)> 1
...(30)> else
...(30)> 2
...(30)> else
...(30)> 3
...(30)> else
...(30)> 4
...(30)> else
...(30)> 5
...(30)> end
[do: nil, else: 0, else: 1, else: 2, else: 3, else: 4, else: 5]
```
(edited)
ryanto [1:24 PM]
similar to concatenated properties? example: classNames, attributeBindings, and such
machty [1:26 PM]
yeah
[1:26]
namedConcatenatedProperties
[1:26]
well, pretty different actually
[1:27]
but there's some overlap
ryanto [1:27 PM]
ha ya
[1:28]
a would be [1,5] instead of args [a, 1][a, 5]
ro0gr [5:31 PM]
joined #topic-forms
machty [9:27 PM]
for anyone who's interested, here's a snapshot of where some of the conversations w the core team have led re: slots / named blocks
[9:27]
https://gist.github.com/machty/d196ff9fb39fe8a9be88cf0176ebf9a1
[9:30]
disclaimer: this is still rough and hardly anyone on the core team's looked at it, but still a decent amount of feedback has been accumulated
mmun [9:31 PM]
there was some issues you raised that i'm not sure if you got answers to
[9:31]
about {{foo-bar @blah=blah}}
machty [9:32 PM]
yeah
mmun [9:36 PM]
> The classic {{else}} will continue to not support block params; if you want block params use {{as @else |a b c|}}.
[9:37]
it's fine to add it as an orthogonal thing, right?
[9:37]
pretty sure yehuda was in favor as well
[9:40]
@machty une idea
[9:41]
if we let @foo=bar be syntax for rebindings, then @@allargs could possible be @=allargs
[9:44]
oh i see, the @@allargs is interesting because it enforces splatting if you use it as an argument
[9:45]
might just cause ppl to pipe it through `hash` first haha
[9:46]
man, I think the as-blockName-blockParams is such a great ret con for using "as" as the separator token (edited)
machty [9:48 PM]
ember's API is one giant retcon
[9:49]
do you agree that we can't/shouldn't do have else in angle-brackets if we have `<as ...>`?
mmun [9:51 PM]
{{else}}?
[9:51]
or sugar for <as @else> in general? i.e. <else> (edited)
[9:52]
i'm open to anything really. at this point everything feels reasonably good and just need to see side by side comparisons with multiple options & situations (edited)
runspired [9:57 PM]
@machty I am against the `<as`
[9:57]
otherwise this seems like it’s starting to shape nicely
[9:58]
(visually it just becomes too hard to tell what’s going on I think)
machty [10:04 PM]
yeah i'm on the fence
[10:04]
proper indentation (not enforced by parser) helps
[10:04]
we might just need more examples
[10:05]
@mmun i mean `<as>` lets us avoid massive changes to Handlebars
[10:05]
but `{{else}}` (within angle brackets) would require those massive changes too (edited)
mmun [10:06 PM]
yeah
knownasilya [10:46 PM]
Left a comment about @arg naming collisions in the gist
mmun [10:53 PM]
yes that's an important consideration
[10:53]
the two solutions are 1) lean on {{let}}, 2) have a rebinding syntax
machty [11:40 PM]
yeah i was assuming #2
[11:41]
without providing an example syntax
----- Yesterday February 6th, 2017 -----
alexander-alvarez [12:14 PM]
@machty are the coffeescript crowd going to get mad at the `@` in hbs not meaing `this`?
machty [12:16 PM]
it does in a way
[12:16]
the way you pass args (what i guess used to be called attrs) in glimmer is `<x-foo @title={{someValue}}>`
[12:16]
and in x-foo's layout template you'll reference it with `{{@title}}`
[12:17]
which may actually be equivalent to `{{this.title}}` (probably not, but conceptually similar)
runspired [12:23 PM]
coffeescript be damned anyway, those folks chose their miserable 3rd class life
----- Today February 7th, 2017 -----
machty [12:25 PM]
```{{#yield a b c to=@thing}}
Here is what gets rendered if @thing isn't passed in.
If @thing is passed in, then it can render this block
with `{{super}}`
{{/yield}}
```
[12:25]
wat?
[12:25]
Vue has a way of defining a default thing that gets rendered when you don't pass in a block
[12:26]
^^ this is a strawman API of something that could do the same
[12:26]
I'm nowhere near super :+1: on this API but wanted to flesh it out more
[12:27]
anyway one open question is: would/should the above pass block params?
[12:27]
it _seems_ weird if it could just close over the data it needs
[12:27]
BUT
[12:27]
one alternative is this block would run with nil scope
[12:27]
zero access to anything other than its block params
[12:28]
the benefit (and a big Middle Finger ™ to all other cons) of this would be that component authors would be forced to pass in all necessary data to properly override a component (edited)
slackbot Custom Response [12:28 PM]
:explicitwarning: We'd love for this to remain an awesome place for all Emberers. Helps us out by editing that message. :point_up: https://github.com/cromwellryan/embercommunity-slack-guidelines/blob/master/CodeOfConduct.md
machty [12:29 PM]
lol
[12:30]
otherwise we might run into a situation where a default block isn't actually externally overridable
[12:30]
but i think the black-holed scope is just too weird
[12:30]
people can PR if there's useful data missing
[12:32]
for context, the alternative of the above syntax is
```{{#if @thing}}
{{yield a b c to=@thing}}
{{else}}
Here is what gets rendered if @thing isn't passed in.
NOTE: there couldn't possibly be any concept of
{{super here since we haven't actually associated
it with `@thing` in any way
{{/if}}
```
sclaxton [12:33 PM]
Orthogonally, yield being a block helper was also part of my idea to have yield render component factories (edited)
machty [12:34 PM]
nice
[12:34]
yeah i think it's worth thinking through
[12:34]
related consideration: one major constraint to block syntax is that it should be trivial to forward such a syntax to other components
sclaxton [12:35 PM]
Its def weird because you'd be essentially binding params to the component while also wrapping it in an anon block
machty [12:35 PM]
if you're a component that accepts `@header` `@body` `@footer` then it should be possible to pass all of those as blocks to `{{default-component @myBlock=@header/footer/body}}`
sclaxton [12:35 PM]
Word
machty [12:35 PM]
but how would you accomplish the above with the proposed syntax
[12:36]
how would you provide a default `@header` block to pass if none was passed into you?
[12:36]
block yield couples "here is a default block" with "render it here, right now"
sclaxton [12:38 PM]
Which proposed syntax?
machty [12:39 PM]
i guess any of them
[12:39]
but assuming `@`-centric
[12:39]
or even any of the ones you've proposed
[12:39]
the only way i can imagine doing it is
[12:40]
```{{let @defaultBody as |a b c|}}
...
{{/let}}
{{wrapper-component @wrapBlock=(or @body @defaultBody)}}
```
[12:41]
and even then i'm not sure the ^ passes the Glimmer static syntax
[12:41]
still awaiting a response from wycats on those semantics
sclaxton [12:41 PM]
mmm gotcha
machty [12:41 PM]
also i'm not sure if ^ is even supported if `@defaultBody` were declared inside the block of another component
[12:43]
```{{#each things as |t|}}
{{let @defaultBlock as |a b c|}}
wat, do I close over `{{t}}` ?
{{/let}}
{{wrapper-component @wrapBlock=(or @default @defaultDefaultBlock)}}
{{/each}}
```
(edited)
[12:43]
also this demonstrates that `@defaultDefault` will be awkward to talk about (edited)
[12:44]
`@default` is possibly a bad name for `{{x-foo}}the unnamed block{{/x-foo}}` (edited)
sclaxton [12:44 PM]
Yeah I've also been thinking about that
[12:44]
Being able to pass in multiple un named blocks
[12:44]
And then somehow index into them
[12:45]
Then all blocks are named
new messages
[12:45]
The "un-named" are just named by an index
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment