Controllers

In this article we continue building up our world-clock app, introducing controllers to the mix and adding a functioning clock to our clock view.

Controllers

Controllers provide a way for us to update and manipulate application data and views; they provide the application logic that states what should happen when the model changes (e.g. state, or data). Controllers are the "C" within MVC.

Ember provides an easy way to generate controllers that are automatically associated with the correct models and routes. You just use the following syntax:

ember generate controller name-of-my-route

Generating a controller for our clock display

In order to display the local time on our clock template, we need a clock controller to specify and update the localTime variable. Using your terminal, run the following command in the app's root:

ember generate controller clock

This will create two new files:

  1. app/controllers/clock.js : a file representing our controller that contains the logic needed to control the clock view.
  2. tests/unit/controllers/clock-test.js : A test file where you can define a test for the functionality of your controller.

Open up app/controllers/clock.js. To set the value of localTime, we will add it as a property within Ember.Controller.extend(). Update it as follows:

import Ember from 'ember';
export default Ember.Controller.extend({
  localTime: new Date().toLocaleTimeString()
});

Any property inside the controller is accessible inside that controller’s template (in this case app/templates/clock.hbs). We've set the localTime property equal to a formatted JavaScript Date string, and it's carried into our template context. Ember uses the matching file names of our controller and template to send the information to the appropriate template.

Now when you view http://localhost:4200/clock, you should see the current local time outputted in place of your {{localTime}} property.

Note: The import Ember from 'ember'; line at the top of these files makes sure every file where we are taking advantage of Ember actually has access to the framework. Without this line, we wouldn't be able to organize our code the way Ember has mapped it out for us.

Making the clock update every second

So far, our clock display just shows the time when the controller was initialized — and then doesn't change. This is not very useful; we ideally want to update it every second.

Let's go back to app/controllers/clock.js and add a couple of methods to handle this — update your file so it looks like this:

import Ember from 'ember';
export default Ember.Controller.extend({
    init: function() {
        // Update the time.
        this.updateTime();
    },
 
    updateTime: function() {
        var _this = this;
 
        // Update the time every second.
        Ember.run.later(function() {
            _this.set('localTime', new Date().toLocaleTimeString());
            _this.updateTime();
        }, 1000);
    },
 
    localTime: new Date().toLocaleTimeString()
});

The two methods you've added are as follows:

  1. init() is a special method in Ember that runs automatically when the controller is first initialized. You can put whatever set up code you might need here; in this case you are just invoking the updateTime() method.
  2. updateTime() uses Ember.run.later() to run the code inside the contained function after 1000ms. The function sets a new value for the localTime property (using the Ember set() method), then runs the updateTime() function again, so the time is updated after each new second has gone by.

Now you should see your clock automatically update every second. This demonstrates how to work with Ember’s data-binding between controllers and templates. If you change a value in a controller, model, or view that’s wired up to a template, the template will automatically update that data for you.

Note: var _this = this; is used because of variable scoping in functions — we want to run the functions inside Ember.run.later(function() { ... }); on this as it relates to updateTime: function() { ... }, so we store a reference to this inside the _this variable before we run the inner function. Jack Franklin's Scope and this in JavaScript provides more context and explanation.

Next

In the next article we'll step up a gear, looking at models and handling data in Ember, adding the rest of our app's functionality along the way. This section will also involve including some external libraries, giving you an idea of how to add new dependencies to your Ember application.

Document Tags and Contributors

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