Using Subexpressions (Nested Helpers) in Ember.js

Posted On: February 21, 2015

If you haven’t read my last post go read it now. The TL;DR; is that we are trying render a component dynamically based on what we are rendering, and the current browser width. The component helper got us most of the way there, but we are still relying on the model to have the name of the component to render.

My initial idea was to make own helper, like the component helper, that could take my crazy responsive ideas and pick the best component available to render. So I screamed at twitter…

Can anyone give me a gist on how to render a component from a helper using public apis? Currently on canary. #emberjs

— raytiley (@raytiley) February 19, 2015

However no one answered my call. After enough wining in IRC @rwjblue (did I mention I have a github crush on him) answered my call. Here is a jsbin of what he came up with.

JS Bin

The special sauce is in the ResponsiveComponentHelper’s helperFunction method. It allows me to pass in a baseName that can then be used to find the appropriate helper. I could use it like this.

{{#each item in schedule}}
  {{responsive-component item.type item=item}}

In the above code item.type is baseName of the component, so if type === run it is going to try and find run-sm, run-med etc. This is just an example @rwjblue gave me and I didn’t motify it to actually determine the current breakpoints etc.

It was an awesome first step, but it wasn’t perfect for my needs. The params passed into the helper aren’t bound, and supposedly binding them makes it much more complicated. This means I can’t pass in the current breakpoint and have the componenet change if the user resizes the browser. A less important, but still relevant concern is that I don’t really get what is going on. It is using APIs that I could understand if I read the source, but aren’t documented and may change on some aspiring core contributers whim (@mixonic). But it lit a spark, and here is what I came up with.

JS Bin

So what is this magic? First I am back to using the good old component helper. However the component name I’m passing in is determined using a handlebars subexpression. This is actually the first legit use for supexpressions that I’ve had outside of query params. If you haven’t used a subexpression before the idea is pretty simple. It is a way to call a helper as a paramter to another helper. Its very functional and lispy, but it allows me to isolate what component gets rendered to a single helper that is easily testable.

It allows for the complicated responsive example to become

{{#each item in schedule}}
    {{component (responsive-helper item.component media.currentBreakpoint) item=item}}

The astute observer will notice that I’m still pretty tightly coupled, but that could be reworked (did I mention I am at a bar?). The important bit is that the choice of component is isolated to my responsive-helper and everything is all magically bound, which is the way it should be.

To recap, a subexpression is just a nested helper. It allows you to replace a parameter to a helper with a value calculated by a second helper. For a good example of where subexpressions (nested helpers) can be used to great affect checkout ember-truth-helpers. In our case we are using a custom heler to calculate a component name which we then pass to the component helper.

So what other magic can subexpressions and the component helper be used for? Personally I’m using it to make component choices for an advanced search builder and choosing components based on screen size (seen above). I see myself using this pattern a lot in the future, it’s just that awesome.