Hi everyone,
I’m updating the Rock & Roll with Ember.js book to 3.10 and started converting the built-in components to the angle-bracket syntax (see release blog post).
Both the release blog post and the original RFC gives examples where the HTML attributes passed to these components are prefixed with @
:
<Input
@type="text"
@class="rr-input"
@placeholder="New band"
@value={{newBandName}}
/>
This just doesn’t feel right to me, let me explain why.
One of the advantages of angle-bracket invocation is that readers of the template can easily tell apart at a glance HTML attributes from component arguments. One such example would be:
<StarRating
class="fr"
@rating={{song.rating}}
@onClick={{action "updateRating" song}}
/>
I can see right away that class
is an HTML attribute (and will be bound to the outer element in classic components) @rating
and @onClick
are component arguments.
Prefixing all keys of a component call with @
blurs that line and is also very hard to teach. Why should one use class
for custom (non built-in) components and @class
in built-in ones? Why make an exception with what could be regarded as teaching examples?
I went ahead and tried using non-prefixed keys for Input
, Textarea
and LinkTo
and it works for all attributes, except value
:
<Input
type="text"
class="rr-input"
placeholder="New band"
@value={{newBandName}}
/>
<LinkTo
@route="bands.band"
@model={{band.id}}
class="rr-band-link"
data-test-rr="band-link"
>
{{capitalize band.name}}
<span class="rr-pointer">
{{fa-icon "angle-right"}}
</span>
</LinkTo>
<Textarea
class="rr-textarea"
data-test-rr="band-description-field"
@value={{@band.description}}
@focus-out={{action (mut showErrors.description) true}}
/>
There is probably a reason I’m missing but if we have to use @class
, @type
, @disabled
, @placeholder
, I’d like to understand it.
1 Like
The RFC specifically mentions this:
As mentioned above, this will allow Ember developers to invoke components with a consistent syntax, which should make it easier to teach.
This RFC does not aim to “fix” issues or quirks with the existing APIs – it merely attempts to provide a way to do the equivalent invocation in angle bracket syntax.
Specifically, because we have existing Ember.Component
implementations that folks are currently relying on (e.g. for extending) that accept these things as arguments (since there was no other way prior to angle invocation). This is why the argument forms are “still around”. For all of the arguments that are only used internally for attributeBindings
, I personally would absolutely pass them as attributes (the non-@
prefixed versions) instead of arguments.
As the guides are updated for the newer angle bracket invocation I’d expect the attribute passing to be used wherever possible.
1 Like
For example, in ember-learn/guides-source#797 you’ll notice passing some attributes. Though most of the examples of {{input}}
in the guides didn’t use the arguments that were just used for attributeBindings
.
1 Like
I understood this as providing a consistent syntax, namely angle-bracket invocation, to call all components whether built-in or not. Not how keys in the component call are prefixed.
Ah, I have now found this comment in the source code of the Input component (link) (sorry, should have read the source first )
### `<input>` HTML Attributes to Avoid
In most cases, if you want to pass an attribute to the underlying HTML `<input>` element, you
can pass the attribute directly, just like any other Ember component.
(...)
However, there are a few attributes where you **must** use the `@` version.
* `@type`: This argument is used to control which Ember component is used under the hood
* `@value`: The `@value` argument installs a two-way binding onto the element. If you wanted a
one-way binding, use `<input>` with the `value` property and the `input` event instead.
* `@checked` (for checkboxes): like `@value`, the `@checked` argument installs a two-way binding
onto the element. If you wanted a one-way binding, use `<input type="checkbox">` with
`checked` and the `input` event instead.
The “non-special” attributes that just work (class
, placeholder
, disabled
, cols
, rows
, etc.) are not explicitly included in attributeBindings
or at least I haven’t found them. I assume they work in some other way.
Anyway, thanks a ton, things are definitely clearer now!
2 Likes