Question

I've recently been porting a number of Ember apps I maintain to RC 8 and ran into this.

Before the router facelift landed I would sometimes manage control flow via promises returned by Ember Data find calls.

For example:

SomeRoute = Ember.Route.extend({
  model: function(params) {
    var resolve = function(model) { return model; };
    var route   = this;
    var reject  = function() { this.transitionTo('someOtherRoute'); };
    return SomeModel.find(params.some_model_id).then(resolve, reject);
  }
  ...
});

With the recent changes, it is now possible to handle errors created in model callbacks via the error action:

SomeRoute = Ember.Route.extend({
  // note: model callback no longer needed--default suffices
  actions: {
    error: function(reason, transition) {
      // check the reason object to determine how/if to handle this error
      this.transitionTo('someOtherRoute');
    }
  }
  ...
});

I much prefer the latter approach as it makes the code easier to read and better separates concerns.

This works well in most cases but I encountered an issue in an app that uses nested routes. I've included a simplified example followed by a jsbin that demonstrates the issue.

Lets say we want to show Articles that belong to Authors and the URLs look like: /authors/:author_slug/articles/:article_slug. We want to redirect to a Not Found page when someone tries to view an article that doesn't exist.

When managing control flow in the model callback as above, you can browse to /authors/some_author/articles/some_invalid_slug and be redirected to /authors/some_author/articles/not_found as expected.

However, if the redirect to the Not Found page is instead managed via the error action, the parent context is lost at some point and you end up at /authors/undefined/articles/not_found.

You can see this in the following jsbins:

http://jsbin.com/eJOXifo/1#/authors/schneier/articles/12345 (redirects to http://jsbin.com/eJOXifo/1#/authors/schneier/articles/not_found)

http://jsbin.com/oNaWelo/1#/authors/schneier/articles/12345 (redirects to http://jsbin.com/oNaWelo/1#/authors/undefined/articles/not_found)

Does anyone know why this happens or how to avoid it?

Notes:

  • I know this doesn't have anything to do with Ember Data. However, implementing something equivalent without Ember Data just makes the example more complicated without adding anything
  • There are a few small hacks to make Ember Data work as expected in jsbin:
    • I'm preloading the parent model to avoid having to load it from anywhere.
    • I'm not doing anything special to provide data for the child model. The app just makes a request to http://jsbin.com/articles/12345. This actually returns a 200 but bombs anyway because the response is html. An API that correctly returns a 404 response gives the same behvaiour.
    • I remember a while ago reading about some service that could be used to build fake API responses for use with services like jsfiddle or jsbin. If anyone knows what it is please comment.
Était-ce utile?

La solution

Your right that the parent context is getting lost. The trick is to extract that context from the transition and pass it as an argument when calling transitionTo. So:

App.ArticlesArticleRoute = Em.Route.extend({
  actions: {
    error: function(reason, transition) {
      console.log('in error handler');
      this.transitionTo('articles.notFound', transition.resolvedModels.authors);
    }
  }
});

With this change, visiting the url:

http://jsbin.com/iVOYEvA/2#/authors/schneier/articles/my-fake-article

will redirect to:

http://jsbin.com/iVOYEvA/2#/authors/schneier/articles/not_found

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top