Class Ember.Component

public

An Ember.Component is a view that is completely isolated. Properties accessed in its templates go to the view object and actions are targeted at the view object. There is no access to the surrounding context or outer controller; all contextual information must be passed in.

The easiest way to create an Ember.Component is via a template. If you name a template components/my-foo, you will be able to use {{my-foo}} in other templates, which will make an instance of the isolated component.

{{app-profile person=currentUser}}
<!-- app-profile template -->
<h1>{{person.title}}</h1>
<img src={{person.avatar}}>
<p class='signature'>{{person.signature}}</p>

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

{{#app-profile person=currentUser}}
  <p>Admin mode</p>
  {{! Executed in the controller's context. }}
{{/app-profile}}
<!-- app-profile template -->
<h1>{{person.title}}</h1>
{{! Executed in the components context. }}
{{yield}} {{! block contents }}

If you want to customize the component, in order to handle events or actions, you implement a subclass of Ember.Component named after the name of the component. Note that Component needs to be appended to the name of your subclass like AppProfileComponent.

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

App.AppProfileComponent = Ember.Component.extend({
  actions: {
    hello: function(name) {
      console.log("Hello", name);
    }
  }
});

And then use it in the component's template:

<!-- app-profile template -->

<h1>{{person.title}}</h1>
{{yield}} <!-- block contents -->

<button {{action 'hello' person.name}}>
  Say Hello to {{person.name}}
</button>

Components must have a - in their name to avoid conflicts with built-in controls that wrap HTML elements. This is consistent with the same requirement in web components.

Show:

Module: ember

The collection of functions, keyed by name, available on this ActionHandler as action targets.

These functions will be invoked when a matching {{action}} is triggered from within a template and the application's current route is this route.

Actions can also be invoked from other parts of your application via ActionHandler#send.

The actions hash will inherit action handlers from the actions hash defined on extended parent classes or mixins rather than just replace the entire hash, e.g.:

App.CanDisplayBanner = Ember.Mixin.create({
  actions: {
    displayBanner: function(msg) {
      // ...
    }
  }
});

App.WelcomeRoute = Ember.Route.extend(App.CanDisplayBanner, {
  actions: {
    playMusic: function() {
      // ...
    }
  }
});

// `WelcomeRoute`, when active, will be able to respond
// to both actions, since the actions hash is merged rather
// then replaced when extending mixins / parent classes.
this.send('displayBanner');
this.send('playMusic');

Within a Controller, Route, View or Component's action handler, the value of the this context is the Controller, Route, View or Component object:

App.SongRoute = Ember.Route.extend({
  actions: {
    myAction: function() {
      this.controllerFor("song");
      this.transitionTo("other.route");
      ...
    }
  }
});

It is also possible to call this._super.apply(this, arguments) from within an action handler if it overrides a handler defined on a parent class or mixin:

Take for example the following routes:

App.DebugRoute = Ember.Mixin.create({
  actions: {
    debugRouteInformation: function() {
      console.debug("trololo");
    }
  }
});

App.AnnoyingDebugRoute = Ember.Route.extend(App.DebugRoute, {
  actions: {
    debugRouteInformation: function() {
      // also call the debugRouteInformation of mixed in App.DebugRoute
      this._super.apply(this, arguments);

      // show additional annoyance
      window.alert(...);
    }
  }
});

Bubbling

By default, an action will stop bubbling once a handler defined on the actions hash handles it. To continue bubbling the action, you must return true from the handler:

App.Router.map(function() {
  this.resource("album", function() {
    this.route("song");
  });
});

App.AlbumRoute = Ember.Route.extend({
  actions: {
    startPlaying: function() {
    }
  }
});

App.AlbumSongRoute = Ember.Route.extend({
  actions: {
    startPlaying: function() {
      // ...

      if (actionShouldAlsoBeTriggeredOnParentRoute) {
        return true;
      }
    }
  }
});
Module: ember

The WAI-ARIA role of the control represented by this view. For example, a button may have a role of type 'button', or a pane may have a role of type 'alertdialog'. This property is used by assistive software to help visually challenged users navigate rich web applications.

The full list of valid WAI-ARIA roles is available at: http://www.w3.org/TR/wai-aria/roles#roles_categorization

Module: ember

A list of properties of the view to apply as class names. If the property is a string value, the value of that string will be applied as a class name.

// Applies the 'high' class to the view element
Ember.View.extend({
  classNameBindings: ['priority'],
  priority: 'high'
});

If the value of the property is a Boolean, the name of that property is added as a dasherized class name.

// Applies the 'is-urgent' class to the view element
Ember.View.extend({
  classNameBindings: ['isUrgent'],
  isUrgent: true
});

If you would prefer to use a custom value instead of the dasherized property name, you can pass a binding like this:

// Applies the 'urgent' class to the view element
Ember.View.extend({
  classNameBindings: ['isUrgent:urgent'],
  isUrgent: true
});

This list of properties is inherited from the view's superclasses as well.

Module: ember

Standard CSS class names to apply to the view's outer element. This property automatically inherits any class names defined by the view's superclasses as well.

Module: ember

Defines the properties that will be concatenated from the superclass (instead of overridden).

By default, when you extend an Ember class a property defined in the subclass overrides a property with the same name that is defined in the superclass. However, there are some cases where it is preferable to build up a property's value by combining the superclass' property value with the subclass' value. An example of this in use within Ember is the classNames property of Ember.View.

Here is some sample code showing the difference between a concatenated property and a normal one:

App.BarView = Ember.View.extend({
  someNonConcatenatedProperty: ['bar'],
  classNames: ['bar']
});

App.FooBarView = App.BarView.extend({
  someNonConcatenatedProperty: ['foo'],
  classNames: ['foo']
});

var fooBarView = App.FooBarView.create();
fooBarView.get('someNonConcatenatedProperty'); // ['foo']
fooBarView.get('classNames'); // ['ember-view', 'bar', 'foo']

This behavior extends to object creation as well. Continuing the above example:

var view = App.FooBarView.create({
  someNonConcatenatedProperty: ['baz'],
  classNames: ['baz']
})
view.get('someNonConcatenatedProperty'); // ['baz']
view.get('classNames'); // ['ember-view', 'bar', 'foo', 'baz']

Adding a single property that is not an array will just add it in the array:

var view = App.FooBarView.create({
  classNames: 'baz'
})
view.get('classNames'); // ['ember-view', 'bar', 'foo', 'baz']

Using the concatenatedProperties property, we can tell Ember to mix the content of the properties.

In Ember.View the classNameBindings and attributeBindings properties are also concatenated, in addition to classNames.

This feature is available for you to use throughout the Ember object model, although typical app developers are likely to use it infrequently. Since it changes expectations about behavior of properties, you should properly document its usage in each individual concatenated property (to not mislead your users to think they can override the property in a subclass).

Module: ember

Returns the current DOM element for the view.

Module: ember

The HTML id of the view's element in the DOM. You can provide this value yourself but it must be unique (just as in HTML):

  {{my-component elementId="a-really-cool-id"}}

If not manually set a default value will be provided by the framework.

Once rendered an element's elementId is considered immutable and you should never change it. If you need to compute a dynamic value for the elementId, you should do this when the component or element is being instantiated:

  export default Ember.Component.extend({
    setElementId: function() {
      var index = this.get('index');
      this.set('elementId', 'component-id' + index);
    }.on('init')
  });
Module: ember
returns

Boolean

Returns true when the component was invoked with a block template.

Example (hasBlock will be false):

{{! templates/application.hbs }}

{{foo-bar}}

{{! templates/components/foo-bar.js }}
{{#if hasBlock}}
  This will not be printed, because no block was provided
{{/if}}

Example (hasBlock will be true):

{{! templates/application.hbs }}

{{#foo-bar}}
  Hi!
{{/foo-bar}}

{{! templates/components/foo-bar.js }}
{{#if hasBlock}}
  This will be printed because a block was provided
  {{yield}}
{{/if}}
Module: ember
returns

Boolean

Returns true when the component was invoked with a block parameter supplied.

Example (hasBlockParams will be false):

{{! templates/application.hbs }}

{{#foo-bar}}
  No block parameter.
{{/foo-bar}}

{{! templates/components/foo-bar.js }}
{{#if hasBlockParams}}
  This will not be printed, because no block was provided
  {{yield this}}
{{/if}}

Example (hasBlockParams will be true):

{{! templates/application.hbs }}

{{#foo-bar as |foo|}}
  Hi!
{{/foo-bar}}

{{! templates/components/foo-bar.js }}
{{#if hasBlockParams}}
  This will be printed because a block was provided
  {{yield this}}
{{/if}}
Module: ember

Used to identify this view during debugging

Module: ember

Destroyed object property flag.

if this property is true the observers and bindings were already removed by the effect of calling the destroy() method.

Module: ember

Destruction scheduled flag. The destroy() method has been called.

The object stays intact until the end of the run loop at which point the isDestroyed flag is set.

Module: ember

If false, the view will appear hidden in DOM.

Module: ember

A view may contain a layout. A layout is a regular template but supersedes the template property during rendering. It is the responsibility of the layout template to retrieve the template property from the view (or alternatively, call Handlebars.helpers.yield, {{yield}}) to render it in the correct location.

This is useful for a view that has a shared wrapper, but which delegates the rendering of the contents of the wrapper to the template property on a subclass.

Module: ember

The name of the layout to lookup if no layout is provided.

By default Ember.View will lookup a template with this name in Ember.TEMPLATES (a shared global object).

Module: ember

Tag name for the view's outer element. The tag name is only used when an element is first created. If you change the tagName for an element, you must destroy and recreate the view element.

By default, the render buffer will use a <div> tag for views.