Handling UI behavior using components

Components are the building blocks of dynamic UI fragments or elements in Ember. They render a template, optionally backed by a class extending Ember.Component.

The easiest way to create a component is to create a template file with a dash-separated name in the app/components/ directory. Then you can embed it in inside other templates by just calling {{<component-name>}} and passing the required parameters.

Components are independent and completely isolated from the client context; all required data must be passed as parameters. However, if you use {{yield}} inside the template, it essentially becomes a block (or container) component, where you can add any content; this content can access any controller attribute and model.

A component can be generated by the following command:

ember generate component <component-name> --pod

This command generates two files, component.js and template.hbs, under the app/<pod-dir>/components/<component-name>/ directory. If you do not use the --pod flag, it generates the <component-name>.js and <component-name>.hbs files under the directory app/components/.

Components insert the content into the DOM structure, where it is invoked, and control the behavior of the inserted content. By default, a component renders a <div/> element with the content generated by its template inside the <div/> element. You can specify a different HTML element instead of the <div/> element by setting the tagName attribute inside the component.js file. Similarly, you can set CSS class names dynamically using another property, assNameBindings.

Components provide some very useful life cycle hooks for manipulating different phases of the component. Some life cycle methods that can be overridden in the component class are didInsertElement(), willInsertElement(), and willDestroyElement().

Components support standard HTML element events, depending upon which tagName is being used. They support all the standard touch events such as touchStart and touchMove, keyboard events such as keyDown, keyUp, and keyPressed, mouse events such as mouseDown, mouseOver, click, and doubleClick, form events such as submit and change, and HTML5 drag and drop events such as dragStart and dragEnd. You just need to declare the event as a function inside the component class; the component will fire the event and the associated function will get invoked as the user interacts with it.

Besides events, components can respond to action handlers, which are named functions defined inside the actions hash of the component class. These actions can be triggered anywhere from the component's template. Action handlers can accept parameters from the client code or templates.

Building a ToggleButton component step by step

Let's learn how to build an Ember component step by step using Ember CLI. We'll build a toggle button that turns off and on when clicked on. The component just changes its label and style based on its status attribute, isActive. We use Bootstrap styles for this example.

First, let's generate the component class and template file (.hbs) using Ember CLI. Issue this command from the command line at the root of your project:

ember generate component toggle-button --pod

See the component.js and template.hbs files generated at app/<pod-dir>/components/toggle-button/. Open and see the component.js file, it looks as given in the following code:

import Ember from 'ember';

export default Ember.Component.extend({
});

The generated template.js file just has {{yield}} inside it. Now you need to add necessary attributes and business logic into these two artifacts in order to make it a proper toggle button component. Here is a modified component.js file, with the proper behavior:

import Ember from 'ember';

export default Ember.Component.extend({
  tagName: "button",
  attributeBindings: ['type'],
  type: "button",
  classNames: ["btn"],
  classNameBindings: ["isActive:btn-primary:btn-default"],
  activeLabel: "On",
  inactiveLabel: "Off",
  isActive: false,

  currentLabel: Ember.computed('isActive', 'activeLabel', 'inactiveLabel', function() {
    return this.get(this.get("isActive") ? "activeLabel" : "inactiveLabel");
  }),

  click: function() {
    var active = this.get("isActive")
    this.set("isActive", !active);
  }
});

In the preceding code, notice that you specified the tagName attribute as button; otherwise, the generated HTML would be <div/>. Also, see how CSS class names are bound dynamically based on the isActive attribute. The currentLabel attribute is a computed attribute that depends on a few other attributes. In effect, the component responds to a click event and actually toggles the isActive variable. Everything else will work based on this event.

Now, let's take a look at the modified template.js file to see how it utilizes the attributes and events handled by the component.js file:

{{currentLabel}}

Surprise! This is all the content in the template. It's so simple to build. All the rest of the heavy lifting is done by the component.js file itself. Now the most interesting part is how the component is invoked from the client. Let's take a look:

{{toggle-button}}

This is how you add the toggle button component in your client code, it is mostly route's template. You can start clicking on the button repeatedly and see that it switches on and off.

This component can be customized by overriding its default properties. Let's try changing its labels when it is on and off from the client side:

{{toggle-button activeLabel="Turn me off now :)" inactiveLabel="Turn me On please.."}}

You can see the new active and inactive labels on the screen as you click on the button, toggling it. The toggle button is the simplest example of an Ember component, intended to give you just a taste of Ember components. A typical Ember application will have many complex components. Converting a reusable UI module or portion into a component is the best way to make your application more elegant and maintainable.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset