Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Promise models and transitioning with back/forward buttons #3087

Closed
gpoitch opened this issue Aug 2, 2013 · 11 comments
Closed

Promise models and transitioning with back/forward buttons #3087

gpoitch opened this issue Aug 2, 2013 · 11 comments

Comments

@gpoitch
Copy link
Contributor

gpoitch commented Aug 2, 2013

Scenario: A route's model hook returns a promise. You go to transition into it via the browser's back or forward buttons.

Bug/jank: While that route is resolving, the currently visible route's scroll position jumps to the last position of said route that is about to be resolved.

It seems like it could be an issue with the router's timing fighting the built in browser behavior. I verified on the latest Chrome and Firefox with both hash and history locations.

I've reduced it to a simple case: http://jsbin.com/elelef/4
To reproduce: navigate into 'Other Route', then scroll down half way, then hit the back button.

@machty
Copy link
Contributor

machty commented Aug 3, 2013

I'm pretty certain this is is reproducible with any JS framework, and there's not really going to be a good solution to it, but I'll let others contradict me. It's just browsers bein browsers.

@raytiley
Copy link
Contributor

raytiley commented Aug 3, 2013

The only way I've seen to handle this is how discourse does it. As you scroll down it adds info to the url so that when you leave the page your back button takes you to where you were in the list. Useful for linking too.

@machty
Copy link
Contributor

machty commented Aug 3, 2013

@raytiley I don't think that's quite related to what @gdub22 is pointing out; I think he's pointing out that there's a default scroll location that the browser automatically goes to whenever you press the back button, which isn't always desirable depending on the transition you're trying to make. You might be able to put in some logic to scroll back to a certain location to override the default behavior, but this is going to be very app specific and not something that Ember should really have a hand in as a framework.

@gdub22 Often folk don't run into this situation because they've cached the previously fetched models and thus any promises resolve immediately. Here's an example where the scroll is avoided because when you click the back button it just uses the cached value. But this isn't really an Ember bug, but just the nature of browsers, and should be handled in an app specific way.

@machty machty closed this as completed Aug 3, 2013
@gpoitch
Copy link
Contributor Author

gpoitch commented Aug 3, 2013

@machty This indeed seems to be just the way the browser acts and returning a cached model will immediately transition.

I'm seeking something on the Transition class has some more info about how the route was entered (linkTo, direct, popstate, etc). Then one could simply return the cached modelFor that route or re-fetch appropriately. Probably better discussed elsewhere. Thanks for your feedback.

@stefanpenner
Copy link
Member

@gdub22 so you want to "invalidate" the cache based on referrer being linkTo, url back or popstate?

@gpoitch
Copy link
Contributor Author

gpoitch commented Aug 3, 2013

@stefanpenner I would invalidate the cache on linkTo (any explicit user action to enter). I would use the cached model on browser forward or back (both popstate). This would then mimic the user experience of a regular http page. I want to avoid building a complex cache map, and I have a feeling there is some info in the router I can tap into.

@gpoitch
Copy link
Contributor Author

gpoitch commented Aug 3, 2013

This seems to be detecting entering via back/forward, although those checks on transition don't feel safe:

model: function(params, transition) {
    if(transition && transition.sequence > 1 && transition.hasOwnProperty('urlMethod')) {
      // Entered via back or forward
      return this.modelFor(this.routeName);
    }
    else {
      // Fetch model
    }
}

@stefanpenner
Copy link
Member

not saying this is good or bad, it feels like we are walking down the path of implementing http caching semantics but at our routing layer.

@gpoitch
Copy link
Contributor Author

gpoitch commented Aug 3, 2013

At least providing some more info about how the Transition was triggered, leaves it up to the implementation, caching being a strong use case.

@gpoitch
Copy link
Contributor Author

gpoitch commented Aug 4, 2013

Got something working:
http://jsbin.com/elelef/12

If navigating to a route via back/forward buttons, the model resolves with the cached data and the browser's built in scroll position restoration works.

If clicking a link to a route, it will re-fetch from the server and return the page to the top.

@msalahz
Copy link

msalahz commented Jun 14, 2016

@gdub22 is there a way to apply your suggestion without having to update all my app routes ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants