Ember pre4 - nested routes
Asked Answered
M

2

5

I'm trying to understand how to use nested routes.

My code:

App.Router.map(function() {
  this.route("site", { path: "/" });
  this.route("about", { path: "/about" });
  this.resource("team", {path:'/team'}, function(){
    this.resource('bob',{path:'/bob'});
  });
});

And I'm trying to get to the Bob page with:

{{#linkTo 'bob'}}bob{{/linkTo}}

What am I missing?

jsbin

Thanks.

Mvd answered 25/1, 2013 at 21:27 Comment(0)
S
11

try instead

{{#linkTo 'team.bob'}}bob{{/linkTo}}

Between you can simplify your router map this way - you only need to specify the path if it's different from the route name.

App.Router.map(function() {
  this.route("site", { path: "/" });
  this.route("about");
  this.resource("team", function(){
    this.route('bob');
  });
});

UPDATE

See a working example here

In summary, You need to provide an implementation of the renderTemplate function of TeamBobRoute where you explicitly specify where you want to render your template bob. Using the render option into you can override the default behaviour, rendering to the parent outlet, and pick which parent template to render to

App.TeamBobRoute = Ember.Route.extend({
  renderTemplate:function(){
    this.render('bob',{
      into:'application',
    });
  }
});

<script type="text/x-handlebars" data-template-name="site-template">
  This is the site template
    {{#linkTo 'about'}}about{{/linkTo}}
     {{#linkTo 'team'}}team{{/linkTo}}
</script>

  <script type="text/x-handlebars" data-template-name="about">
  This is the about page
</script>

    <script type="text/x-handlebars" data-template-name="team">
  This is the team page
    {{#linkTo 'team.bob'}}bob{{/linkTo}}
</script>

  <script type="text/x-handlebars" data-template-name="bob">
  This is the bob page
</script>

<script type="text/x-handlebars">
  This is the application template
  {{outlet}}
</script>

FYI the render method supports the following options: into, outlet and controller as described below.

The name of the PostRoute, as defined by the router, is post.

By default, render will:

  • render the post template
  • with the post view (PostView) for event handling, if one exists
  • and the post controller (PostController), if one exists
  • into the main outlet of the application template

You can override this behavior:

App.PostRoute = App.Route.extend({
  renderTemplate: function() {
    this.render('myPost', {   // the template to render
      into: 'index',          // the template to render into
      outlet: 'detail',       // the name of the outlet in that template
      controller: 'blogPost'  // the controller to use for the template
    });
  }
});

If you had a named template inside your application template then you would target it this way

App.TeamBobRoute = Ember.Route.extend({
  renderTemplate:function(){
    this.render('bob',{
      into:'application',
      outlet:'team-member',
    });
  }
});

<script type="text/x-handlebars">
  This is the application template
  {{outlet 'team-member'}}
  {{outlet}}
</script>
Scholasticate answered 25/1, 2013 at 22:8 Comment(6)
I tried doing that inside the jsbin and it wasn't working. Thanks for the reminder about the paths.Mvd
You need to define route inside a resource not another resource. I updated my answerScholasticate
According to the guides I'm supposed to be able to do a nested resource. For my actual application I do need it to be a nested resource. Can you try getting it to work with the jsbin? I tried even with route and it didn't work either.Mvd
Thanks for the updated jsbin. That does work. Very similar to what Andre pointed out. Wish I could figure out how to make it use the application outlet instead.Mvd
Ok buddy, i figured this out for you, the feature is not documented, i ready in previous version and i had to dig into the source code once again for it. You can use an option 'into' to decide which outlet you're targeting. I'll update my answer shortly with the details, in the meantime you, check out an updated version in jsbin again jsbin.com/ecujad/18/editScholasticate
Ken, thank you so much! That really helps. And it works with resource also.Mvd
C
3

You're missing the outlet in the team page. The template should look like this.

<script type="text/x-handlebars" data-template-name="team">
   This is the team page
   {{#linkTo 'bob'}}bob{{/linkTo}}
   {{outlet}}
</script>

Each route is rendered into it's parent's template's outlet.

so when you go into "team", then "team" is rendered into the "application" outlet.

When you go to "bob", the "bob" template is rendered into the "team" outlet.

This can be overridden, but is the default behavior.

Also, each parent resources gives you two model/controller/view/template sets. So when you define:

this.resource('team',{path:'/team'});

You get the "team" template and the "team-index" template.

the "team" template is where stuff that is shared between child routes goes (this is why it needs to have the outlet) and the "team-index" template is where stuff that is specific to your "team index" would go.

Cristie answered 25/1, 2013 at 22:28 Comment(2)
Thanks for the clarification. That really helps. If I do want the bob template rendered in the application outlet, how do I overwrite that?Mvd
This guide emberjs.com/guides/routing/rendering-a-template goes through some of the options. Although you really want to keep to Ember's naming conventions as much as possible. Instead of rendering "bob" into "application", make "team" contain only the {{outlet}} and "team-index" can contain your current team template. You get the same result, but it stays more true to the way Ember wants you to architect the app.Cristie

© 2022 - 2024 — McMap. All rights reserved.