Ember Components, Controllers, and the Interface Model

I write lots of ember components.  Most components have a certain amount of interop with the controller that is presenting it. How you manage that coupling makes all the difference, though.

There’s two schools of thought for components.  The idiomatic way, as presented in the ember guides, would be to have a single action for a component that is bound to an action or method on the presenting controller.  This style of design lets you work on having a component to one thing well, though it has a few limitations.  For starters, if you’re building a component because there’s (almost) no reason to use a view, a single action and some bound properties doesn’t make life easy for having a robust component.  Second, most UI widgets I end up building do quite a few things in the context of itself based upon the state of the controller.

The second way, and the way I’ve been working lately, is to pass the presenting context as a property called “ctx” to the component.  This allows me to use any method, property, or computed on the controller in my component without having to explicitly bind each value.  You could argue that you’re saving on setter/getter calls due to fetching directly from the controller.  You could also argue this is handy because it allows a controller to mixin support for a style of component.  Hey — that means we get interfaces! in javascript!

Lets say we have the following bits:

This looks wacky, but there’s a sort of mad scientist vibe happening here.  We’ve been able to define a discreet bit of functionality within a mixin that any controller can use to support a component.

To me, this looks like a better model than the one-action-multiple-bindings approach that the guides provide. You have the flexibility to provide action bubbling by invoking actions on a controller, which eliminates the need for a large implementation at the component level.

This all comes with one giant disclaimer — this approach works because it requires discipline.  If this looks like it’s a lot of extra work– that’s because it is. And that’s okay, because we’re doing something wacky with a pattern that doesn’t technically exist in the language we’re working in.  Most of the time, I’d recommend you build toward the best case – which is standalone, loosely coupled components that don’t work with the controller much at all.

But, for those moments where that’s not enough, and you’re about to build a view, this is the best alternative I’ve been able to find.