Best practices for ember subnavs


#1

I’m not trying to pull a double stackoverflow and discuss post but I have several projects coming up that involve subnavs, some relatively complex, and I just wanted to see what people thought the best way to go about this in ember is so not resort to a bunch of jQuery hacking.

My original SO post is here if you’re interested: http://stackoverflow.com/questions/18475041/want-ember-js-named-outlet-to-only-display-on-click

But ultimately, I have a navigation bar set up in the application template and I would like a subnav to display when the ‘about’ link on main nav is clicked, but I don’t want anything else to change except for maybe the url changing to /about, but not /about/subnav, which is what is currently happening with the way I am implementing named outlets.

Then when one of the sub links is clicked, say ‘leadership’, the url will change to /about/leadership and the leadership template will load and the subnav will remain displayed.

Here’s my github repo as well. Thanks very much.


#2

You should use nested resources for that.

Here’s a jsbin that shows how that would work.

The main part is the routes/resources declaration:

App.Router.map(function() {
  this.resource("about", function() {
    this.route("philosophy");
    this.route("leadership");
    this.route("staff");
    this.route("affiliations");
  });
  
  this.route("conditions");
  this.route("programs");
  this.route("testimonials");
});

Here, you define an aboutresource which have a few nested routes.

Then, it’s all about conventions. You just have to properly name your templates.

Here’s the application template:

<h1>MAIN</h1>
<nav>
  <ul>
    <li>{{#linkTo "about"}}about{{/linkTo}}</li>
    <li>{{#linkTo "conditions"}}conditions{{/linkTo}}</li>
    <li>{{#linkTo "programs"}}programs{{/linkTo}}</li>
    <li>{{#linkTo "testimonials"}}testimonials{{/linkTo}}</li>
  </ul>
</nav>
{{outlet}}

Here’s the about template:

<h2>ABOUT</h2>
<nav>
  <ul>
    <li>{{#linkTo "about.philosophy"}}philosophy{{/linkTo}}</li>
    <li>{{#linkTo "about.leadership"}}leadership{{/linkTo}}</li>
    <li>{{#linkTo "about.staff"}}staff{{/linkTo}}</li>
    <li>{{#linkTo "about.affiliations"}}affiliations{{/linkTo}}</li>
  </ul>
</nav>
{{outlet}}

Here’s the about/philosophy template:

handlebars

PHILOSOPHY

```

Ember will automagically add an .active class to all the links in the current route.

EDIT: you should definitely check out @ryanflorence’s excellent video on nested routes.


#3

What if I want the about subnav to display in the application template and not the about template? The nav code is currently in application.hbs, including a background image where the nav and subnav are going to be displayed, so if I render the about subnav in the about template it won’t be with the other nav styled with the bg image in application.hbs.


#4

The longer I look at it I think I may be able to move the subnav handlebars code to about.hbs. I’ll let you know. Thank you again for your help.


#5

I am working on a similar problem. Trying to do a pull down select list. Asked the question on SO.

Solution seems to be to put some state in the ApplicationController.

Here is an example:


#6

I guess my question now is if I use nested routes and have have the ‘about’ template render in the outlet where the subnav is supposed to be (the about template is nothing but sublinks), and then do something like this:

<script type="text/x-handlebars" id="about">
  <h2>About</h2>
  <ul>
    <li>
      {{#linkTo "about.location"}}Location{{/linkTo}}
    </li>
    <li>
      {{#linkTo "about.product"}}Product{{/linkTo}}
   </li>
  </ul>
 {{outlet}}
 </script>

Won’t about.product load in the skinny, horizontal area where my subnav is, thus blowing my skinny subnav into a gigantic template. Don’t I need the outlet for the about subpages outside of the subnav? How do I accomplish this?


#7

I want the sub nav to go in the skinny white bar directly below the main nav, and then the about sub pages to load behind the nav bar, filling up the rest of the page:


#8

You may want to try using a component for this. And have the component render into a named outlet in your main application template.

The nice thing is that the component can be dropped in and shared in all sorts of places, and the context (controller and models) can be passed into it making it a very flexible construct.

In handlebars the component

{{sub-nav}}

I worked out a a basic example of components here.

If you could put together a basic JSBin of the concept you are trying to achieve, I could take a stab at this.


#9

Thank you for your reply. I’ll look into components. Here’s the github repo until I can set up a jsbin: https://github.com/jtrinker/ew