Named Arguments (as of 3.1)
In short, with Named Arguments, {{title}}
becomes {{@title}
in the template of {{my-header title=title}
. This helps distinguish component arguments from component properties such as local component state and computed properties.
Here is the original blog post on Named Arguments.
Angle Bracket Invocation (as of 3.4)
Prior to Ember 3.4, components were invoked using double curlies. Now we can invoke them using angle bracket invocation.
Non-Block Component
becomes
<CharactersRemaining @max= @value= />
Block Component
characters remaining
becomes
<CharactersRemaining @max= @value= as |charactersRemaining|>
characters remaining
</CharactersRemaining>
Because component arguments are prefixed with @
, any other attributes on the component invocation will become HTML attributes. For example:
<CharactersRemaining
@max=
@value=
data-test="characters-remaining"
/>
The data-test
attribute will automatically be set as an HTML data attribute on the component's element. No need for attributeBindings
here!
We can even use single word component names with angle bracket invocation! However, this doesn't work when generating a component via Ember CLI at the moment. We can get around this by generating a component with a hyphen and then renaming it to a single word.
If your app isn't on Ember 3.4 or above, you can install the ember-angle-bracket-invocation-polyfill
, which allows you to use angle bracket invocation all the way back to Ember 2.12.
Here is the RFC on Angle Bracket Invocation.
Template-only Glimmer Components (as of 3.1)
Template-only glimmer components are an optional feature that allow us to have components without a JavaScript file. This is great for those cases where we had components with an empty class definition. To get started, install the optional features addon:
ember install @ember/optional-features
Next, enable it with the following in config/option-features.json
:
{
"template-only-glimmer-components": true
}
Now, create a template and that is your component! One thing to note is that your curly expressions need to be prefixed with @
. If we have a component called my-header
with a title
attribute, the template would go from this:
<header></header>
to this:
<header>
</header>
HTML Attribute Spreading with ...attributes
One of my favorite features of angle bracket invocation is being able to capture all HTML attributes and spread them over another element via ...attributes
. I have found this particularly useful with template-only Glimmer components. For example, let's say we created a template-only Glimmer component called required-action-callout
with a template like this:
<div class="alert alert-warning">...</div>
We can invoke it as such:
<RequiredActionCallout class="mt-2" data-test="required-action-callout">
...
</RequiredActionCallout>
In order for div.alert.alert-warning
to get the class mt-2
and the data-test
attribute, we can modify our template as such:
<div class="alert alert-warning" ...attributes>
...
</div>
The final result will be:
<div class="mt-2 alert alert-warning" data-test="required-action-callout">
...
</div>
If you put ...attributes
first, such as:
<div ...attributes class="alert alert-warning">
...
</div>
any attributes in ...attributes
that are present on the element will win out resulting in:
<div class="mt-2" data-test="required-action-callout">
...
</div>
Personally, I have found myself only using ...attributes
as the last thing on an element. Another thing to note is that ...attributes
can only be used within an element position. {{log attributes}}
logs undefined
.
Here is the original blog post on Template-only Glimmer Components.