Upcoming Async Router API

“what would be the way of going to the first item of a collection when the collection has been resolved?”

Isn’t that what I’m doing? If model returned a promise, then afterModel gets called with the resolved value of that promise. So in my example, posts is resolved so you can check its length. posts view would not be rendered until until after all destination routes’ models resolved.

1 Like

Yes, but I (probably mistakenly) understand that calling transitionTo will just abort the current transition, so I believe that the posts would not be rendered.
Now if I better understand, in this example posts view will be rendered when all the post.show models hooks are resolved. Is that right ?

Calling transitionTo will immediately abort the current transition, like you thought.

You are correct; posts view will not be rendered during the failed transition attempt, but will render when you get to post.show.

@machty in the last example (“Advanced”), list item 2, what’s the difference between using transition.halt() vs transition.abort()? Thanks.

That should say .abort(). I’ve updated the gist. Thanks for pointing it out!

So it’s great, I really think all your work is very consistent :slight_smile:

OK! I’m ready to merge this thing.

https://github.com/emberjs/ember.js/pull/2740

Also, how cool is this pattern?

App.ArticlesRoute = Ember.Route.extend({
  beforeModel: function() {
    if (!App.Article) {
      return $.getScript('/models/article.js');
    }
  }
});

Even if we end up opting for a more container-based way of doing stuff, this seems pretty rad.

3 Likes

Awesome. I don’t personally have the need for loading partial applications, but that is incredibly powerful. Thanks a lot for all your work on this @machty. This is gonna clean up a lot of ugly code.

We have a liftoff <3 <3 <3

Thanks everyone for your help!

5 Likes

Awesome, props to @machty for the legendary effort on this! :rocket: :rocket: :rocket:

Great work @machty. I like the beforeModel hook especially as I just had to implement the authentication scenario with redirect hacks

Here’s the embercast that makes heavy use of this http://www.embercasts.com/episodes/client-side-authentication-part-2

What happens to the serialize and deserialize hooks under the new regime?

Currently I might have something like this in a route:

App.FilterRoute = Em.Route.extend
  setupController: (controller, model) ->
    controller = @controllerFor('addressbook')
    addressbookController.set 'searchText', ''
    Ember.run.next =>
      addressbookController.set('model.selectedFilter', model)

  serialize: (filter) ->
    filter: filter

  deserialize: (params) ->
    params.filter

How would this look in the new router?

@dagda1 There is no deserialize hook anymore (deserialize has been private API for a while). You should change deserialize to model and it should work. Not sure what you’re doing with run.next but maybe it’s necessary for some reason.

deserialize previously translated a url into the route arguments, which you need when you are entering the app at a specific url.

Are you saying this now happens in model?

In the last 5-6 months or so, the public API has been to use model. deserialize has been private for a while. But yeah, model gets the same url params and behaves the same way. It also gets a new transition parameter:

model: function(params, transition) {
  return Thing.find(params.id);
}

What about the issue of having to duplicate model query code? What I mean is you have your code in the model hook, but if you want to do a transitionToRoute, then you have to implement that same query either in your controller, router event, or possible a view. This seems horribly unintuitive, since you should be able to pass in the params to transitionToRoute, and that should hit the model hook with the passed in params.

model: function (params) {
  return App.User.find({ type: params.type});
}

Now a transition:

var userType = "admin",
  admins = App.User.find({ type: userType });

this.transitionToRoute("admins", admins);

Now this works because you’ve overridden the serialize hook and it returns { type: "admin" }, which is fed into the URL, and the model passed through (bypassing the model hook).


Now that’s a simple example with Ember-Data, but what if it was a Ember.$.ajax with Ember.RSVP.Promise example, and the params had to be transformed for the query?

I propose being able to pass in the params object, and hitting the model hook when using transitionToRoute. Maybe I’m doing something wrong :smile:

@knownasilya I believe this change has already been added to master, assuming we’re talking about the same thing. It doesn’t work quite the way you’re suggesting though, since there’s no great way to distinguish between a params object and a context object that you actually want to have used as the model, but linkTo and transitionTo (and therefore transitionToRoute) now work such that if you pass in a number or string as the context, it constructs a params object that will 1) be passed to the model hook and 2) be used to serialize the href for a linkTo.

So this solves the problems of 1) duplicated model logic (you can now just let model always do all the model loading logic rather than needing a model reference ahead of time to use for linkTo or transitionTo) and 2) needing a model to generate an href.

Furthermore linkTo params are now bound, so you can do {{linkTo someRoute}} and someRoute will be looked on up the template context (most likely the controller). Details here: https://github.com/emberjs/ember.js/pull/2942

1 Like

So this will really help with a few areas that we’ve been adding black magic to work, but it seems like it’d be really convenient to have a callback to didTransition on the route to know when a transition has occurred (maybe it came from the url and not from me programmatically calling transitionTo.

App.ArticlesRoute = Ember.Route.extend({
  didTransition: function(controller, model){
       // Do things every time a transition has occurred into this route
   }
 });

I guess I could just manually hook into it from the willTransition, do some

App.ArticlesRoute = Ember.Route.extend({
  willTransition: function(transition){
       transition.then({
          // Fake didTransition
       });
   }
 });

That is exactly what I was referring to! :smile: That’s great news, thanks @machty!