Views and templates

In this article we will start adding to the skeleton app we created earlier on, introducing usage of routes and templates in Ember as we go.

Note: At this point, we are assuming that you have followed the instructions in Creating an Ember app, and are ready to start adding code to your skeleton app directory. If you have not yet been to this stage, go through the previous sections and return here.

Routes

Routes tell an app that a certain part of the content/functionality will exist at a certain URL. Along with Templates, which specify the content structure that will be visible at each route, they form the basis of the "V" (View) in MVC in Ember applications. Think of a route as a 'page' of your application.

Ember will handle the dynamic generation of the required content at build time, and apply the JavaScript, CSS, etc. that makes that content work. To recap, a route is created using the following command:

ember generate route my-route-name

Adding the current time

We'll start by adding a clock 'page' to our app, to display the current time. To create a new page, we need to generate a route — run the following command in your terminal, making sure you are inside your app's root directory:

ember generate route clock

This will generate:

  1. app/routes/clock.js: This file controls the route.
  2. app/templates/clock.hbs: A Handlebars template that defines the content that will appear at the named URL.
  3. tests/unit/routes/clock-test.js : A test file where you can define a test for the functionality at your route.

Your clock template will be available on your test server at http://localhost:4200/clock (run the ember serve command again if it's not currently running). If you navigate to this URL, however, you'll notice that it displays the same welcome message as our home page (http://localhost:4200). In order to display the current time instead, we'll need to update our clock template.

Templates

Various HTML templating systems exist for web apps. These tend to provide superior functionality over plain HTML, such as the ability to include variables that are dynamically updated when the app's state or data changes. As explained earlier in this series, Ember uses Handlebars for templating.

Updating our clock template

Our template file has already been generated at app/templates/clock.hbs. Open it up in your text editor and you'll see that by default this contains only the following:

{{outlet}}

Handlebars uses curly braces to differentiate between plain HTML and templating logic. Items inside curly braces — at a basic level — are variables that can represent whatever data you want. At the moment the template only includes a default welcome message; let's change this to include a variable to output our local time.

Replace {{outlet}} with the following:

<h2>Local Time: <strong>{{localTime}}</strong></h2>

By wrapping localTime in these braces, our template will know to replace the word localTime with whatever value we specify.

If you return to http://localhost:4200/clock in your browser, you'll notice that the page still renders "Welcome to Ember.js", albeit with "Local Time: ", underneath it. This is because the welcome message comes from app/templates/application.hbs. If you look in that file, you'll see two lines:

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

{{outlet}}

When any view is navigated to by the app's user, application.hbs is shown, but with the view's template content inserted too. We'll look at more details in the next section, along with how to get rid of the default welcome message.

Note: You may have expected to see "Local Time: {{localTime}}" printed to the page, but Handlebars knows we want to replace anything inside curly braces with our custom data. Since we haven't yet provided our template with this value, nothing will render in its place.

The main application template

application.hbs is a special template created when you first created the app, which represents the main, or master application view. You are given this automatically so you'll always have something displayed at the root of your app (i.e. your-server.com/). Whenever you view any "page" in your app, it is actually the application.hbs template that is shown, but with the contents of the route's corresponding template inserted in place of the {{outlet}}. In the case of our clock route, the rendered content will be whatever exists in clock.hbs.

So far we've been viewing our app through our clock route at http://localhost:4200/clock. But since this is going to be the only/main page of the app, it'd be nice to have it appear when we go to the root of our domain.

So you've already got an application.hbs file, but that's it — you'll notice there was no application route created for you by default. Often times, you'll find that a template is all you need to render the content you want. However, if you want to do anything more sophisticated with a template, you will need to put that logic in a corresponding route.

Generating an application route

Let's generate a main application route by entering the command below in the app's root:

ember generate route application

At this point you will be prompted with the question [?] Overwrite app/templates/application.hbs?, as application.hbs already exists. It is fine to go ahead and overwrite it, so type Y and press enter to confirm. Just like the last time you ran the ember generate route command, you will get a new route, template and unit test generated. You'll notice that localhost:4200/clock will now only display "Local time:", because the new application.hbs only contains {{outlet}}, and not the welcome message.

Making the application route redirect to the clock route

At this point, open your app/routes/application.js file and update the contents like so:

import Ember from 'ember';

export default Ember.Route.extend({
    redirect: function() {
        this.transitionTo('clock');
    }
});

Here we are extending the default Ember Route functionality with a redirect() method that will forward any requests for the root of our application to the clock route using transitionTo(). We will now be redirected to our ticking clock at localhost:4200/clock whenever we hit http://localhost:4200/.

In addition to showing the clock on our main page (which we'll fix in the next article!), we're going to want some navigation that allows users to toggle between the main clock view, and a view allowing them to choose new timezones to add to the main display. In our application template, let's add two links. One will correspond to our clock route, and the other will link to a timezones route that we will be creating shortly.

Update the contents of app/templates/application.hbs to look like this:

<h1 id='title'>It's 5'o'clock somewhere</h1>

<ul>
    <li>{{#link-to 'clock'}}Clock{{/link-to}}</li>
    <li>{{#link-to 'timezones'}}Manage Timezones{{/link-to}}</li>
</ul>

{{outlet}}

You'll notice the same Handlebars convention of using curly braces that we saw in our clock template. In this example, {{#link-to}} is a built-in Handlebars helper for creating links — it takes one parameter, the route you want to link to.

As we alluded to before, {{outlet}} is Ember's way of reserving a space on the page for the content a user is requesting to view. So when we click the links for our clock route or timezones route, the outlet will automatically render the content from the requested route's template.

If you go to look at your application now, you'll notice the page is blank. We've lost our "Local time:" heading. We must have an error in our code somewhere, so let's go and investigate now.

Debugging Practice

 If you open the console tab in your developer tools, you should see an error coming specifically from Ember:

Ember Error

This is because we are trying to link to a timezones route that does not yet exist. We'll deal with this in a later article, so for now, update the line

<li>{{#link-to 'timezones'}}Manage Timezones{{/link-to}}</li>

to simply

<li>Manage Timezones</li>

So that we can carry on. You should now see this:

Next

In order to display the current local time, we'll need to create a corresponding clock controller to define the value of the localTime variable we've got in our clock.hbs template. This will be the topic of our next article.

Note: Before you move on to the next part, notice that your application display updated automatically upon editing your clock template — there was no need to refresh the page or restart the server. This is a rather nice feature of Ember CLI.

Document Tags and Contributors

 Contributors to this page: chrisdavidmills, brittanystoroz, ChrisL
 Last updated by: chrisdavidmills,