How to use outlets from within your each loop

Published on April 21, 2015 by Toran Billups

*Ember 2 Update* I've created a modern version of this technique with ember-twiddle for all those using ember 2x

*Glimmer Update* the custom-outlet you see below isn't necessary because the Ember.Assert that required quoted args was removed. Because glimmer isn't stable yet I didn't modify the below/or the example project I put together back in April. Instead I created a glimmer branch and you can checkout the commits for technical details about how it works w/ canary today. Big thanks to intuitivepixel for the pull request that landed the final working glimmer nested outlet example!

If you've ever tried to inject a template inside of an outlet that is itself inside of an each loop might find it's full of surprises. I decided to outline each issue I ran up against and talk through the final solution I ended up with.

If you just want to see the commits and the example ember-cli project check it out on github. Each commit along the way tells part of the story (as you will quickly see below).

First I wanted to see what a single outlet would do so I created a bare bones app with a single nested template. I then added the line you see below in my parent template so I could inject the child html on the fly.

Here is the simple parent/child route relationship for reference.

The first issue I found after I got this much functional was that if I clicked any one of the details links it would inject the child html into EACH of the outlets. The desired behavior is that it should only inject into a single outlet.

The next challenge was that I had an index value (from the each loop -using ember 1.11) but outlet won't accept a non quoted name. So I instead created a custom-outlet (HTMLBars helper) that would let a number/integer based value play the role of my outlet name.

This looks like something that could be added to the normal outlet (in the future) but at this time it requires the ugly hack you see below (in the app.js file of your ember-cli project).

Now in my parent template I can pass the index in as a named outlet using the new "custom-outlet" helper.

But now when I click the link-to helper in the browser nothing shows up. To correct this you need to add some renderTemplate logic to the child route itself.

This now renders correctly but when I click a second or third link it's clear I'm not closing /or disconnecting the previous. To do this just add the following willTransition logic to the child route.

Now this works perfectly but what if I want to have that same outlet inject another template (not details)? Turns out that custom-outlet is reuse friendly! Just add another route/template and link-to and you are off to the races!

Hope this helps someone else get the same great UX w/out all the pain I went through!