File System Nesting

Components can be nested inside sub-folders for logical groupping. For
example, if we placed our template in
app/templates/components/person/short-profile.hbs, we can invoke it as
<Person::ShortProfile />:

app/templates/application.hbs

1

<Person::ShortProfile @person={{this.currentUser}} />

Or equivalently, {{person/short-profile}}:

app/templates/application.hbs

1

{{person/short-profile person=this.currentUser}}

Yielding Contents

You can use yield inside a template to include the contents of any block
attached to the component. The block will be executed in its original context:

1
2
3
4

<PersonProfile @person={{this.currentUser}}><p>Admin mode</p>{{! Executed in the current context. }}</PersonProfile>

or

1
2
3
4

{{#person-profileperson=this.currentUser}}<p>Admin mode</p>{{! Executed in the current context. }}{{/person-profile}}

profile.hbs

1
2

<h1>{{@person.name}}</h1>{{yield}}

Customizing Components With JavaScript

If you want to customize the component in order to handle events, transform
arguments or maintain internal state, you implement a subclass of Component.

class attribute values can also be set by providing a classNameBindings
property set to an array of properties names for the component. The return
value of these properties will be added as part of the value for the
components's class attribute. These properties can be computed properties:

If the value of a class name binding returns a boolean the property name
itself will be used as the class name if the property is true. The class name
will not be added if the value is false or undefined.

Custom Class Names for Boolean Values

When using boolean class name bindings you can supply a string value other
than the property name for use as the class HTML attribute by appending the
preferred value after a ":" character when defining the binding:

Invoking this component when the isEnabled property is true will produce
HTML that looks like:

1

<divid="ember1"class="ember-view"></div>

Invoking it when the isEnabled property on the component is false will
produce HTML that looks like:

1

<divid="ember1"class="ember-view disabled"></div>

Updates to the value of a class name binding will result in automatic update
of the HTML class attribute in the component's rendered HTML
representation. If the value becomes false or undefined the class name
will be removed.

Both classNames and classNameBindings are concatenated properties. See
EmberObject documentation for more
information about concatenated properties.

Other HTML Attributes

The HTML attribute section of a component's tag can be set by providing an
attributeBindings property set to an array of property names on the component.
The return value of these properties will be used as the value of the component's
HTML associated attribute:

Handling Browser Events

Components can respond to user-initiated events in one of three ways: passing
actions with angle bracket invocation, adding event handler methods to the
component's class, or adding actions to the component's template.

Passing Actions With Angle Bracket Invocation

For one-off events specific to particular instance of a component, it is possible
to pass actions to the component's element using angle bracket invocation syntax.

In this case, when the first component is clicked on, Ember will invoke the
firstWidgetClicked action. When the second component is clicked on, Ember
will invoke the secondWidgetClicked action instead.

Besides {{action}}, it is also possible to pass any arbitrary element modifiers
using the angle bracket invocation syntax.

Event Handler Methods

Components can also respond to user-initiated events by implementing a method
that matches the event name. This approach is appropriate when the same event
should be handled by all instances of the same component.

An event object will be passed as the argument to the event handler method.

widget.js

1
2
3
4
5
6
7
8
9

import Component from'@ember/component';
exportdefault Component.extend({
click(event) {
// `event.target` is either the component's element or one of its childrenlet tag = event.target.tagName.toLowerCase();
console.log('clicked on a `<${tag}>` HTML element!');
}
});

In this example, whenever the user clicked anywhere inside the component, it
will log a message to the console.

It is possible to handle event types other than click by implementing the
following event handler methods. In addition, custom events can be registered
by using Application.customEvents.

Touch events:

touchStart

touchMove

touchEnd

touchCancel

Keyboard events:

keyDown

keyUp

keyPress

Mouse events:

mouseDown

mouseUp

contextMenu

click

doubleClick

focusIn

focusOut

Form events:

submit

change

focusIn

focusOut

input

Drag and drop events:

dragStart

drag

dragEnter

dragLeave

dragOver

dragEnd

drop

{{action}} Helper

Instead of handling all events of a particular type anywhere inside the
component's element, you may instead want to limit it to a particular
element in the component's template. In this case, it would be more
convenient to implement an action instead.

For example, you could implement the action hello for the person-profile
component:

Once you call this method, any time the key's value is set, your observer
will be notified. Note that the observers are triggered any time the
value is set, regardless of whether it has actually changed. Your
observer should be prepared to handle that.

There are two common invocation patterns for .addObserver():

Passing two arguments:

the name of the property to observe (as a string)

the function to invoke (an actual function)

Passing three arguments:

the name of the property to observe (as a string)

the target object (will be used to look up and invoke a
function on)

the name of the function to invoke on the target object
(as a string).

The sender is the object that changed. The key is the property that
changes. The value property is currently reserved and unused. The rev
is the last property revision of the object when it changed, which you can
use to detect if the key value has really changed or not.

Usually you will not need the value or revision parameters at
the end. In this case, it is common to write observer methods that take
only a sender and key value as parameters or, if you aren't interested in
any of these values, to write an observer that has no parameters at all.

didReceiveAttrspublic

Called when the attributes passed into the component have been updated.
Called both during the initial render of a container and during a rerender.
Can be used in place of an observer; code placed here will be executed
every time any attribute updates.

When you call get on a computed property, the function will be
called and the return value will be returned instead of the function
itself.

Unknown Properties

Likewise, if you try to call get on a property whose value is
undefined, the unknownProperty() method will be called on the object.
If this method returns any value other than undefined, it will be returned
instead. This allows you to implement "virtual" properties that are
not defined upfront.

NOTE: If you do override init for a framework class like Ember.View,
be sure to call this._super(...arguments) in your
init declaration! If you don't, Ember may not have an opportunity to
do important setup work, and you'll see strange behavior in your
application.

Sometimes you need to change a value directly or indirectly without
actually calling get() or set() on it. In this case, you can use this
method instead. Calling this method will notify all observers that the
property has potentially changed value.

person.on('didLoad', function(){
// fired once the person has loaded
});

An optional target can be passed in as the 2nd argument that will
be set as the "this" for the callback. This is a good way to give your
function access to the object triggering the event. When the target
parameter is used the callback method becomes the third argument.

Subscribes a function to a named event and then cancels the subscription
after the first time the event is triggered. It is good to use one when
you only care about the first time an event has taken place.

This function takes an optional 2nd argument that will become the "this"
value for the callback. When the target parameter is used the callback method
becomes the third argument.

readDOMAttr
(name)
public

Normally, Ember's component model is "write-only". The component takes a
bunch of attributes that it got passed in, and uses them to render its
template.

One nice thing about this model is that if you try to set a value to the
same thing as last time, Ember (through HTMLBars) will avoid doing any
work on the DOM.

This is not just a performance optimization. If an attribute has not
changed, it is important not to clobber the element's "hidden state".
For example, if you set an input's value to the same value as before,
it will clobber selection state and cursor position. In other words,
setting an attribute is not always idempotent.

This method provides a way to read an element's attribute and also
update the last value Ember knows about at the same time. This makes
setting an attribute idempotent.

In particular, what this means is that if you get an <input> element's
value attribute and then re-render the template with the same value,
it will avoid clobbering the cursor and selection position.
Since most attribute sets are idempotent in the browser, you typically
can get away with reading attributes using jQuery, but the most reliable
way to do so is through this method.

rerenderpublic

Renders the view again. This will work regardless of whether the
view is already in the DOM or not. If the view is in the DOM, the
rendering process will be deferred to give bindings a chance
to synchronize.

If children were added during the rendering process using appendChild,
rerender will remove them, because they will be added again
if needed by the next render.

In general, if the display of your view changes, you should modify
the DOM element directly instead of manually calling rerender, which can
be slow.

Triggers a named action on the ActionHandler. Any parameters
supplied after the actionName string will be passed as arguments
to the action target function.

If the ActionHandler has its target property set, actions may
bubble to the target. Bubbling happens when an actionName can
not be found in the ActionHandler's actions hash or if the
action target function returns true.

This method is generally very similar to calling object["key"] = value or
object.key = value, except that it provides support for computed
properties, the setUnknownProperty() method and property observers.

Computed Properties

If you try to set a value on a key that has a computed property handler
defined (see the get() method for an example), then set() will call
that method, passing both the value and key instead of simply changing
the value itself. This is useful for those times when you need to
implement a property that is composed of one or more member
properties.

Unknown Properties

If you try to set a value on a key that is undefined in the target
object, then the setUnknownProperty() handler will be called instead. This
gives you an opportunity to implement complex "virtual" properties that
are not predefined on the object. If setUnknownProperty() returns
undefined, then set() will simply set the value on the object.

Property Observers

In addition to changing the property, set() will also register a property
change with the object. Unless you have placed this call inside of a
beginPropertyChanges() and endPropertyChanges(), any "local" observers
(i.e. observer methods declared on the same object), will be called
immediately. Any "remote" observers (i.e. observer methods declared on
another object) will be placed in a queue and called at a later time in a
coalesced manner.