Transitioning when encountering an error in Ember - ember.js

I am trying to do this.transitionTo('route name') in the ApplicationRoute error action.
What seems to happen is when I click on the link, it hits the error, and doesn't transition to the target route, it seems to say it's transitioning to the route it was just in again. This is using {{#link-to}} so I have a feeling there is some magic going on in there...
I am trying to use this example.
The error is happening in the model() method on the route (which is using jquery and returning a promise [jqXHR]) because I am returning a 401 http code.
Is this not correct?
App.ApplicationRoute = Ember.Route.extend(
actions:
error: (error, transition) ->
if error.status == 401
#transitionTo('login')
)
Another thing I've tried is setting the .ajaxError method and transitioning in there but the result seems to not transition either.
App.ApplicationRoute = Ember.Route.extend(
setupController: (controller, model) ->
route = #
Ember.$(document).ajaxError((event, jqXHR, ajaxSettings, error) ->
if jqXHR.status == 401
route.transitionTo('login')
)
controller.set('content', model)
)
Has anyone got this working on ember 1.2.0?

Try returning true in your error hook, to bubble the error event.
From the documentation (http://emberjs.com/guides/routing/asynchronous-routing/#toc_when-promises-reject):
actions: {
error: function(reason) {
alert(reason); // "FAIL"
// Can transition to another route here, e.g.
// this.transitionTo('index');
// Uncomment the line below to bubble this error event:
// return true;
}
}

Turns out it was an issue on my end. I had some extra logic that was essentially countering my transition! Whoops!

Related

Query-params-new nested routes strange error

In an application I use the latest canary versions for Ember and Ember Data. I have the following router:
this.resource('articles', {path: '/articles'}, function() {
this.resource('article', {path: '/:article_id'});
});
In the ArticlesController I specify some queryParams:
queryParams: ['category', 'search'],
category: '1', // defaults to 1
searchTerm: "",
In my ArticlesRoute I specify a model refresh and the model:
queryParams: {
category: {
refreshModel: true
}
},
model: function(params) {
// here I do use the params to return articles based on category and/or searchTerm
}
So far so good, all code above works perfect. However when I do a this.transitionTo('article', articleObject) or this.transitionToRoute('article', articleObject) in my application I get the following error:
Error: You didn't provide enough string/numeric parameters to satisfy all of the dynamic segments for route article
at Object.__exports__.default.subclass.createParamHandlerInfo (http://localhost:8000/vendor/ember/index.js:44242:21)
at Object.__exports__.default.subclass.applyToHandlers (http://localhost:8000/vendor/ember/index.js:44121:37)
at Object.__exports__.default.subclass.applyToState (http://localhost:8000/vendor/ember/index.js:44088:21)
at Object.Router.transitionByIntent (http://localhost:8000/vendor/ember/index.js:43312:33)
at Object.Router.refresh (http://localhost:8000/vendor/ember/index.js:43459:21)
at EmberObject.extend.refresh (http://localhost:8000/vendor/ember/index.js:22616:35)
at EmberObject.extend._actions.queryParamsDidChange (http://localhost:8000/vendor/ember/index.js:22328:22)
at Object.triggerEvent (http://localhost:8000/vendor/ember/index.js:24563:38)
at trigger (http://localhost:8000/vendor/ember/index.js:44812:16)
at fireQueryParamDidChange (http://localhost:8000/vendor/ember/index.js:43612:9) index.js:14220
Uncaught Error: Assertion Failed: Error: You didn't provide enough string/numeric parameters to satisfy all of the dynamic segments for route article index.js:3658
This strange error only happens when I first clicked a Category so the queryParam category is changed, and then fire a transitionTo to an article.
I have tried to use the debugger; statement to get the source of the error. However it seems that is an event that calls this error. When searching the sourcecode I found that the error originates from line 44242 of ember.js.
Does anyone know why this error happen after I have transitioned to a non query-params-new route?
Edit: now in Github too: https://github.com/emberjs/ember.js/issues/5070 (comment on Github)
JSBin: http://emberjs.jsbin.com/yiquyupa
I ran into almost the same issue in an afterModel callback where the parent route/controller has queryParams.
I found that if you just pass the queryParams from the transition argument (not the queryParams argument which is null/undefined) into Route.transitionTo / Route.replaceWith then the transition completes.
Example:
afterModel: function(model, transition, queryParams) {
// FIXME: unresolved Ember issue https://github.com/emberjs/ember.js/issues/5070
this.replaceWith('another.route', model, { queryParams: transition.queryParams});
}
I don't know why this happens, but queryParams is still a relatively new feature and still has some rough edges.

EmberJS 404 Error Handling

I'm dealing with error handling with EmberJS. Now I can handle my errors like this:
App.MediaShowRoute = Ember.Route.extend
...
actions:
error: ()->
#transitionTo '404'
But it is just a temporary decision. What I want to do now, is to render the '404' template within that route, where I get 404 error. For example, if I go to
/media/111111
route and i get an 404 error, I don't want to transition to the 404 page, I want to stay on the same page, but render the 404 template in it. I tried it this way:
actions:
error: () ->
#render '404',
into: 'media.show'
but it is not working :) I will be grateful for your help :)
You'll probably want to look at the ErrorRoute and error template here.
It doesn't exactly handle error codes very well, but when you reject the promise from the model on your App.MediaShowRoute your error will become the content of the ErrorController... You can then check for it in your ErrorRoute#renderTemplate
App.ErrorRoute = Ember.Route.extend({
'renderTemplate' : function() {
switch (this.get('controller.content.code')) {
case 404 : return this.render('404');
default : return this.render();
}
}
});
Take a look at my blog post for a more in depth example of how you might pass the error code around: http://www.riverrockapps.com/post/improving-error-route-in-emberjs

How to manually invoke a route in ember.js RC1

I have the following controller and I'd like to bubble up an event using send
App.PersonController = Ember.ObjectController.extend({
page: function(page) {
var model = PersonApp.Page.create({id: page});
this.send("person.page", model); //should bubble up ...
}
});
here is my route setup
PersonApp.Router.map(function(match) {
this.resource("person", { path: "/" }, function() {
this.route("page", { path: "/page/:page_id" });
});
});
here is the simple page model (shim basically)
PersonApp.Page = Ember.Object.extend({
});
although I'm using the route "person.page" and I'm passing a valid model I get the following error (seemingly the router does not have this route?)
Uncaught Error: Nothing handled the event 'person.page'.
If it helps debug the controller / router relationship I noticed inside my controller if I dump this.get('target') ...
_debugContainerKey: "router:main"
and if I dig further ... and print this
this.get('target').get('router')
I see a router w/ my route under the currentHandlerInfos array ... not sure if I should be this deep though
... another slight update
If I do this (full blown) it seems to modify the window.location but my model/setupController hooks on the route are never hit
this.get('target').get('router').transitionTo(route, model);
I think, send is just used for events of a route. Assuming your controller would call send like this:
//in the controller
this.send("personPage", model);
// a matching Route
App.PersonRoute = Ember.Route.extend({
events : {
personPage : function(page){
// this should be called
}
}
});
For your case you need to leverage transitionTo (your access on the router property was too much, i think. The router instance of Ember.Router has again a router property. Pretty confusing :-)).
this.get("target").transitionTo("person.page", model);

Correct clean up code

I have the following two routes for edit and new:
WZ.ExercisesNewRoute = Em.Route.extend
model: ->
WZ.Exercise.createRecord()
deactivate: ->
#_super.apply this, arguments
#get('currentModel.transaction').rollback()
WZ.ExercisesEditRoute = Em.Route.extend
model: (params) ->
WZ.Exercise.find(params.exercise_id)
serialize: (params, options) ->
exercise_id: params.get('id')
deactivate: ->
#_super.apply this, arguments
tx = #get('currentModel.transaction')
tx.rollback() if tx
I would like to know what the correct code should be in each deactivate so the store is in a correct state if the user does not save, does save or whatever.
Currently if I route to the edit route and then directly to the new route without saving, I get the following error:
Uncaught Error: Attempted to handle event willSetProperty on
while in state rootState.deleted.saved.
Called with {reference: [object Object], store: ,
name: name}
This question is for an older version of ember data, but answer would have been to first check the state for isDeleted and only rollback if the record is not already deleted.
In the newer ember data there is no concept of a transaction, but you can still run into a similar issue if you are trying to rollback a record that is not yet persisted.
I would probably do this in the routers willTransition event as you can do things like abort the transition if you want to give the user the option to save the changes.
willTransition: function(transition) {
controller = this.get('controller')
if( controller.get('content.isDirty') ) {
if( controller.get('content.isNew') && confirm('Closing this window will revert all unsaved changes.') ){
controller.get('content').deleteRecord();
} else {
controller.get('content').rollback()
}
}
}

Attempted to register a view with an id already in use

Since this commit we can't registrer a view with an ID twice. This seems logical. However I got an issue.
Router
App.Router.map(function() {
this.resource('contact', { path: '/contacts/:contact_id' });
});
App.ContactShowRoute = Ember.Route.extend({});
View
App.ContactShowView = Em.View.extend({
elementId: "page-show-contact"
});
Consider that I'm already on the route App.ContactShowRoute. I would like to transitionTo() the same route but with a different context.
I expected emberjs to destroy the view and then create it again, but I got the following error:
Uncaught Error: assertion failed: Attempted to register a view with an id already in use: page-show-contact
I don't want to instantiate a view with the same ID twice. I just want ember to destroy the actual one and then create a new one.
It seems to be a bug in the current version. Maybe you should open a ticket.
Until this is fixed, this might help:
App.ContactShowRoute = Ember.Route.extend({
renderTemplate : function(controller, model) {
if(this.lastRenderedTemplate == this.routeName)
return;
return this._super();
}
});