6
votes

http://jsfiddle.net/bugsinamber/xjvYk/6/

Setup

I have an index view with a list of stories. This gets rendered into the application outlet. When I click on each story, a story view gets rendered into the same outlet (replacing the index view). I'm using nested routes.

Issue

When I click on "all stories" to go back to index view from story view, it works fine. But if hit the browser back button to go back to the index view, the path changes to "/stories" correctly and yet the index view doesn't render. I have to hit the back button one more time for the index view to render.

The template

<script type="text/x-handlebars" data-template-name="application">
    {{outlet}}    
</script>

<script type="text/x-handlebars" data-template-name="stories">
    <p>Stories Index Page</p>    
    {{#each story in controller}}
    {{#linkTo "story"}}
    {{story.title}}
    {{/linkTo}}
    {{/each}}   
</script>

<script type="text/x-handlebars" data-template-name="story">
   {{#linkTo "index"}}Back to all stories{{/linkTo}}

   {{title}}    
    <p>Story test page</p>
</script>

The app.js

App = Ember.Application.create({});

App.Router.map(function() {
    this.resource("stories", function() {
        this.resource("story", {path: ':story_id'});
    }); 
});

App.StoriesRoute = Ember.Route.extend({
  model: function() {
    return App.Story.find();   
  }
});

App.StoryRoute = Ember.Route.extend({
  model: function(params) {
    return App.Story.find(params.story_id);
  },  
  renderTemplate: function() {
      this.render('story', {   // the template to render
          into: 'application' // the template to render into
      });   
  }
});

App.IndexRoute = Ember.Route.extend({
  redirect: function() {
    this.transitionTo('stories');
  } 
});

What I know so far

This works correctly if I don't use nested routes. Apparently I shouldn't use nested routes if I'm not nesting my views, but that limits the design needs. Logically, I should be allowed to use nested routes in this case.

I'm nesting the routes because I need to access "stories" from the story controller like shown below. If I don't nest the routes, then when I load the story view first (without loading the index view yet), then "posts" doesn't return anything.

App.StoryController = Ember.ObjectController.extend({
    needs: "stories", 
    previousPost: function() {
        return this.advancePost(1);
    },
    nextPost: function() {
        return this.advancePost(-1);
    },
    advancePost: function(delta) {
        var index, length, posts;
        posts = this.get('controllers.stories');
        length = posts.get('length');
        index = (posts.indexOf(this.get('content')) + delta + length) % length;
        if (index >= 0 && index < length) {
            return this.transitionToRoute('story', posts.objectAt(index));
        }

    }
});

Thanks in advance.

1
You said it, they shouldn't be nested. What do you mean by limits the design? You get the same result without nesting them, only without the errors. Also you wouldn't waste an App.Store.find() request that you don't need if you remove the nesting.Teddy Zeenny
Hi Teddy, just edited my original post to show you why I'm nesting the routes. Please do let me know if the same can be achieved without nesting.bugsinamber

1 Answers

2
votes

Your routes should be nested according to your UI. stories and story template are not nested, so just do:

App.Router.map(function() {
  this.resource("stories");
  this.resource("story", { path: ':story_id' }); 
});

If you want the story URL to include stories, you can do:

  this.resource("story", { path: 'stories/:story_id' }); 

Next, you want to access all the stories in App.StoryController. That does not mean that it needs to be nested inside the stories resource, or that you need to use App.StoriesController.

You want to access the data, so get the data and set it in App.StoryController:

App.StoryRoute = Ember.Route.extend({
  setupController: function(controller, model) {
    controller.setProperties({
      model: model,
      stories: App.Story.find()
    });
  },
  model: function(params) {
    return App.Story.find(params.story_id);
  }
});

And keep the App.StoriesRoute route the same, as a separate route, that is not related to App.StoryRoute.

App.StoriesRoute = Ember.Route.extend({
  model: function() {
    return App.Story.find();   
  }
});