On Friday I gave a presentation at EmberFest. The talk was framed by having worked on several Ember codebases, including one for almost 9 months. I’ve found that new Ember developers (or even experienced ones!) tend to lean heavily on feature-rich controllers to architect their applications- this works for a time, but as a codebase grows in complexity the controllers become unwieldy and confusing.

The fantastic Luke Melia must be thinking the same thing, because in RC8 he landed a change of the events hash to be called actions. This cosmetic change is almost a distraction from the real change: A refactoring of how controllers, routes, and views handle actions.

There is now an Ember.ActionHandler mixin that unifies the behavior. Check it out:

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
var Actionable = Ember.Object.extend(Ember.ActionHandler);
 
var secondTarget = Actionable.extend({
  actions: {
    "Wie Ghet's": function(){
     console.log("Und dir?");
    }
  }
}).create();
 
var firstTarget = Actionable.extend({
  target: secondTarget,
  actions: {
    "Wie Ghet's": function(){  // If actions was undefined or this action didn't exist, only secondTarget would handle it.
      console.log("Danke gut");
      return true; // If you return true, the event will continue to bubble.
    }
  }
}).create();
 
firstTarget.send("Wie Ghet's");

 
// Danke gut
// Und dir?

Having this behavior consistent, especially the logic behind when to bubble an action or not, is incredibly important. Thanks Luke!

I find that most successful Ember projects follow a simple pattern for application design:

  • Controllers present information to templates. And not much else, ideally.
  • Actions are handled on routes. This makes routes (which can access models and arbitrary controllers via controllerFor) and controllers each responsible for a different set of concerns.

The result is better and more maintainable code. Here are the slides from the talk:

Rumor has it that we may have video soon, I’ll update this post when they are published.

Update: Many thanks to Luke Melia for catching a few bugs in the code samples!

Update 2: Now with video from the NYC meetup.

By Matthew Beale
4 comments
  1. Allen at September 6th, 2013 at 07:46 PM

    Hi Matt, Thanks for the post. I am an Ember newbie and my understanding of your post may be wrong, but what you stated in the post seems to be in conflict with Ember website’s guide.

    Let’s take TO-DO example on the ember site, are you saying that “add a new to-do” should be happening in route instead of in a controller?

    I have been following your blogs and they are tremendous helps to me, but this one is a bit confusing to me. A video may help clarify things a lot, I will be waiting for your updates.

  2. Matthew Beale at September 10th, 2013 at 08:49 AM

    @Allen I can’t be sure which code on the Ember.js website you are referring to, so responding in specifics may be impossible. Actions can certainly be handled on controller objects, but it is my experience that the expected behavior of a given action is often dependent on what page the user is visiting, and not what the context of a given template is. It is a subtle difference, but using actions this way tends to keep controllers much simpler and much less coupled to other controllers.

    There are always exceptions, and for smaller apps this could be considered a non-issue. And again, actions do of course bubble through controllers and can be handled there if you choose to follow that pattern. I only suggest you consider how that decision impacts the flexibility of your code.

  3. Allen at September 11th, 2013 at 01:42 PM

    @Matt Thanks for the clarification. I think I understand your point a bit more. The code I was referring to is the “createToDo” action in Todos.TodosController at http://emberjs.com/guides/getting-started/creating-a-new-model/

  4. Tom C at October 3rd, 2013 at 04:11 PM

    Thanks for this. Wonderfully enlightening.

Comments are closed for this article.