Balint Erdi

Reminiscing About EmberFest 2014

EmberFest 2014 ended a week ago and I already feel nostalgic. It was a great event with great people and you could feel the excitement about Ember in the air and in all conversations. It was almost single-handedly organized by Joachim Haagen-Skeie for which he deserves huge kudos.

It was really great to associate real people with twitter avatars and have fascinating conversations about various topics that included the Ember Inspector, the difficulties in building a build tool and even Firefox OS.

The functional paradigm making a headway into Emberland

One thing that struck me about Ember initially is that it seems to rely heavily on (shared) state. Some (most?) of that is inevitable given Ember being a performant framework that runs in the browser and is written in Javascript. None of these facilitates ditching (or minimizing) state and go with a functional, stateless approach.

On the other hand, I really came to cherish the simplicity of the functional paradigm and have been gravitating towards languages that allow this (Clojure was, and still is, my favorite). So I added a mental note about my two favorite things being at such a great distance from each other and moved on.

One theme of the conference and the hallway talks, however, is how Ember embraces the functional, immutable approach where it makes sense to. It might have something to do with my confirmation bias, but let me cite the examples nevertheless. Paul Chavard had a talk on his using immutable data structures in Ember. Jo Liss revealed how Broccoli uses a “rebuild-from-scratch” approach instead of trying to find out which assets to rebuild at each modification. Finally, Alex Matchneer, aka. machty, prolific Ember and router.js contributor had a presentation on React vs. Ember at EmberNYC which you should go read. His last slide has a bullet-point that states: “Don’t be surprised if Ember adopts DOM-diffing”.

It would be an understatement if I said I’m happy to see the functional world coming to Ember.

Promises

I had a talk at the conference called “Don’t call me back - How Ember uses promises and how you can, too”. As it usually happens, in doing research for the talk, I learned a lot not just about promises but about other topics, too. This time, it was the (in)famous run loop I stumbled across on several occasions so I am really happy I know a lot more about that beast now. You can find the slides of my presentation below.

I might even do another talk “How Ember uses the run loop and how you should probably not”, or something to this effect.

EmberFest 2015

The greatest thing about EmberFest was its vibe. I saw the tweets coming in from EmberConf this March and the post-conf blog posts about the awesome community and how one could feel the excitement that we are building apps with a tool that is new and hot now but is probably going to be the framework of choice for many in a few years. It is definitely a fascinating world to live in.

I’ll certainly be there at EmberFest 2015, so hopefully see you there!

Ember Gotcha: Controllers Are Singletons

There is a somewhat subtle bug in the current version of the Rock & Roll with Ember app. If you start to create a song for an artist that does not have one and then switch to another one, the song creation process does not need to be restarted by clicking on the “Why don’t you create one?” link. Also, if you’ve already partially inputted the name of the song for the first one, it stays there for the second artist:

Start creating a song for Radiohead Input Karma for Radiohead Observe song title stays for Red Hot Chili Peppers

The above behavior was brought to my attention by David Lormor, an astute reader and watcher of my screencasts.

In some circumstances it is desirable for the result of some user interaction to linger between route transitions but in other cases it is not. I put the current example firmly in the latter camp and thus consider the above a bug.

Let me explain what causes this behavior and then provide a simple solution to fix it.

Repeat after me: controllers are singletons

Controllers in Ember are singletons. Controllers in Ember are singletons. Controllers in Ember are singletons.

When the user leaves a page and goes to another one, the controller is not torn down. It lives on, keeping its properties.

This makes total sense for a framework that aims to be a tool for creating long-lived, rich-client side applications but is something to watch out for when you develop Ember applications.

If you have a long background in back-end development, like yours truly, it is especially easy to fall prey to this, as you could see.

Same controller, different model

Initially, when the applicaiton is loaded, the songCreationStarted property of the controller is set to false. When the user clicks the “create one” in the “Why don’t you create one?” blurb, it is set to true and thus the text input field appears to allow adding a new song.

Now comes the tricky part. If the user then decides to go to a different artist, she clicks the name of another artist in the sidebar. What happens? A transition is made from one ArtistSongsRoute to another ArtistSongsRoute. The artist is going to be different but the same ArtistSongsController is used.

To prove my point, here are two screenshots of the Ember Inspector’s sidebar. The first one is before, the second one is after the transition between /artists/radiohead/songs and /artists/red-hot-chili-peppers/songs:

Ember Inspector - Radiohead songs Ember Inspector - RHCP songs

You can see that the controller is the same Ember object but the value of the artist property changes.

Understanding the problem

When the transition is made between the two artists, the artist object is changed and consequently any data bound to the artist (and the artist property of the ArtistSongs controller) is going to be rerendered but, since the controller instance is not changed, unrelated data will stay unchanged on screen.

What happens in the code? If you take a look at the template, you see that the text input field is shown if canCreateSong is true:

<script type="text/x-handlebars" data-template-name="artist/songs">
  {{#if canCreateSong}}
    <div class="list-group-item">
      {{input type="text" class="new-artist" placeholder=newSongPlaceholder value=newTitle insert-newline="createSong" }}
      <button class="btn btn-primary btn-sm new-song-button" {{action "createSong"}}>Add</button>
      (...)
    </div>
  {{/if}}
</script>

canCreateSong is defined in the controller and is true if either songCreationStarted is true or if there are already songs. Since songCreationStarted has just been set to true by the enabledSongCreation action (and the controller instance is not changed) when the user clicked the “create one” link for the first artist, canCreateSong stays true and the text field stays visible:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
App.ArtistSongsController = Ember.ArrayController.extend({
  (...)
  songCreationStarted: false,
  canCreateSong: function() {
    return this.get('songCreationStarted') || this.get('length');
  }.property('songCreationStarted', 'length'),

  actions: {
    enableSongCreation: function() {
      this.set('songCreationStarted', true);
    }
  }
  (...)
});

A simple fix

To fix this, the simplest solution is to manually reset the properties that we do not want to persist.

One solution is to do this in the setupController of the route since that always gets called when transitioning to a new route:

1
2
3
4
5
6
7
8
9
10
App.ArtistSongsRoute = Ember.Route.extend({
  (...)
  setupController: function(controller, model) {
    this._super(controller, model);
    controller.set('artist', this.modelFor('artist'));
    controller.set('newTitle', '');
    controller.set('songCreationStarted', false);
  },
  (...)
});

And that totally works. However, I prefer placing this “resetting” code to the controller, probably because it is strictly controller-related and also because I can make the code really telling there:

1
2
3
4
5
6
7
8
9
10
11
12
13
App.ArtistSongsController = Ember.ArrayController.extend({
  (...)
  songCreationStarted: false,
  canCreateSong: function() {
    return this.get('songCreationStarted') || this.get('length');
  }.property('songCreationStarted', 'length'),

  artistDidChange: function() {
    this.set('newTitle', '');
    this.set('songCreationStarted', false);
  }.observes('artist'),
  (...)
});

The observes function property extension will run the artistDidChange code every time the artist property of the controller changes and that is exactly when we need to clear the title and allow the song creation process to be restarted. Nice, clean and does exactly one thing.

Note: The latest version of the code that contains these changes is available on Github.

Model Dependent State - UPDATE

It turns out I stumbled into something substantial. As Luke Melia points out below in the comments (thank you, Luke!), the above problem has been under consideration for a while.

Alex Matchneer, a member of the Ember core team gave a presentation at EmberFest in which he explains that there is a missing primitive.

He calls it “Model Dependent State” and it is what would decice under what conditions a certain controller property is “sticky” (whether it retains its value when you change the model of a certain controller or not).

Here is the part where he begins to talk about Model Dependent State.

Indicating Progress - Loading Routes in Ember.js

When an Ember app is being loaded at first, the user sees a blank screen. When transitioning between two routes and loading data to render for the destination template, there is no indication that something is happening and thus the user can be perplexed. Ideally, loading data happens fast enough so that users barely notice the blank screen or freeze, but web apps do not always behave ideally.

If you have read some of my other articles on Ember, you will not be surprised to hear that there is a splendid solution for this problem and that it is based on a convention.

Unresolved promises

The model hook of routes is the canonical place to fetch data needed to render the corresponding template. When a promise is returned, execution is blocked until that promise is resolved (or rejected). That is the period during which the application seems unresponsive. When starting up the application, this can even mean that the user only sees a blank screen. Since data is fetched asyncronously, not even the spinner in the tab title is going to spin.

The user may just close the tab and go on with her life. We can’t let that happen and unsurprisingly Ember has a convention-based solution that is easy to work with and customize.

Beautiful, reusable conventions

We saw how each resource route (and thus each route level) creates an outlet for the level below to render content in. Let’s take a look at the routes of the application to see how that plays out:

1
2
3
4
5
6
7
App.Router.map(function() {
  this.resource('artists', function() {
    this.resource('artist', { path: ':slug' }, function() {
      this.route('songs');
    });
  });
});

The outlet defined in the (top-level) application template is going to be filled in by the content rendered by the first-level templates (in this case, artists).

<script type="text/x-handlebars">
  <div class="container">
    <div class="page-header">
      {{#link-to "index"}}
        <h1>Rock & Roll<small> with Ember.js</small></h1>
      {{/link-to}}
    </div>
    <div class="row">
      {{outlet}}
    </div>
  </div>
</script>

Next, the outlet in the artists template is populated by the routes below the artists resource route:

<script type="text/x-handlebars" data-template-name="artists">
  <div class="col-md-4">
    (list of artists)
  </div>
  <div class="col-md-8">
    <div class="list-group">
      {{outlet}}
    </div>
  </div>
</script>

The artist template also defines an outlet into which content is rendered by the routes below the artist resource. In this case, there is no common markup for a single artist so the template only defines the outlet:

<script type="text/x-handlebars" data-template-name="artist">
  {{outlet}}
</script>

Finally, there is a single route defined below the artist resource, artist.songs:

<script type="text/x-handlebars" data-template-name="artist/songs">
  (...)
  {{#each sortedSongs}}
    <div class="list-group-item">
      {{title}}
      {{star-rating ...}}
    </div>
  {{/each}}
  (...)
</script>

Loading routes build on the nested routes pattern

The ingenious thing about indicating that loading data from the backend is happening is that it leverages the “nested routes, nested templates” architecture explained above.

When the model hook of a certain route returns a promise that is not resolved, a so-called loading template at the same level as the route is going to be rendered.

When loading the list of artists in the artists route, a loading route at the same level is going to be activated. That, by default, means a top-level loading template is rendered.

Consequently, all we need to do is to put into that template what we want the user to see while data is being fetched. Currently that is what she sees in that scenario:

Loading indication before

You think we can beat that?

Top-level loading template

The convention says that the loading route (and thus template) should be the sibling of the route we define it for and should be called loading.

The loading template for the artists route should consequently be called loading:

<script type="text/x-handlebars" data-template-name="loading">
  <div class="loading-pane">
    <div class="loading-message">
      Loading stuff, please have a cold beer.
      <div class="spinner"></div>
    </div>
  </div>
</script>

Let’s inspect what our app looks like while loading data from the backend:

Loading indication before

Nice, but it gets nicer still.

Loading route for the songs

We can now descend a couple of levels and make a loading template for when the songs of a certain artist are being fetched.

Let’s take a look at the “routing table” to see what that template should be named:

1
2
3
4
5
6
7
App.Router.map(function() {
  this.resource('artists', function() {
    this.resource('artist', { path: ':slug' }, function() {
      this.route('songs');
    });
  });
});

The loading route should be the sibling of the route under consideration.

In this particular case, this latter is artist.songs and thus the loading template should be named artist.loading:

<script type="text/x-handlebars" data-template-name="artist/loading">
  <div class="loading-pane">
    <div class="loading-message">
      Loading the artist, please have an organic orange juice.
    </div>
    <div class="spinner"></div>
  </div>
</script>

Indicating loading artist

Customizing loading route behavior

More precisely, what happens when entering a route where one of the model hooks returns an unresolved promise is that a loading event is fired on the route.

We saw above that the default implementation is to look up a route at the same level as the route itself and render the corresponding template.

However, this behavior is customizable. For example, we can pop up an alert box in 1993-style, telling the user she needs to wait.

Below, I do that for the top-level artists route:

1
2
3
4
5
6
7
8
9
10
11
12
App.ArtistsRoute = Ember.Route.extend({
  model: function() {
    return someDataThatTakesTooLongToFetch();
  },

  (...)
  actions: {
    loading: function() {
      alert("Loading data, go make some coffee.");
    }
  }
});

It works:

1993-style loading indication

Another thing we can do is to render another loading template:

1
2
3
4
5
App.LoadingRoute = Ember.Route.extend({
  renderTemplate: function() {
    this.render('working');
  }
});
<script type="text/x-handlebars" data-template-name="working">
  <div class="loading-pane">
    <div class="loading-message">
      I work hard while you play hard.
      <div class="spinner"></div>
    </div>
  </div>
</script>

Which also just works:

Rendering a different template

Since handling the loading state happens in the route, the most powerful piece of Ember architecture, the possibilities are many.

Why I love this solution and why you should, too

In summary, let’s see what Ember’s solution of indicating the loading of data brings to the table:

  1. It uses a convention to eliminate boilerplate and spare you from having to come up with your own solution.
  2. It allows different markup and text for the different “slow” parts. By default, each loading template will be rendered exactly where the data would be rendered.
  3. If this default behavior does not suit your taste or needs, there are several ways to tweak it, in well-defined ways.

Note: The latest version of the code that contains these changes is available on Github.

Replacing Items in Browser History in Ember.js

One of the outstanding features of Ember.js is that all things related to URLs, including going back and forth in browser history, just work. This is something people got used to with “classical”, server-side applications and that several other client-side frameworks lack.

In this post, I am going to focus on a browser history feature, replacing entries in it as users navigate between routes instead of adding to it.

Navigating between routes in Ember

If either the link-to template helper or the route’s transitionTo method is used to move between routes (and thus URLs), a new entry is going to be added to the browser’s history. That is fine most of the time but sometimes the desired behavior might be replacing the current entry.

Taking the example from the guide, if one is paging through the comments made on a photo where each one has its own route, we probably do not want these comment URLs to clutter the history. Similarly, we don’t want the user to land on these URLs when she hits the Back button in the browser.

Using the link-to helper

All that needs to be done is adding the replace=true option to the link-to helper.

So if the link that takes you to the next comment is written like this:

{{link-to 'Next comment' 'photo.comment' nextComment}}

It should now become:

{{link-to 'Next comment' 'photo.comment' nextComment replace=true}}

Transitioning from inside routes

The canonical way to go from one route to another is route.transitionTo. If flipping between comments of a photo was implemented as an action in the route, the action handler would have the following line:

1
this.transitionTo('photo.comment', nextComment);

To make that replace the current history entry, this becomes:

1
this.replaceWith('photo.comment', nextComment);

replaceWith takes the exact same parameters as transitionTo.

In the controller

As Jacques Crocker points out in his comment below, I missed the case where we want to transition to another route, replacing the current item in the history, from inside a controller.

Here is how to do that:

1
this.replaceRoute('photo.comment', nextComment);

So thank you, Jacques.

Setting the Document Title in Ember Apps

The document title serves as a quick and concise way to identify web pages. It gets displayed in search results and bookmarks and allows the user to see at a glance what content she has open in each tab.

Therefore it is important to have descriptive document titles in our web applications, whether they get rendered on the backend or set in the client app.

In the following short post, I’ll focus on showing how to do that with Ember.

Setting the title property

The way to set the document title from the browser is to just assign a value to the title property of the document:

1
document.title = "1 mind-blowing way to set the title for your html document";

Or, from jQuery:

1
$(document).attr('title',"1 mind-blowing way to set the title for your html document");

Having context-aware titles

For our document titles to be really useful, it would be great to have some kind of information from the page’s content be reflected in them.

To use my favorite example app, Rock & Roll, I expect the page that displays songs from a certain artist to have a segment that is common across all pages in the app and another segment that uniquely identifies that page. For songs of Led Zeppelin, this could be Led Zeppelin songs - Rock & Roll with Ember.js.

I choose to put the unique part first so it can be clearly seen in a tab even if its width is limited.

Finding the best place for setting the title

When considering where to implement setting the title, we have to keep in mind that the code has to run at each route transition so that the title for the new page is correctly set. Also, the context of the page (in the above example, the artist Led Zeppelin) already has to be known.

Considering these constraints, the title could be set either in the afterModel or in the setupController hook. The controller instance is not needed for setting the title so I’ll go with the afterModel hook.

For the artists route, we content ourselves with setting a static title and we can thus focus on the artist.songs route:

1
2
3
4
5
6
7
App.ArtistSongsRoute = Ember.Route.extend({
  (...)
  afterModel: function(model) {
    var artistName = this.modelFor('artist').get('name');
    $(document).attr('title', artistName + ' songs - Rock & Roll');
  }
});

If we now navigate to the songs page for any artist, we can see the name of the artist reflected in the tab title:

Artist name in tab title

NOTE: Jonathan Evans has a great post in which he uses the didTransition action in routes to set the document title. I recommend you to read it.

Make Your Own Computed Property Macro in Ember.js

The most common way to define computed properties (CPs) in Ember.js apps is to call the property function extension, passing in the “dependent keys”, the path patterns that should trigger the recomputation of the property’s value.

The entry-level, classical example is fullName:

1
2
3
4
5
App.Person = Ember.Object.extend({
  fullName: function() {
    return this.get('firstName') + ' ' + this.get('lastName');
  }.property('firstName', 'lastName')
});

person.get('fullName') will change if and only if either firstName or lastName has changed. Its value gets cached between changes.

This simple, yet extremely powerful, construct is a fundemental piece of what makes Ember apps a joy to work with and capable of scaling out to build complex apps.

Let’s now define a slightly more difficult computed property:

1
2
3
latestPosts: function() {
  return this.get('sortedPosts').slice(0, 10);
}.property('sortedPosts.[]')

Assuming that this.get('sortedPosts') contains the sorted posts latestPosts is going to contain the first ten of these.

This is a very common pattern. We only want to show the 10 most recent posts, the three top scorers on a Hall of Fame board or the 10 latest notifications of a user. The above CP definition gets the job done. I see two ways it can be improved, though.

First, it is prone to errors that are hard to debug. If you misspell sortedPosts in the property(…) call, you can spend a considerable amount of time trying to find out why your property does not update correctly.

Second, if it is used in several places of the application, it is a good idea to extract the common pattern and reuse it to cut down on development time and make the code more robust.

Eliminating the duplication

We need a repeatable way to create such computed properties that also eliminates the risk of misspelling the property name:

1
2
3
4
5
function sliced(dependentKey, firstIndex, lastIndex) {
  return function() {
    return this.get(dependentKey).slice(firstIndex, lastIndex);
  }.property(dependentKey + ".[]");
}

This is exactly what we had before for latestPosts. Note the .[] in the property path composition tucked after dependentKey. It guarantees that if any of the elements in the array designated by dependentKey changes (elements are added or removed), the property defined by sliced is going to be updated.

Then, whereever the need to slice up a certain array arises, we can use this method to create it thusly:

1
2
3
4
App.DaysController = Ember.ArrayController.extend({
  workDays: sliced('model', 0, 5),
  weekend: sliced('model', 5)
})

As usual, I put together an example to demonstrate how it works in practice:

Sliced property generator

A couple of useful resources

A handful of computed property macros are built into Ember, while the ember-cpm library defines some more, so check these first if you recurringly find yourself in need of a certain logic in computed properties.

If you still haven’t found what you’re looking for, this post hopefully sets you on your way to define your own ones.

Dependency Injection in Ember.js - Going Deeper

In a previous post I introduced the basic elements of Dependency Injection in Ember and showed how to set up a dependency on the objects it is needed on. I also mentioned the framework itself uses this same mechanism to establish its dependencies.

In this post, I’ll expand on this latter. I’ll point at where these dependencies are set up which gives me the possibility to introduce the options of the basic parts, register and inject.

I’ll also share a couple of tricks to prevent using the abominable this.__container__ and finish by showing how these pieces fit together in the main method of the container, container.lookup.

How does Ember do it?

When an Ember app is created, the first thing it does is creating a container it uses internally:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var Application = Namespace.extend(DeferredMixin, {
  (...)
  init: function() {
    if (!this.$) { this.$ = jQuery; }
    this.__container__ = this.buildContainer();
    (...)
  },
  (...)
  buildContainer: function() {
    var container = this.__container__ = Application.buildContainer(this);

    return container;
  },
}

(link to soure code)

(Note: Here is where App.__container__ gets set and thus you, as an application developer has access to the underlying container. Notice the double underscores, though. It tells you that you should not ever use that in “real” apps. There are officially supported ways, public API methods to achieve whatever you strive to achieve the forbidden way. It is sometimes enough to ask on Twitter.)

Let’s see how the container is built up (as usual, I cut out the parts that are not relevant to the current subject):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
  buildContainer: function(namespace) {
    var container = new Container();

    (...)
    container.optionsForType('component', { singleton: false });
    container.optionsForType('view', { singleton: false });
    container.optionsForType('template', { instantiate: false });
    container.optionsForType('helper', { instantiate: false });

    container.register('application:main', namespace, { instantiate: false });

    container.register('controller:basic', Controller, { instantiate: false });
    container.register('controller:object', ObjectController, { instantiate: false });
    container.register('controller:array', ArrayController, { instantiate: false });
    container.register('route:basic', Route, { instantiate: false });

    container.register('router:main',  Router);
    container.injection('router:main', 'namespace', 'application:main');

    (...)

    container.injection('controller', 'target', 'router:main');
    container.injection('controller', 'namespace', 'application:main');

    container.injection('route', 'router', 'router:main');

    (...)

    return container;
  }

(link to source code)

The faithful reader knows from the first part in the DI series that the above makes it so that e.g this.namespace points to the application in all controllers or that this.router refers to the router in all routes.

Let’s now turn out attention to the first definition block to learn new things.

optionsForType

optionsForType is a comfortable way to define options that should be used when looking up any instance of a particular type from the container.

It can be seen above that components and views are defined as non-singletons which mean that any time a component or view is looked up on the container, a new instance is created and returned.

I got me some code to prove it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
App = Ember.Application.create();

var Artist = Ember.Object.extend();

Ember.Application.initializer({
  name: "setup",
  initialize: function(container, application) {
    container.optionsForType('model', { singleton: false });
    container.register('model:artist', Artist);
  }
});

App.IndexRoute = Ember.Route.extend({
  model: function() {
    var artist1 = this.container.lookup('model:artist');
    var artist2 = this.container.lookup('model:artist');
    return [artist1, artist2];
  }
});

App.IndexController = Ember.ArrayController.extend({
  equal: function() {
    return this.get('firstObject') === this.get('lastObject');
  }.property('model.{firstObject, lastObject}')
});

If you then write a template for the index route that just displays the equal property you’ll see that its value is false, thus a new object is in fact instantiated each time.

Here is a link to the jsbin if you would like to see it.

If you replace { singleton: false } with { singleton: true } the equal property is going to be true, the model object is going to be a true singleton.

Singletons are the default

As Ember core team meber Stefan Penner points out, the { singleton: true } option is the default, so there is no need to explicitly state it.

As a consequence, container.register('store:main', Store, { singleton: true }) is exactly the same as application.register('store', Store).

Objects that come from the container can access it

I learned this from Matthew Beale, a prolific Ember contributor and presenter. It’s well worth your time to watch his presentation on “Containers and Dependency Injection” he gave at an Ember NYC meetup.

Amongst other useful stuff, he also reveals that all objects that come from the container have access to it via a container property on them.

That allowed me to write this.container.lookup in the route above since routes are created by the container, too.

This also does away with the need to use the private __container__ in most cases.

To instantiate or not to instantiate

Above, in the code for buildContainer you can see another option, instantiate, which is false for templates and helpers. To save you from scrolling all the way up, here are the relevant lines:

1
2
  container.optionsForType('template', { instantiate: false });
  container.optionsForType('helper', { instantiate: false });

This option permits the registration of entities (yeah, stuff) that do not need to be instantiated (or cannot be). Templates and helpers fit the bill since they are functions and thus cannot be instantiated.

container.lookup

The lookup method in the container is a great summary for all the things discussed here.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function lookup(container, fullName, options) {
  options = options || {};

  if (container.cache.has(fullName) && options.singleton !== false) { // 1
    return container.cache.get(fullName);
  }

  var value = instantiate(container, fullName); // 2

  if (value === undefined) { return; }

  if (isSingleton(container, fullName) && options.singleton !== false) {
    container.cache.set(fullName, value); // 3
  }

  return value; // 4
}

First, if a singleton is needed and the object has already been looked up, we just return the object saved in the cache. (see 1 above)

Next, we instantiate an object for the fullName (e.g ‘controller:artists’ or ‘route:index’). The instantiate method takes care of just returning the value if the instantiate option is set to false. (see 2 above)

If the instantiation was successful (the factory was found) and a singletion was demanded, we set this value in the cache so that we can return it the next time it is looked up. (see 3 above)

Finally, we return what was looked up. (see 4 above)

container.lookup just calls the above function after verifying the fullName has the right syntax, that is it has a type and a name part joined together by a :.

And that’s where everything comes together.

Ember.run.bind

Ember has several great features that are not widely known, like its Dependency Injection system I wrote about last week.

It has also really handy API methods in hiding. One usually stumbles on them while looking for something in the superbly commented source code.

I hereby introduce such a handy method and hope to make that into a recurring thing. Who knows? Eventually this might also grow into a series.

If it does, I would have to find a catchy name for it. “Ember Chispas” came to mind and rings nice but unfortunately Jeffrey Biles already has a monopoly on it via his “Ember Sparks” series. (Chispa is Spanish for spark.) We’ll have to talk, Jeffrey :)

Anyway, let’s see the first thingie.

… and in the runloop bind them

The run loop in Ember deserves its own blog post series, and I am probably not the one who will write it. (The official guide on the subject is a good place to start, Alex Matchneer’s “Everything You Never Wanted to Know About the Ember Run Loop” is more elaborate).

For the sake of this chispa, it suffices to state that any async callback from a 3rd party javascript library needs to be wrapped into an Ember.run.

Blatantly stealing the example from the source code, here is how this is done:

1
2
3
4
5
6
var that = this;
jQuery(window).on('resize', function(){
  Ember.run(function(){
    that.handleResize();
  });
});

See that beautiful var that=this;? It can be got ridden of via Ember.run.bind:

1
jQuery(window).on('resize', Ember.run.bind(this, this.handleResize));

Less code to write and all the mustaches are gone (not that there is anything wrong with {{mustaches}}, of course).

Dependency Injection in Ember.js - First Steps

Dependency injection (DI) is a less-known, yet powerful feature of the framework we know and love called Ember.js. It works through the container and is comprised of two parts: registration and injection.

The framework itself uses it so that the objects instantiated through the container have the dependencies correctly initialized on them (for the theoretical programmers out there, the Ember DI system is thus probably considered a construction-time DI). The API methods are exposed to application developers for them to register and inject their own objects.

In this first blog post, I’ll introduce the main concepts. In a couple of further blog posts I intend to dig deeper, give examples of what it can be used for and show a few gotchas.

Step 1 - Registration

To be able to inject an entity onto others it first has to be registered on the container. Think of the container as the birthplace of objects in Ember. It knows how to instantiate objects and look up factories by their name.

Throughout the post, I’ll use the example of a store. If you have worked with ember-data, the store is the principal piece. It creates model objects and finds them by their type, id or other criteria so you probably want it to be accessible from routes and controllers alike.

If you have not come through such a store, don’t despair. It is but a handy example to illustrate dependency injection and how it works for a singleton object.

Let’s assume we have a reference to the store “class” in a variable called Store. To register said store, we write the following:

1
2
3
4
5
6
7
Ember.Application.initializer({
  name: "store",

  initialize: function(container, application) {
    container.register('store:main', Store, { singleton: true });
  }
});

The container now knows the store by the name store:main. That is the name it has to be referred by subsequently. The singleton: true option instructs the container not to instantiate a new object each time but use a singleton instead.

Step 2 - Injection

Once the object/factory is registered, it can be used on other objects in the application. As mentioned above, a store is best used from controllers and routes. So let’s inject them there:

1
2
3
4
5
6
7
8
9
Ember.Application.initializer({
  name: "injectStore",
  before: "store",

  initialize: function(container, application) {
    application.inject('controller', 'store', 'store:main');
    application.inject('route', 'store', 'store:main');
  }
});

The main method, application.inject takes as its first argument the object(s) where we want the injection to happen, then the injected name and then the name of what should be injected. The “what should be injected” has to be the same name we had registered the object previously with.

The first parameter, controller and route define what is called a type injection. This means the injected name will be available on all instances of the type, all controllers and routes in this case. The injected name is store and it refers to a single instance of the store class since that’s how we defined it at registration time.

We could also just define a simple injection. In a somewhat hypotethical example, let’s assume we only need the store on the artists route. We write the following to achieve that:

1
2
3
4
5
6
7
8
Ember.Application.initializer({
  name: "injectStore",
  before: "store",

  initialize: function(container, application) {
    application.inject('route:artists', 'store', 'store:main');
  }
});

Step 3 - Putting the two pieces together

Let’s say we want to create an artist object in a route and that creating objects happens through the store (as it does in ember-data, e.g). The following snippets set up the injection:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Ember.Application.initializer({
  name: "store",

  initialize: function(container, application) {
    container.register('store:main', App.Store, { singleton: true });
  }
});

Ember.Application.initializer({
  name: "injectStore",
  before: "store",

  initialize: function(container, application) {
    application.inject('route', 'store', 'store:main');
  }
});

This makes the singleton instance of the store available on all routes of the application so we could, for example, write this:

1
2
3
4
5
App.IndexRoute = Ember.Route.extend({
  model: function() {
    return this.store.createRecord('artist');
  }
});

I also created a jsbin to show this in action, although admittedly there is little action at this point.

Why DI?

This is all fine and dandy, but what problems does dependency injection solve? First and foremost, it decouples the pieces of your application. Dependencies are not hardcoded but injected at construction time. This makes your components easier to use together since pieces can be swapped in and out as needed.

It is also the de facto way of adding the objects that are not provided by Ember.js to your application. The store is an example of such an object but you can also add analytics integration, a pool of workers and other fancy things easily.

An added benefit is improved unit testing since you can inject mocks as cooperators and verify calls made on those.

We are going to look at other aspects of DI in Ember.js in more detail in a next post. Stay tuned and prepare your mojitos.

Observable Path Patterns in Ember

Property paths are the heart and soul of Ember.js apps. You use them in templates and you define dependencies for computed properties and observers through property paths.

In this post, I concentrate on this latter and show you various ways of setting up these dependencies through a practical example. There is a pretty good section in the guides about one path pattern. Here, I intend to cover more (all?) of them.

Badges are back

I am going to build on the badges “micro-app” that I had started to develop in my previous post about getters in setters.

There are two minimal model classes, User and Badge:

1
2
3
4
5
6
7
8
9
App.User  = Ember.Object.extend({
  name: ''
});

App.Badge = Ember.Object.extend({
  name: '',
  score: 0,
  unlocked: false
});

We also create a couple of instances to have some data to show and work with:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var cory = App.User.create({ name: "Cory Filibuster" });

var rook = App.Badge.create({
  name: "R00k",
  score: 1,
  unlocked: true
});

var taciturn = App.Badge.create({
  name: "Taciturn",
  score: 10
});

var talkative = App.Badge.create({
  name: "Talkative",
  score: 100
});

var hemingway = App.Badge.create({
  name: "Hemingway",
  score: 1000
});

Our application looks like this initally:

Initital state

Simple property chain

The simplest, non-aggregate property path is just a series of names, connected by dots. This designates a property that you can arrive at by walking the path, segment by segment, where each of them gets you to another object until you finally reach the property.

(If a path is very long, you should probably think about the dependencies between your objects and the structure of your code.)

You see that the profile panel has the user’s first name as its header. The property that gets displayed there can be defined by such a path:

1
2
3
4
5
6
App.IndexController = Ember.ArrayController.extend({
  (...)
  firstName: function() {
    return this.get('user.name').split(/\s+/)[0];
  }.property('user.name'),
});

This sets up a computed property (CP) that will be recomputed whenever user.name changes. The arguments to the property call are called the dependent keys of the CP and you can pass as many as you would like (although, thanks to the various property path patterns, you will rarely need a lot).

Now, whenever the name property of the user property on the controller changes, firstName is recomputed and this change gets propagated to all the instances where firstName is used (e.g in the header of the panel).

Above that, the user.name key also triggers a change if the user object itself changes. To see that, we turn to the thing you should only ever use for demo purposes, the __container__ object:

1
2
var maggie = App.User.create({ name: "Maggie Raindance" });
App.__container__.lookup('controller:index').set('user', maggie);

You can see the name change in the header right away:

User name changes

Aggregate property paths

On other occasions, a CP should depend on an array of items. Whenever something gets added to or removed from the array, the property needs to be updated.

One example of that is the number of badges in the profile panel:

1
2
3
4
5
6
App.IndexController = Ember.ArrayController.extend({
  (...)
  badgeCount: function() {
    return this.get('model').length;
  }.property('model.[]'),
});

The model here is the array of badges so when we add another one through the New badge panel, badgeCount gets its new value:

Badge count gets updated

What I said about the user.name path triggering an update when the user changes also holds true here. If the array of badges was swapped out for another array, it would trigger the recalculation of badgeCount.

Aggregate property path with a specified property

There are cases where the value of the CP becomes stale also when the items in the dependent array stay the same, but a certain property of one of them changes. Ember has a way to express this very succintly.

The example is the “Total score” in the profile panel:

1
2
3
4
5
6
7
App.IndexController = Ember.ArrayController.extend({
  (...)
  totalScore: function() {
    var sum = function(s1, s2) { return s1 + s2; };
    return this.get('model').getEach('score').reduce(sum);
  }.property('model.@each.score'),
});

This is the most inclusive of the patterns we have seen so far. It prompts an update if the model changes, if any item is added or removed and also if the score of any item changes. If we type this at the console:

1
App.__container__.lookup('controller:index').set('model.lastObject.score', 200);

, then the total score changes accordingly, even though no item was inserted or deleted:

Total score

Brace yourself

To present the next pattern, let’s assume that not all badge scores need to be tallied to get the total but only the unlocked ones (which makes total sense). So the dependent keys for totalScore needs to account for that. That’s pretty easy:

1
2
3
4
5
6
7
App.IndexController = Ember.ArrayController.extend({
  (...)
  totalScore: function() {
    var sum = function(s1, s2) { return s1 + s2; };
    return this.get('model').filterBy('unlocked').getEach('score').reduce(sum);
  }.property('model.@each.score', 'model.@each.unlocked'),
});

When the second badge is unlocked, the score jumps from 1 to 11 (and the number of badges from 1 to 2), so the dependent keys work fine:

1
App.__container__.lookup('controller:index').get('model').objectAt(1).set('unlocked', true);

Unlocked property change triggers update

Starting with Ember 1.4.0, though, there is a more concise way to define the same, called “property brace expansion”. It works very similar to argument expansion in the shell:

1
2
3
4
5
6
7
App.IndexController = Ember.ArrayController.extend({
  (...)
  totalScore: function() {
    var sum = function(s1, s2) { return s1 + s2; };
    return this.get('model').filterBy('unlocked').getEach('score').reduce(sum);
  }.property('model.@each.{score,unlocked}'),
});

This establishes that totalScore should be recomputed if either the score or unlocked properties of any item in the model array changes.

An important restriction of property brace expansion is that the expansion part can only be placed at the end of the path, so e.g property('{foo,bar}.baz') will not have the desired effect.

Computed property macros are the bee’s knees

Computed property macros have several advantages. They are very expressive, very performant and perhaps most importantly more robust than typing out the property path patterns by hand where a typo can cause a considerable amount of head-scratching.

They are also a joy to work with and compose. In fact, all the CP definitions above can be re-defined by using only macros:

1
2
3
4
5
6
7
App.IndexController = Ember.ArrayController.extend({
  (...)
  badgeCount: Ember.computed.alias('unlockedBadges.length'),
  unlockedBadges: Ember.computed.filterBy('model', 'unlocked'),
  unlockedScores: Ember.computed.mapBy('unlockedBadges', 'score'),
  totalScore: Ember.computed.sum('unlockedScores'),
});

They have one big disadvantage, though. It is very hard to use them in a blog post to explain property path patterns.

(The code presented here can be found as a gist on Github)

ps. Yes, that Maggie Raindance.)