Search code examples
templatesember.jsroutesoutlet

Ember: how to render to an outlet in a parent route/template?


I have a page on our site, lets call it "animals", which is broken into two sections - there's a menu on the left and content in a panel on the right. The left menu has two tabs; "cats" and "dogs", each with a list of breeds in them.

So if I go to /animals/dogs/beagle I want to see the dogs tab open with 'beagle' selected and the information about beagles in the panel on the right.

My problem is that the physical hierarchy of my templates doesn't really follow my route hierarchy, as the /animals route is effectively the whole screen including the panel on the right and some functionality around the menu on the left (allowing it to be hidden, etc). The animal route (/cats or /dogs) is a template rendered inside the {{outlet}} within the menu on the left, but because the breed information I want to render doesn't sit inside the area "owned" by the template above it (inside the menu on the left) I don't really know how to get it to where it's supposed to be (which is maybe a second {{outlet}} inside the top-level /animals template?).

What's the best/right way to achieve this without effectively reproducing the whole screen at the lowest level of my hierarchy just so these two sections sit within the same template area?

Here's some ASCII art :)

 ------------------------------------------------------------
| Animals                                                    |
|   ------   ------          ----------------------------    |
|  | Cats | | Dogs |        | All about Persian cats...  |   |
|  |      `------------     |                            |   |
|  | Birman            |    |                            |   |
|  | >Persian<         |    |                            |   |
|  | Siamese           |    |                            |   |
|   -------------------      ----------------------------    |
 ------------------------------------------------------------

Solution

  • What you are looking for is named outlets. More on it here : http://emberjs.com/guides/routing/rendering-a-template/

    Basically in your animals template you would have to define outlet like :

          <h5>ANIMALS</h5>
          <div>
            <div style="with:40%; float: left;">
              <div style="padding-right:20px;">
                <div>NAVIGATION</div>
                SOME NAVIGATION STUFF
            </div>
            <div style="with:60%; float: left;">
              <div>DETAILS</div>
              <div>{{outlet 'details'}}</div>//THIS IS WHERE YOUR DETAILS STUFF WILL BE RENDERED
            </div>
            <div style="clear:both;"></div>
          </div>
    

    and you would have your breed specific details rendered in the outlet named "details". The way you control what should be rendered where can be specified in the "renderTemplate" hook in your respective , like this:

            App.BreedRoute = Ember.Route.extend({
              .....
    
              renderTemplate: function() {
                this.render({'into':'animals', 'outlet':'details'});
              }
            });
    

    which basically says, whatever output you get out of 'breed' route should be rendered into 'details' outlet which you can find in 'animals' route.

    here is a jsbin to give you an idea : http://emberjs.jsbin.com/bugexa/1/

    click on the breed list to show the details in the right hand section of the screen. Hope this helps.