Class Ember.Templates.helpers
publicaction public
Defined in packages/@ember/-internals/glimmer/lib/helpers/action.ts:14
The {{action}}
helper provides a way to pass triggers for behavior (usually
just a function) between components, and into components from controllers.
Passing functions with the action helper
There are three contexts an action helper can be used in. The first two contexts to discuss are attribute context, and Handlebars value context.
In these contexts,
the helper is called a "closure action" helper. Its behavior is simple:
If passed a function name, read that function off the actions
property
of the current context. Once that function is read, or immediately if a function was
passed, create a closure over that function and any arguments.
The resulting value of an action helper used this way is simply a function.
For example, in the attribute context:
The resulting template render logic would be:
1 2 3 4 5 6 7 |
var div = document.createElement('div'); var actionFunction = (function(context){ return function() { return context.actions.save.apply(context, arguments); }; })(context); div.onclick = actionFunction; |
Thus when the div is clicked, the action on that context is called.
Because the actionFunction
is just a function, closure actions can be
passed between components and still execute in the correct context.
Here is an example action handler on a component:
component.js | |
1 2 3 4 5 6 7 8 |
import Component from ' /component'; import { action } from ' /object'; export default class extends Component { setName(model, name) { model.set('name', name); } } |
or
component.js | |
1 2 3 4 5 6 7 8 |
import Component from '@ember/component'; export default Component.extend({ click() { // Note that model is not passed, it was curried in the template this.sendAction('submit', 'bob'); } }); |
Attaching actions to DOM elements
The third context of the {{action}}
helper can be called "element space".
For example:
Used this way, the {{action}}
helper provides a useful shortcut for
registering an HTML element in a template for a single DOM event and
forwarding that interaction to the template's context (controller or component).
If the context of a template is a controller, actions used this way will
bubble to routes when the controller does not implement the specified action.
Once an action hits a route, it will bubble through the route hierarchy.
Event Propagation
{{action}}
helpers called in element space can control event bubbling. Note
that the closure style actions cannot.
Events triggered through the action helper will automatically have
.preventDefault()
called on them. You do not need to do so in your event
handlers. If you need to allow event propagation (to handle file inputs for
example) you can supply the preventDefault=false
option to the {{action}}
helper:
To disable bubbling, pass bubbles=false
to the helper:
To disable bubbling with closure style actions you must create your own
wrapper helper that makes use of event.stopPropagation()
:
bubbling.js | |
1 2 3 4 5 6 7 8 9 |
import { helper } from '@ember/component/helper'; export function disableBubbling([action]) { return function(event) { event.stopPropagation(); return action(event); }; } export default helper(disableBubbling); |
If you need the default handler to trigger you should either register your
own event handler, or use event methods on your view class. See
"Responding to Browser Events"
in the documentation for Component
for more information.
Specifying DOM event type
{{action}}
helpers called in element space can specify an event type.
By default the {{action}}
helper registers for DOM click
events. You can
supply an on
option to the helper to specify a different DOM event name:
See "Event Names" for a list of acceptable DOM event names.
Specifying whitelisted modifier keys
{{action}}
helpers called in element space can specify modifier keys.
By default the {{action}}
helper will ignore click events with pressed modifier
keys. You can supply an allowedKeys
option to specify which keys should not be ignored.
This way the action will fire when clicking with the alt key pressed down.
Alternatively, supply "any" to the allowedKeys
option to accept any combination of modifier keys.
Specifying a Target
A target
option can be provided to the helper to change
which object will receive the method call. This option must be a path
to an object, accessible in the current context:
app/controllers/application.js | |
1 2 3 4 5 6 |
import Controller from ' /controller'; import { inject as service } from ' /service'; export default class extends Controller { someService; } |
array (options) Array public
Defined in packages/@ember/-internals/glimmer/lib/helpers/array.ts:9
Available since v3.8.0
- options
- Array
- returns
- Array
- Array
Use the {{array}}
helper to create an array to pass as an option to your
components.
or
Would result in an object such as:
1 |
['Tom Date', 'Yehuda Katz', this.get('myOtherPerson')] |
Where the 3rd item in the array is bound to updates of the myOtherPerson
property.
component public
Defined in packages/@ember/-internals/glimmer/lib/helpers/component.ts:5
Available since v1.11.0
The {{component}}
helper lets you add instances of Component
to a
template. See Component for
additional information on how a Component
functions.
{{component}}
's primary use is for cases where you want to dynamically
change which type of component is rendered as the state of your application
changes. This helper has three modes: inline, block, and nested.
Inline Form
Given the following template:
And the following application code:
app/controllers/application.js | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import Controller from '@ember/controller'; import { tracked } from '@glimmer/tracking'; export default class ApplicationController extends Controller { isMarketOpen = 'live-updating-chart' get lastUpdateTimestamp() { return new Date(); } get infographicComponentName() { return this.isMarketOpen ? 'live-updating-chart' : 'market-close-summary'; } } |
And the following component template:
The Last Update: {{this.lastUpdateTimestamp}}
will be rendered in place of the {{yield}}
.
Nested Usage
The component
helper can be used to package a component path with initial attrs.
The included attrs can then be merged during the final invocation.
For example, given a person-form
component with the following template:
When yielding the component via the hash
helper, the component is invoked directly.
See the following snippet:
1 2 3 |
<PersonForm as |form|> <form.nameInput @placeholder="Username" /> </PersonForm> |
or
1 2 3 |
{{#person-form as |form|}} {{form.nameInput placeholder="Username"}} {{/person-form}} |
Which outputs an input whose value is already bound to model.name
and placeholder
is "Username".
When yielding the component without the hash helper use the component
helper.
For example, below is a full-name
component template:
1 2 3 |
<FullName as |field|> {{component field placeholder="Full name"}} </FullName> |
or
1 2 3 |
{{#full-name as |field|}} {{component field placeholder="Full name"}} {{/full-name}} |
concat public
Defined in packages/@ember/-internals/glimmer/lib/helpers/concat.ts:19
Available since v1.13.0
Concatenates the given arguments into a string.
Example:
or for angle bracket invocation, you actually don't need concat at all.
debugger public
Defined in packages/@ember/-internals/glimmer/index.ts:263
Execute the debugger
statement in the current template's context.
When using the debugger helper you will have access to a get
function. This
function retrieves values available in the context of the template.
For example, if you're wondering why a value {{foo}}
isn't rendering as
expected within a template, you could place a {{debugger}}
statement and,
when the debugger;
breakpoint is hit, you can attempt to retrieve this value:
1 |
> get('foo') |
get
is also aware of keywords. So in this situation
You'll be able to get values from the current item:
1 |
> get('item.name') |
You can also access the context of the view to make sure it is the object that you expect:
1 |
context |
each public
Defined in packages/@ember/-internals/glimmer/lib/helpers/each-in.ts:9
The {{#each}}
helper loops over elements in a collection. It is an extension
of the base Handlebars {{#each}}
helper.
The default behavior of {{#each}}
is to yield its inner block once for every
item in an array passing the item as the first block parameter.
Assuming the @developers
argument contains this array:
1 |
[{ name: 'Yehuda' },{ name: 'Tom' }, { name: 'Paul' }]; |
The same rules apply to arrays of primitives.
1 |
['Yehuda', 'Tom', 'Paul'] |
During iteration, the index of each item in the array is provided as a second block parameter.
Specifying Keys
In order to improve rendering speed, Ember will try to reuse the DOM elements where possible. Specifically, if the same item is present in the array both before and after the change, its DOM output will be reused.
The key
option is used to tell Ember how to determine if the items in the
array being iterated over with {{#each}}
has changed between renders. By
default the item's object identity is used.
This is usually sufficient, so in most cases, the key
option is simply not
needed. However, in some rare cases, the objects' identities may change even
though they represent the same underlying data.
For example:
1 2 3 |
people.map(person => { return { ...person, type: 'developer' }; }); |
In this case, each time the people
array is map
-ed over, it will produce
an new array with completely different objects between renders. In these cases,
you can help Ember determine how these objects related to each other with the
key
option:
By doing so, Ember will use the value of the property specified (person.name
in the example) to find a "match" from the previous render. That is, if Ember
has previously seen an object from the @developers
array with a matching
name, its DOM elements will be re-used.
{{else}} condition
{{#each}}
can have a matching {{else}}
. The contents of this block will render
if the collection is empty.
each-in public
Defined in packages/@ember/-internals/glimmer/lib/helpers/each-in.ts:115
Available since v2.1.0
The {{each-in}}
helper loops over properties on an object.
For example, if the @user
argument contains this object:
1 2 3 4 |
{ "name": "Shelly Sails", "age": 42 } |
This template would display all properties on the @user
object in a list:
Outputting their name and age.
fn public
Defined in packages/@ember/-internals/glimmer/lib/helpers/fn.ts:15
Available since v3.11.0
The fn
helper allows you to ensure a function that you are passing off
to another component, helper, or modifier has access to arguments that are
available in the template.
For example, if you have an each
helper looping over a number of items, you
may need to pass a function that expects to receive the item as an argument
to a component invoked within the loop. Here's how you could use the fn
helper to pass both the function and its arguments together:
list.js | |
1 2 3 4 5 6 7 8 |
import Component from ' /component'; import { action } from ' /object'; export default class ItemsList extends Component { handleSelected(item) { // ...snip... } } |
In this case the display-item
component will receive a normal function
that it can invoke. When it invokes the function, the handleSelected
function will receive the item
and any arguments passed, thanks to the
fn
helper.
Let's take look at what that means in a couple circumstances:
- When invoked as
this.args.select()
thehandleSelected
function will receive theitem
from the loop as its first and only argument. - When invoked as
this.args.select('foo')
thehandleSelected
function will receive theitem
from the loop as its first argument and the string'foo'
as its second argument.
In the example above, we used @action
to ensure that handleSelected
is
properly bound to the items-list
, but let's explore what happens if we
left out @action
:
list.js | |
1 2 3 4 5 6 7 |
import Component from ' /component'; export default class ItemsList extends Component { handleSelected(item) { // ...snip... } } |
In this example, when handleSelected
is invoked inside the display-item
component, it will not have access to the component instance. In other
words, it will have no this
context, so please make sure your functions
are bound (via @action
or other means) before passing into fn
!
See also partial application.
get public
Defined in packages/@ember/-internals/glimmer/lib/helpers/get.ts:20
Available since v2.1.0
Dynamically look up a property on an object. The second argument to {{get}}
should have a string value, although it can be bound.
For example, these two usages are equivalent:
If there were several facts about a person, the {{get}}
helper can dynamically
pick one:
For a more complex example, this template would allow the user to switch between showing the user's height and weight with a click:
The {{get}}
helper can also respect mutable values itself. For example:
Would allow the user to swap what fact is being displayed, and also edit that fact via a two-way mutable binding.
hasBlock (the) Boolean public
Defined in packages/@ember/-internals/glimmer/index.ts:184
- the
- String
- name of the block. The name (at the moment) is either "main" or "inverse" (though only curly components support inverse)
- returns
- Boolean
- `true` if the component was invoked with a block
{{has-block}}
indicates if the component was invoked with a block.
This component is invoked with a block:
This component is invoked without a block:
Using angle bracket invocation, this looks like:
1 |
<MyComponent>Hi Jen!</MyComponent> {{! with a block}} |
1 |
<MyComponent/> {{! without a block}} |
This is useful when you want to create a component that can optionally take a block and then render a default template when it is not invoked with a block.
hasBlockParams (the) Boolean public
Defined in packages/@ember/-internals/glimmer/index.ts:226
- the
- String
- name of the block. The name (at the moment) is either "main" or "inverse" (though only curly components support inverse)
- returns
- Boolean
- `true` if the component was invoked with block params
{{has-block-params}}
indicates if the component was invoked with block params.
This component is invoked with block params:
This component is invoked without block params:
This is useful when you want to create a component that can render itself differently when it is not invoked with block params.
hash (options) Object public
Defined in packages/@ember/-internals/glimmer/lib/helpers/hash.ts:9
Available since v2.3.0
- options
- Object
- returns
- Object
- Hash
Use the {{hash}}
helper to create a hash to pass as an option to your
components. This is specially useful for contextual components where you can
just yield a hash:
Would result in an object such as:
1 |
{ name: 'Sarah', title: this.get('office') } |
Where the title
is bound to updates of the office
property.
Note that the hash is an empty object with no prototype chain, therefore
common methods like toString
are not available in the resulting hash.
If you need to use such a method, you can use the call
or apply
approach:
1 2 3 |
function toString(obj) { return Object.prototype.toString.apply(obj); } |
if public
Defined in packages/@ember/-internals/glimmer/lib/helpers/if-unless.ts:50
The if
helper allows you to conditionally render one of two branches,
depending on the "truthiness" of a property.
For example the following values are all falsey: false
, undefined
, null
, ""
, 0
, NaN
or an empty array.
This helper has two forms, block and inline.
Block form
You can use the block form of if
to conditionally render a section of the template.
To use it, pass the conditional value to the if
helper,
using the block form to wrap the section of template you want to conditionally render.
Like so:
You can also specify a template to show if the property is falsey by using
the else
helper.
You are also able to combine else
and if
helpers to create more complex
conditional logic.
Inline form
The inline if
helper conditionally renders a single property or string.
In this form, the if
helper receives three arguments, the conditional value,
the value to render when truthy, and the value to render when falsey.
For example, if useLongGreeting
is truthy, the following:
Will render:
1 |
Hello Alex |
Nested if
You can use the if
helper inside another helper as a nested helper:
or
One detail to keep in mind is that both branches of the if
helper will be evaluated,
so if you have {{if condition "foo" (expensive-operation "bar")
,
expensive-operation
will always calculate.
input (options) public
Defined in packages/@ember/-internals/glimmer/lib/components/input.ts:9
- options
- Hash
let public
Defined in packages/@ember/-internals/glimmer/lib/syntax/let.ts:10
The let
helper receives one or more positional arguments and yields
them out as block params.
This allows the developer to introduce shorter names for certain computations in the template.
This is especially useful if you are passing properties to a component that receives a lot of options and you want to clean up the invocation.
For the following example, the template receives a post
object with
content
and title
properties.
We are going to call the my-post
component, passing a title which is
the title of the post suffixed with the name of the blog, the content
of the post, and a series of options defined in-place.
or
link-to public
Defined in packages/@ember/-internals/glimmer/lib/components/link-to.ts:243
loc (str) public
Defined in packages/@ember/-internals/glimmer/lib/helpers/loc.ts:8
- str
- String
- The string to format.
Calls String.loc with the provided string. This is a convenient way to localize text within a template. For example:
1 2 3 |
Ember.STRINGS = { '_welcome_': 'Bonjour' }; |
1 2 3 |
<div class='message'> Bonjour </div> |
See String.loc for how to set up localized string references.
log (params) public
Defined in packages/@ember/-internals/glimmer/lib/helpers/log.ts:7
- params
- Array
log
allows you to output the value of variables in the current rendering
context. log
also accepts primitive types such as strings or numbers.
mount (name, model) public
Defined in packages/@ember/-internals/glimmer/lib/syntax/mount.ts:63
- name
- String
- Name of the engine to mount.
- model
- Object
- Object that will be set as the model of the engine.
The {{mount}}
helper lets you embed a routeless engine in a template.
Mounting an engine will cause an instance to be booted and its application
template to be rendered.
For example, the following template mounts the ember-chat
engine:
Additionally, you can also pass in a model
argument that will be
set as the engines model. This can be an existing object:
1 2 3 |
<div> {{mount 'admin' model=userSettings}} </div> |
Or an inline hash
, and you can even pass components:
1 2 3 4 5 6 7 |
<div> <h1>Application template!</h1> {{mount 'admin' model=(hash title='Secret Admin' signInButton=(component 'sign-in-button') )}} </div> |
mut (attr) public
Defined in packages/@ember/-internals/glimmer/lib/helpers/mut.ts:9
- attr
- Object
- the "two-way" attribute that can be modified.
The mut
helper lets you clearly specify that a child Component
can update the
(mutable) value passed to it, which will change the value of the parent component.
To specify that a parameter is mutable, when invoking the child Component
:
or
The child Component
can then modify the parent's value just by modifying its own
property:
1 2 3 4 5 6 |
// my-child.js export default Component.extend({ click() { this.incrementProperty('childClickCount'); } }); |
Note that for curly components ({{my-component}}
) the bindings are already mutable,
making the mut
unnecessary.
Additionally, the mut
helper can be combined with the fn
helper to
mutate a value. For example:
or
The child Component
would invoke the function with the new click value:
1 2 3 4 5 6 |
// my-child.js export default Component.extend({ click() { this.get('click-count-change')(this.get('childClickCount') + 1); } }); |
The mut
helper changes the totalClicks
value to what was provided as the fn
argument.
The mut
helper, when used with fn
, will return a function that
sets the value passed to mut
to its first argument. As an example, we can create a
button that increments a value passing the value directly to the fn
:
You can also use the value
option:
on public
Defined in packages/@ember/-internals/glimmer/lib/modifiers/on.ts:215
Available since v3.11.0
The {{on}}
modifier lets you easily add event listeners (it uses
EventTarget.addEventListener
internally).
For example, if you'd like to run a function on your component when a <button>
in the components template is clicked you might do something like:
post.js | |
1 2 3 4 5 6 7 8 9 |
import Component from ' /component'; import { action } from ' /object'; export default class LikePostComponent extends Component { saveLike() { // someone likes your post! // better send a request off to your server... } } |
Arguments
{{on}}
accepts two positional arguments, and a few named arguments.
The positional arguments are:
event
-- the name to use when callingaddEventListener
callback
-- the function to be passed toaddEventListener
The named arguments are:
- capture -- a
true
value indicates that events of this type will be dispatched to the registered listener before being dispatched to any EventTarget beneath it in the DOM tree. - once -- indicates that the listener should be invoked at most once after being added. If true, the listener would be automatically removed when invoked.
- passive -- if
true
, indicates that the function specified by listener will never call preventDefault(). If a passive listener does call preventDefault(), the user agent will do nothing other than generate a console warning. See Improving scrolling performance with passive listeners to learn more.
The callback function passed to {{on}}
will receive any arguments that are passed
to the event handler. Most commonly this would be the event
itself.
If you would like to pass additional arguments to the function you should use
the {{fn}}
helper.
For example, in our example case above if you'd like to pass in the post that was being liked when the button is clicked you could do something like:
post.js | |
1 |
<button {{on 'click' (fn this.saveLike @post)}}>Like this post!</button> |
In this case, the saveLike
function will receive two arguments: the click event
and the value of @post
.
Function Context
In the example above, we used @action
to ensure that likePost
is
properly bound to the items-list
, but let's explore what happens if we
left out @action
:
post.js | |
1 2 3 4 5 6 7 |
import Component from ' /component'; export default class LikePostComponent extends Component { saveLike() { // ...snip... } } |
In this example, when the button is clicked saveLike
will be invoked,
it will not have access to the component instance. In other
words, it will have no this
context, so please make sure your functions
are bound (via @action
or other means) before passing into on
!
outlet (name) public
Defined in packages/@ember/-internals/glimmer/lib/syntax/outlet.ts:24
- name
- String
The {{outlet}}
helper lets you specify where a child route will render in
your template. An important use of the {{outlet}}
helper is in your
application's application.hbs
file:
You may also specify a name for the {{outlet}}
, which is useful when using more than one
{{outlet}}
in a template:
Your routes can then render into a specific one of these outlet
s by specifying the outlet
attribute in your renderTemplate
function:
app/routes/menu.js | |
1 2 3 4 5 6 7 |
import Route from '@ember/routing/route'; export default Route.extend({ renderTemplate() { this.render({ outlet: 'menu' }); } }); |
See the routing guide for more
information on how your route
interacts with the {{outlet}}
helper.
Note: Your content will not render if there isn't an {{outlet}}
for it.
partial (partialName) public
Defined in packages/@ember/-internals/glimmer/index.ts:306
- partialName
- String
- The name of the template to render minus the leading underscore.
The partial
helper renders another template without
changing the template context:
The above example template will render a template named
"-nav", which has the same context as the parent template
it's rendered into, so if the "-nav" template also referenced
{{foo}}
, it would print the same thing as the {{foo}}
in the above example.
If a "-nav" template isn't found, the partial
helper will
fall back to a template named "nav".
Bound template names
The parameter supplied to partial
can also be a path
to a property containing a template name, e.g.:
The above example will look up the value of someTemplateName
on the template context (e.g. a controller) and use that
value as the name of the template to render. If the resolved
value is falsy, nothing will be rendered. If someTemplateName
changes, the partial will be re-rendered using the new template
name.
query-params (hash) Object public
Defined in packages/@ember/-internals/glimmer/lib/helpers/query-param.ts:10
- hash
- Object
- takes a hash of query parameters
- returns
- Object
- A `QueryParams` object for `{{link-to}}`
This is a helper to be used in conjunction with the link-to helper. It will supply url query parameters to the target route.
textarea public
Defined in packages/@ember/-internals/glimmer/lib/components/textarea.ts:122
See Ember.Templates.components.Textarea.
unbound public
Defined in packages/@ember/-internals/glimmer/lib/helpers/unbound.ts:9
The {{unbound}}
helper disconnects the one-way binding of a property,
essentially freezing its value at the moment of rendering. For example,
in this example the display of the variable name
will not change even
if it is set with a new value:
Like any helper, the unbound
helper can accept a nested helper expression.
This allows for custom helpers to be rendered unbound:
The unbound
helper only accepts a single argument, and it return an
unbound value.
unless public
Defined in packages/@ember/-internals/glimmer/lib/helpers/if-unless.ts:147
The unless
helper is the inverse of the if
helper. It displays if a value
is falsey ("not true" or "is false"). Example values that will display with
unless
: false
, undefined
, null
, ""
, 0
, NaN
or an empty array.
Inline form
The inline unless
helper conditionally renders a single property or string.
This helper acts like a ternary operator. If the first property is falsy,
the second argument will be displayed, otherwise, the third argument will be
displayed
For example, if useLongGreeting
is false below:
Then it will display:
1 |
Hi |
You can use the unless
helper inside another helper as a subexpression.
If isBig is not true, it will set the height to 10:
or
Block form
Like the if
helper, unless
helper also has a block form.
You can also use an else
helper with the unless
block. The
else
will display if the value is truthy.
If userData
is false, undefined, null, or empty in the above example,
then it will render:
1 |
Please login. |
with (options) String public
Defined in packages/@ember/-internals/glimmer/index.ts:91
- options
- Object
- returns
- String
- HTML string
Use the {{with}}
helper when you want to alias a property to a new name. This is helpful
for semantic clarity as it allows you to retain default scope or to reference a property from another
{{with}}
block.
If the aliased property is "falsey", for example: false
, undefined
null
, ""
, 0
, NaN
or
an empty array, the block will not be rendered.
NOTE: The alias should not reuse a name from the bound property path.
For example: {{#with foo.bar as |foo|}}
is not supported because it attempts to alias using
the first part of the property path, foo
. Instead, use {{#with foo.bar as |baz|}}
.
yield (options) String public
Defined in packages/@ember/-internals/glimmer/index.ts:123
- options
- Hash
- returns
- String
- HTML string
{{yield}}
denotes an area of a template that will be rendered inside
of another template.
Use with Component
When designing components {{yield}}
is used to denote where, inside the component's
template, an optional block passed to the component should render:
Result:
1 2 3 |
<label> First name: <input type="text" /> </label> |
Additionally you can yield
properties into the context for use by the consumer:
Result:
1 2 3 4 |
<label> <p class="error">First Name must be at least 3 characters long.</p> First name: <input type="text" /> </label> |