Avoiding Reload on Transition Back to Listing Route From Details Route


#1

Given a site with a listing route and a details route where a user navigates from the listing route to the details route and then back to the listing route, what is the preferred way to maintain the state of the listing route when you navigate back into it?

I currently have something along the lines of :

this.route('posts');
this.route('post', {
	path: '/posts/:post_id'
});

But given that they are not nested the app does a full transition navigating between the routes and reloads the listing page. I’d like to avoid reloading the listing but I can’t nest the routes / UI due to design requirements.

Any ideas?


#2

Assuming what you mean by “keeping the state” as just the data that’s been loaded, you can still achieve this with nested routes. All routes provide you with an additional “secret” index route. So you’re router.js could look like:

this.route('posts', function(){
   this.route('post', { path: '/:post_id' });
});

Because of that, you can achieve what you looking to do with the following structure. Below, I’m using the pods layout here because it’s easier to illustrate the point, but hopefully it will translate:

- posts/
   - route.js - Load all of models for the list here
   - controller.js - Keep your state here (like filters/sort)
   - template.hbs - Keep this as just an {{outlet}} and whatever 
                    UI you want for both views
   - index/
      - route.js
      - controller.js 
      - template.hbs - All you UI for the list goes here. It will have 
                       access to the whatever is in the parent controller scope
   - post/
      - route.js - Any additional data loading for just the post, 
                   You can `peekRecord` in the store to get the post 
                   without a network request
      - controller.js  
      - template.hbs - Your post specific UI. This will replace the 
                       list UI in index/template.hbs

This is how I would approach it. There may be other ways to go about this, so maybe someone else will chime in. I hope this helps!


#3

Hey, thanks for the response!

Correct me if I’m wrong but would that route structure not necessitate loading all of the data for the posts route when hitting the post route directly? Unless I put the model for the posts route somewhere other than the model hook but I don’t think that’s what you’re suggesting.


#4

Yeah, that’s a good point. That setup would require the loading of all of the posts, even if you’re going directly to the individual post route. If that’s a deal breaker, then things get more complicated. I suppose the thing you’re looking to avoid is a refetching of all the posts each time you go to the list? If you’re doing a store.query for the list, there really isn’t a mechanism for backgrounding or using the local copy like there is for store.findAll.

One option is to:

  1. In your route for the index, do a store.peekAll for you posts
  2. Make sure your posts list has a good empty/loading state
  3. Also in the index route, in setupController(which will not block the page loading), do your store.query for the posts
  4. When the query resolves, the store will be populated and the peekAll will get the posts and rerender the list

Then, when you navigate to your post, you’ll have it. When you come back to the posts list, the posts will still be in the store and it will render right away.

I’m sure there are more edge cases I’m missing here, but hopefully it stirs some ideas for you.


#5

That seems like a good starting point. I’ll give it some thought. Thank you. :slight_smile: