Loading substates: A simple search scenario


#1

I’m trying figure out a good pattern to follow when setting up loading substates.

A lot of the time I’m running into situations where a user decides to go to a new route and I want to take them there immediately. I don’t want my template rendering to be delayed until all of the model hook promises have been resolved. I’d rather bring users to the page that they want to see and have the page populated with data as it comes in.

I thought this was something that I could accomplish by taking advantage of loading substates but I’m not quite sure how to set this up to get the intended effect.

A simple search scenario

SearchIndex route

The SearchIndex template here is the one with the darker gray background. The search results are coming from the model hook in the SearchIndexRoute. The search input is updating the value of a queryParam defined on the SearchIndexController that is set to refresh the model hook in the route whenever it changes.

Search when loading

While the SearchIndexRoute's model hook’s data is loading, the search/loading.hbs template fills the outlet in the search.hbs template.

What I want Search to look like when loading

The problem is that I want the user to immediately be presented with the search input when they decide to transition to this route. Further, when they decide to enter a search query into the input, the search input should stay present while the model hook is being refreshed.

https://dl.dropboxusercontent.com/u/10547667/JS_Bin_-_Collaborative_JavaScript_Debugging.png

JS Bin of the Situation


#2

I don’t believe you can use the built-in loading substate for this. I’ve solved this with an additional state flag, like this:

Also, depending on your user interface requirements, you might prefer to bind the loading state to a class instead of a replacement template, like this: http://jsbin.com/sociwozewo/2/edit


#3

Thanks @tcjr. Those solutions can be used to get around waiting for the model promises to resolve after the initial transition but they don’t solve the problem when the user first navigates to the page. I’d like for the UI around the results to be presented immediately, eventually loading the results when the model promises resolve.


#4

@HeroicEric I am running into the same situation here.

I am trying to solve it in the following way but there’s a bunch of edge cases which are making it difficult:

  • Parent route containing only the search bar, and an outlet. This route has a “search” query parameter which will refresh the model on change, but the route doesn’t have a model
  • Child “loading” route with just a loading indicator
  • Child “results” route, shares the parent’s controller in order to have access to the “search” query parameter.

#5

@mdentremont You might want to check out https://github.com/danmcclain/ember-deferred-content, which really simplifies cases like this.