10 Comments

5 Ember.js Addons You Should Start Using

ember_Ember-Light
At Atomic Object, we’ve done a lot of work (and a lot of thinking) about the Ember.js application development framework. We also love using open source libraries to help us get more work done, as efficiently as possible. So here are five Ember addons that I think are worth looking into.

1. ember-data-factory-guy


Testing is an essential part of writing quality code. At Atomic Object, we practice Test Driven Development (TDD) whenever possible. Tests often rely on setting up a specific data state within the application, making a programmatic change or calling a function, and asserting that the output or mutated state is correct.

The addon ember-data-factory-guy  is designed specifically for Ember Data models in a testing environment. There are many advantages to using factory-guy instead of filling your tests with repeated @store.createRecord() calls, among them:

  • It helps streamline testing setup.

  • Using factories lets you avoid doing the same thing over and over (creating records manually).

  • The factory-guy syntax is declarative and easy to read.

  • It does a lot of work for you out of the box (provided you are using Ember Data).

Factory-guy comes with generators, so creating a new factory is easy from the command line: ember g factory user will create a factory named users.js in the tests/factory folder. One of the many things I love about factory-guy is that it will automatically fill in hasMany relationships, saving you from the annoyance of creating all the records yourself in test setup.

For instance, a User model may have many cars:

  User = DS.Model.extend({
    name: DS.attr('string'),
    cars: DS.hasMany('car')
  });

The corresponding factory can, by default, fill in a car whenever a user is created, or create custom factories:

FactoryGuy.define('user', {
  default: {
    name: "Jim Bob",
    cars: FactoryGuy.hasMany('car', 1)
  },
  jay_leno: {
    name: "Jay Leno",
    cars: FactoryGuy.hasMany('car', 130)
  }

To create a default user, your test would call FactoryGuy.make('user');. To use our custom jay_leno user, it would be: FactoryGuy.make('jay_leno');. It’s very easy.

Obviously, that only scratches the surface of the features factory-guy provides. You can check out more at factory-guy’s github repository.

2. ember-ajax


Most ambitious web applications are backed by some web server that provides an API consumed by the web app. Libraries like Ember Data will automatically make requests to the API, but often developers will need to make requests themselves. In those cases, you should reach for the ember-ajax addon.

Ember-ajax provides a straightforward AJAX service for use in Ember applications (unsurprisingly, it wraps jQuery AJAX). It provides convenient HTTP verbs: POST, PUT, DEL, PATCH–but not GET (get is a special method reserver on every Ember.Object). Since this addon is a service, it can be included in your Ember code via dependency injection:

import Ember from 'ember';
 
export default Ember.Route.extend({
  ajax: Ember.inject.service(),
  model() {
    return this.get('ajax').request('/posts');
  }
});

And since it’s a regular Ember.Service, it can be easily injected into tests and mocked, stubbed, etc.

3. ember-wormhole


There are times when you may come across a case where a UI is a logical child of another UI element, but it needs to render as a top-level DOM element. In these cases, look no further than ember-wormhole, which allows you to render a block anywhere on the page.

My colleague Jeanette Head correctly pointed out that rendering to arbitrary DOM locations can be a bad smell in a web application, and this addon provides plenty of rope for a developer to get themselves into trouble. I personally have come across two clear and common cases where the wormhole has been useful:

  • Modals: Say you have a component deeply nested in an application, and it needs to open a modal which pops up and covers the entire UI or grays out the rest of the screen–but it uses data that is in the scope of the component. In this case, the wormhole would lead from the component to some top-level DOM element where the modal resides.

  • Popovers: When validating an input field or providing a small contexture UI, we may want to display an element that sits “on top” of the field or control. In this case, I have struggled with containing div elements that have CSS overflow properties and incorrectly clip the popover. Ember-wormhole can be used to bring the popover up to a higher level in the DOM and avoid the overflow clipping problem.

Ember-wormhole is very powerful–and can be very useful–but always remember, with great power comes great responsibility.

4. ember-truth-helpers


It can be annoying to create computed properties on Ember Components and Controllers just to perform simple logical operations. In the past, I have found myself tediously wiring up simple computed properties using Ember.Computed not, equal, gte, lte, etc. A little addon called ember-truth-helpers has helped me avoid writing all these extra computed properties myself. It lets you move the logic into the template, using a nice syntax:

truth-helpers

5. ember-i18n


Finally, a favorite and (in my opinion) a necessity for developing any Ember application that requires localization: ember-i18n.

To declare translations, files must go in app/locales/[locale]/translations.js, and export an object containing functions or strings as keys that will be used to translate for a given locale. For instance, this translations object will have a key user.edit.title that will translate to “Edit User” in English:

export default {
  'user.edit.title': 'Edit User'
}

Any text that must be translated will use that above key to render the correct translated content. Ember-i18n provides handlebars helpers and an i18n service for translating: the handlebars {{t}} helper.

{{t "user.edit.title"}}

The above code will render Edit User on the page. The service provides a t function used to translate as follows:

export default Ember.Object.extend({
  i18n: Ember.inject.service(),
 
  afterModel: function(post) {
    document.title = this.get('i18n').t('title.post', { post: post });
  }
});

Ember-i18n has a lot of other cool features including location fallback, nested translations, string interpolation, dynamic locale setting, pluralization, etc. It also has great documentation. Be sure to check it out at its github repo.

I’ve covered five Ember addons that I’ve found to be extremely useful, but I always love to hear about new ones that I haven’t tried. What addons have you used in your Ember projects?