cult3

Using Templates in Ember

Apr 13, 2015

Table of contents:

  1. The Application file
  2. Getting started with Handlebars
  3. Handlebars helpers
  4. Conclusion

Last week we looked at setting up an Ember application as part of an existing Laravel repository.

Ember is a front-end framework that makes building interactive client-side applications much easier than rolling your own Javascript.

One of the core components of Ember is it’s templating engine. In today’s tutorial we will explore the Ember templating engine to learn more about how Ember works.

The Application file

If you read last week’s post , you will remember that we peaked into the application.hbs file.

<h2 id="title">Welcome to Ember.js</h2>
{{outlet}}

We also added a index.hbs file and then we fired up ember serve to see that our file had automatically been injected into the page.

The application.hbs is your main application template file and so it is where you will put your header and footer stuff.

The {{outlet}} tag is where the actual contents of the page will be injected.

You can have multiple named outlets to designate multiple areas of the page, but we’ll cross that bridge when we come to it.

Getting started with Handlebars

If you’ve ever done any kind of Javascript view templating in the past, you’ve probably already heard of Handlebars.js.

Handlebars.js is a logicless templating language that make it really easy to draw a line between the view and the data.

Ember builds upon Handlebars.js by extending the language to include some of the really amazing features of Ember.

Properties in Handlars.js are wrapped using the {{property}} syntax and all view properties will be automatically kept up-to-date by Ember as data across your application changes.

Handlebars helpers

The following is a run down of the most common Handlebars helpers you will find yourself using when writing Ember application views.

if

A very common requirement of a view is to only show a section based upon some condition. To achieve this we can use the if helper:

{{#if user}}
    <p>Hello {{user.username}}!</p>
{{/if}}

If the value you pass to the if helper evaluates to true, the section inside the block will be rendered.

If you want to render an alternative in the case of a false value, you can also include an {{else}} block:

{{#if user}}
    <p>Hello {{user.username}}!</p>
{{else}}
    <p>Hello guest!</p>
{{/if}}

If you want to only display a section of the view if the condition evaluates as false you can use the unless helper:

{{#unless user}}
    <p>You need to sign in</p>
{{/unless}}

each

Another common requirement is when you have a list of items that you need to display on a page. To iterate through the list and display each item, you can use the each helper:

{{#each post in posts }}
    <h2>{{post.title}}</h2>
    <p>{{post.excerpt}}</p>
{{/each}}

You can also {{else}} block that will be displayed if there are no items in the list:

{{#each post in posts }}
    <h2>{{post.title}}</h2>
    <p>{{post.excerpt}}</p>
{{else}}
    <p>There are no posts to display.</p>
{{/each}}

All web applications will require links between the various pages of the user interface. It’s usually a good practice to avoid hard coding links into your views as it becomes a bit of a nightmare to update them when your routes inevitable change.

Ember provides the link-to helper to deal with this functionality:

{{#link-to 'index'}}Home{{/link-to}}

The would render to the following HTML:

<a href="/">Home</a>

You can also pass in model objects that will automatically be used as part of dynamic routes:

{{#each post in posts}}
    <h2>{{#link-to 'posts.view' post}}{{post.title}}{{/link-to}}</h2>
    <p>{{post.excerpt}}</p>
{{/each}}

This would render as:

<h2><a href="/posts/1">Post title</a></h2>
<p>Post except</p>

<h2><a href="/posts/2">Post title</a></h2>
<p>Post except</p>

<h2><a href="/posts/3">Post title</a></h2>
<p>Post except</p>

One of the really nice little touches from Ember is that a class of active will automatically be injected into the link that represents the current page.

This means it’s very easy to highlight where there the user is in the navigation, for example.

action

One of the big benefits of using a front-end framework like Ember is that it make it really easy to add interactivity to your application.

One way of doing this is by adding the {{action}} helper to an element in the view:

<button {{action 'comments'}}>View Comments</button>

When the user clicks this button, the named event comments will be sent to your application. This will trigger the method on the Controller that is associated with this View:

App.PostController = Ember.ObjectController.extend({
  actions: {
    comments: function () {
      // Load and display comments
    },
  },
});

input

One of the best showcases of Ember’s functionality is the binding between input elements. When the user types into an input element you can very easily display it as part of the View.

{{input name="email" placeholder="Enter your email"}}

If you want to dispatch an action on a specific event, you can do so using the on property:

{{input name="search" action="search" on="key-press"}}

A really great use case of this functionality is to show automatic previews of what your user is typing in.

Binding Attributes

Sometimes it useful to bind attributes from your Controller into the view. For example, you might have the following in your template:

<input name="email" required={{isRequired}}>

If the isRequired attribute is true, this element will be rendered as:

<input name="email" required>

However, if the isRequired attribute is false, the element will be rendered as:

<input name="email">

You can also bind class attributes to elements like this:

<fieldset class="{{highlight}}">

</fieldset>

If the highlight attribute is set as warning, the template above would render as:

<fieldset class="warning">
</fieldset>

If you want to add a class attribute based on a boolean value, you can write the following:

<fieldset class="{{required}}">
</fieldset>

If required property is set as true, the template above would be rendered as:

<fieldset class="required">
</fieldset>

However, if the required property is set as false, the template would be rendered as:

<fieldset>

</fieldset>

Conclusion

Using a templating language like Handlebars.js is a great way to keep your Views clean. Inevitably there is always going to be some “logic” in your View, but by using a templating system you will keep your Views clean and tidy.

Handlebars.js is baked right into Ember and so the two aspects of your client-side application will really work well together. We will explore some more of these integrations as we continue our deep dive into Ember.

This is a series of posts on building an entire Open Source application called Cribbb. All of the tutorials will be free to web, and all of the code is available on GitHub.

Philip Brown

@philipbrown

© Yellow Flag Ltd 2024.