Search code examples
javascriptember.jsember-data

How to transition to a route from an Ember Data Adapter


In my application, I've got an ApplicationAdapter whose ajaxError method is customized. Within that method, I'd like to be able to transition to a given route. How can I do this?

App.ApplicationAdapter = DS.RESTAdapter.extend({
    ajaxError: function(jqXHR) {
        var error = this._super(jqXHR);
        if (jqXHR) {
            switch(jqXHR.status) {
            // [...]
            case 401:
                // How can I transitionTo('login') here?
            }
            // [...]
        }
    }
});

Solution

  • Instead of transition in the adapter, isn't a good pratice IMHO, you can return an instance of Error and handle it in the error action of the current route:

    App.UnauthorizedError // create a custom Error class
    
    App.ApplicationAdapter = DS.RESTAdapter.extend({
        ajaxError: function(jqXHR) {        
            var defaultAjaxError = this._super(jqXHR);
            if (jqXHR) {
                switch(jqXHR.status) {            
                    case 401:
                    return new App.UnauthorizedError()
                }
            }
            return defaultAjaxError;
        }
    });
    
    App.IndexRoute = Ember.Route.extend({
      model: function() {
          return this.store.find('person');
      },
      actions: {
          error: function(reason) {
              // all errors will be propagated to here, we check the instance to handle the UnauthorizedError          
              if (reason instanceof App.UnauthorizedError) {
                  this.transitionTo('login')
              }
          }
      }  
    });
    

    If you want to use this for all routes, you can put the unauthorized transition in the ApplicationRoute. Because the ApplicationRoute is the parent of all routes, and not handled actions, or actions that return true, will bubble to the parent routes.

    App.ApplicationRoute = Ember.Route.extend({
        actions: {
          error: function(reason) {
              if (reason instanceof App.UnauthorizedError) {
                  this.transitionTo('login')
              }
          }
      }
    });
    
    App.BarRoute = Ember.Route.extend({
        actions: {
            error: function(reason) {
                // handle errors of bar route
    
                // bubble to application route
                return true;
            }
        }
    });
    

    This is a fiddle with this sample http://jsfiddle.net/SkCH5/