These are the things that I don't believe is totally consistent and things I think might give problems in different situations. We don't have to solve them all, but make sure that we don't get ourselves into something that's going to be hard to solve.
.dispatch
(or.perform
,.resend
or whatever we're gonna call it) needs to be supported in a consistent way.- Retrying with previously rejected promises.
- Should contain the full target route path. It doesn't matter where it came from.
- Does
TransitionEvent
replicate itself, or does it have anEventDescriptor
that can be reused? Important thing is that we don't reuse the sameTransitionEvent
instance, as this will mean trouble regardingisAborted
and resolved contexts. - How do you put extra state on a
TransitionEvent
that must survive after calling.dispatch
? Do you just add properties to it, or should it have adata
property that you need to add properties about the transition to (e.g.transitionEvent.data.startTime = new Date()
.
- There should only be one
activeTransitionEvent
on the router.TransitionEvent
should have anisAborted
boolean property that hooks with multiple async steps can use to check if they should continue or not. When a new transition is started (.transitionTo
,{{linkTo}}
or.dispatch
), the previous one is aborted and the new one becomes theactiveTransitionEvent
. - Consistent return values from
router.modelFor
. We talked about deprecatingrouter.modelFor
, and create a new method onTransitionEvent
also calledmodelFor
, that returns the model for a given route name as it would be if/when the transition is finished. If you want the current model you're probably either in a controller, and should useneeds
, or you can usethis.controllerFor('user').get('model')
. A model is not active until it's on the controller. - What's the point of
routeTo
? Why don't we just havetransitionTo
, and it always bubbles anwillExit
event on all current routes? Then a.dispatch
is always simply a newtransitionTo
called on the current route, no matter where we are at that point. - Should calling
.perform
onTransitionEvent
from within arouteTo
really stop the bubbling? Why would a child route want to prevent its parent from doing its work?
I can't think of a good way to support retrying transitions with supplied contexts that are promises. There isn't a generic way to reload the data. Unless...
Let the transitionTo
method accept "functions that returns promises" as context. Then every time a TransitionEvent
is fired, that function is fired and returns a fresh promise that hasn't been resolved yet. It works kinda like Alex' Lazy Perserverant Promises, but doesn't set any demands for the promises themselves (they can be jqXHR
, RSVP.Promise
etc.). So, if a developer needs to be able to retry TransitionEvents
with promises that can be rejected, he needs to do like this:
App.SomeController = Ember.Controller.extend({
username: '', //Bound to a textfield in the template
didClickButton: function() {
var username = this.get('username');
this.transitionTo('user', function() {
return $.get('/users/'+username);
});
}
});
Let's say that the AJAX call returns with a 401 Unauthorized
status code since the user's session has timed out. Then the jqXHR
will be rejected. This will trigger an error (WHERE?). The error handler can then store the TransitionEvent
in a transitionToPerformOnceLoggedIn
property. Once the user has logged in, we call .perform()
on the transitionToPerformOnceLoggedIn
, which will once again send the GET request to /users/:username
.
In cases where you know that the value has already been resolved, you don't need to incapsulate it in a function. This will work fine in all cases:
App.RepoController = Ember.Controller.extend({
needs: ['user'],
goToRepoOwner: function() {
this.transitionTo('user', this.get('controllers.user.model'));
}
});
So this is not changing any old functionality. It's just a new option to use, which is necessary for repeated async lookups.
The only unknown I have here is: Who handles the error
event? Is it an event that bubbles up from the current route. This probably makes the most sense, since you would probably have an error
event handler in your App.ApplicationRoute
that checks for 401 requests. Or is it called on the target route? How does it work in the code you've made so far?