Render HTML Controls with Expressions

So far we’ve used some pretty vanilla controls to illustrate Ember’s templating system. But the Handlebars expression language and Ember’s helper classes are capable of rendering a great deal more variety than that.

In this section we’ll go through the most useful controls available in Ember. We’ll start with how to use Ember to display static data, and then talk about conditionals and looping. Then we’ll visit input controls and wrap up by going over actions and links.

Rendering Data

The most fundamental use of Handlebars expressions is to simply display data from the route and its related controller. A controller is a class used to provide access to the data supplied via the route’s model hook. Recall that each template is bound to one and only one route. This is also true for controllers. Each controller maintains a set of properties, which are data that can be used by the template. Thus far, we haven’t needed to explicitly define a controller class and have relied on default functionality in the framework. However, if we want to display the data for a given controller property, we simply add it to an expression in our template, like this:

 <div>{{propertyName}}</div>

Whatever data is held in that property will be displayed as static text on the page. If your controller looks like this:

 import​ Ember from ​'ember'
 
 export​ ​default​ Ember.Controller.extend({
  propertyName: ​"A value"
 });

then the previous expression will render this:

 <div>A value</div>

It’s possible for a controller to manage the data of just one record, which is called an ObjectController, or many records, which is called an ArrayController. In our example, the controller that backs the notebooks template is an ArrayController. If you have an ArrayController, you can render data from the list of records it manages by using the {{each}} expression, as we saw earlier in the chapter. Let’s now turn to Ember’s control flow expressions.

Controlling Templates with Looping and Conditionals

Ember has a number of different means of controlling what is displayed within a template. One such construct is the {{if}} expression. An {{if}} expression renders a section of the template (or not) based on whether the provided property is true, or whether it’s false, null, undefined, or []. (Oh, JavaScript.)

To use an {{if}} expression, you’ll surround the block you want to conditionally include, like this:

 {{#if condition}}
  <div>HELLO</div>
 {{else}}
  <div>never mind</div>
 {{/if}}

Ember refers to such an expression as a block expression, because a block of template code is surrounded by the expression. Block expressions require an opening and closing tag (for example, {{#if}} and {{/if}}). In this case, “HELLO” will be rendered if condition is true; otherwise “never mind” will be rendered.

Ember also allows you to chain together conditions, rather than nest them within your {{else}} block. If you have two, three, or forty-seven conditions that you need to chain together, you can do so like this:

 {{#if condition}}
  <div>HELLO</div>
 {{else if condition2}}
  <div>never mind</div>
 {{else if condition3}}
  <div>WAT</div>
 {{else}}
  <div>go away</div>
 {{/if}}

You can also shortcut the standard {{if}} syntax by using an inline if:

 {{if condition 'on' 'off'}}

The second and third parameters to the inline conditional can contain a property or a string, but nothing more. The {{if}} expression has a sibling expression called {{unless}}. Use this expression when you have one outcome in which to render the body of the expression, and you don’t want to confuse matters by “not”-ing the conditional, like this:

 {{#unless hasChrome}}
  The Chrome web browser is required to run this app.
 {{/unless}}

The admonishment to use only Chrome is displayed unless the user has the Chrome browser. The hasChrome variable is a value provided by the backing model or route attributes, and isn’t a standard part of Ember. Yes, you could also use an {{if}}, but this combination of expression and property reads a bit more clearly. You’ll notice we used these expressions in our application.hbs template.

You’ve already seen the code to loop over a list of items using {{each}} earlier in this chapter, so I won’t repeat it. I will remind you that {{each}} requires that your controller reference a list of records as its model.

Binding Input Fields

Every expression we’ve seen thus far is geared toward displaying static text. A lot of Ember’s power comes from its ability to link editable fields to the controller, so we need to use input fields as well. Let’s update our example to use input fields now.

Start by taking a look at the notebooks template:

 title: {{input value=title}}
 <button ​{{​action ​'​addNotebook​'}}​>Add</button>

A minimal {{input}} expression such as this renders the following HTML:

 <input type=​"text"​ value=​"Notebook Title"​ />

We didn’t explicitly define a type for the input field, but Ember set it to "text" by default. The other option is to set it explicitly, like this:

 {{input type="text" value=title}}

This renders the equivalent HTML. If you look closely you’ll see that the type attribute is set to a quoted string, while value is set to an unquoted string. This distinction is important. A quoted string will be rendered in the HTML exactly as written; an unquoted string will render the value of the given controller property.

The following HTML attributes can also be set for an input field:

accept

autocomplete

autofocus

autosave

disabled

form

formaction

formenctype

formmethod

formnovalidate

formtarget

height

inputmode

max

maxlength

min

multiple

name

pattern

placeholder

readonly

required

selectionDirection

size

spellcheck

step

tabindex

value

width

 

In addition to HTML attributes, the {{input}} expression supports event handlers, or actions, as they are known in Ember. You can link to an action from your {{input}} expression like so:

 {{input type="text" value=name action="execute"}}

In the previous example, the value attribute is bound to a variable in the backing controller. The value may be bound or unbound. If it’s bound, it won’t need quotes; if it’s unbound, you provide the exact string you want to set into the value of the field, within quotes.

The action property is bound to the Return key press event. When Return is pressed, the named action is called. A number of other user events may be bound by setting the name of the event to an action (for example, enter="actionName"). They are as follows:

  • enter
  • escape-press
  • focus-in
  • focus-out
  • insert-newline
  • key-press
  • key-up

By providing an action for each of these user events, you trigger actions within your controller or route, which can be used to load data, execute validation, or write to persistent storage. In the next section we’ll see how to assign an action to a generic HTML element. But let’s spend a bit more time on the {{input}} expression first.

The {{input}} expression can also be used to render a check box by setting the type to checkbox. Similar to the text type, there are a number configurable properties:

  • autofocus
  • checked
  • disabled
  • form
  • indeterminate
  • name
  • tabindex

These properties can be bound to a controller property, or not.

Sometimes you’ll want to capture more text than you can comfortably display in a text field. In this case, the {{textarea}} expression is available. The {{textarea}} expression works like the {{input}} expression. It renders a control of type textarea, with the value bound to the selected property of the controller’s model.

 {{textarea value=property rows=5 cols=40}}

You can also see that we’ve set a few other HTML properties: rows and cols. As before, if set to controller properties, they’ll take the value of these properties; otherwise they’ll be set to whatever specific value is provided. In total, the following HTML properties may also be used in the {{textarea}} expression:

autofocus

cols

disabled

form

maxlength

name

placeholder

readonly

required

rows

selectionDirection

selectionEnd

selectionStart

spellcheck

tabindex

value

wrap

 

These are three of the most fundamental means of linking properties to your user interface. You may think this is limiting, and it would be if this was the only way to create reusable controls in Ember. However, there is another way, and we will see it in the next chapter. Now, let’s move on and learn how to enable action handling in Ember.

Binding Actions to Routes

Your user interface needs to do two things: display data and respond to user input. We’ve seen the first; now let’s start on the second.

Your Route, which has a one-to-one relationship with your template, has a list of functions available to the template called actions.

As you might expect, Ember has an expression for linking an HTML element action with the route: the {{action}} expression. Let’s look at a basic example of an action, from the login template:

 <div class=​"col-md-12"​>
  Login: {{input value=name}} <button ​{{​action ​'​login​'}}​>Login</button>
 </div>

First, we’ve added an input field, so the {{action}} will have something to work with. In the route, the action handler takes that value and checks against the server to see if the user is valid. The {{action}} expression is bound to the next control we added: an HTML button that displays the text “Login.” Used in this manner, the {{action}} expression binds the login action from the route to the onclick event of the button. The onclick event is the default for the button, which is why the {{action}} expression is bound to this event. When the button is clicked, the login action will fire.

We’ve already seen a lot on actions in the previous chapter, so this might be a review for you. Let’s now take a look at compiling templates.

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

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