I am currently working on an ember project using
1.7.1 and I’ve reached the point of no return with regard to passing action names down a component hierarchy and then bubbling them back up using
sendAction. I believe the problem is still present in recent versions of ember and we need to somehow make this more user friendly.
I will illustrate the problem with an easily grokked todo example before giving a couple of solutions.
Here is a list of todos:
Here I am creating a
todo-list component and specifying an action that I want called when a todo is checked to signify it is finished.
Below is a route with a
finishTodo action that is referenced in the above code sample:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
All good so far but with the current state of data down and actions up, I need to pass this action name down to each child component that would use
sendAction to call it.
In the example, I need to specify the action name in each
todo-item component that the
todo-list component creates:
I then need to bubble this up from the child
1 2 3 4 5 6 7 8 9
This gets bubbled up to the
todo-list component that uses
sendAction to bubble this up to the route:
1 2 3 4 5 6 7 8 9
Here is a jsbin that shows the up and down duplicity in its entirety.
One sure sign of tight coupling is the number of places/files that you need to change for one method name change. As developers, we should be seeing this type of thing as a red flag that requires attention.
One way round this is to create a helper to package up the action, the context and any arguments that are needed to call the action. This can be achieved with a handlebars subexpression and a handlebars helper.
I can refactor the
todo-list component to this:
The above code uses a handlebars subexpression to create a method named
action on each
todo-item component, I pass in the
targetObject which in this case is the
controller but you can reference anything that is accessible and has an actions hash, I also pass the action name I want called and any additional arguments.
The subexpression calls this handlebars helper that returns a higher order function:
1 2 3 4 5 6 7 8
I can then call this action in the
1 2 3 4 5 6
Here is a jsbin of the above.
This makes things a little more sane for me and I can eliminate a lot of code. Another alternative that I am considering is to enhance the global event bus I previously blogged about.
The alternative is to carry on with what is currently on offer but I’ve just reached my limit with that.