EmberJS redirect when no subroute specified

339 views Asked by At

I have a set of nested routes and templates that I'd like to auto-select the first model if no sub-routes are specified. The route structure is:

App.Router.map(function() {
  this.route('sales', function () {
    this.route('orders', function () {
      this.route('order', { path: ':order_id' });
    });  
  });
});

If the user hits sales.orders then they should be redirected to the first order on the sales.orders model. Making this work is no problem. The issue comes when the user hits sales/orders/:order_id No matter what :order_id is the user is always redirected to the first order in the orders array.

I'm currently performing the redirect in the setupControllerhook of the SalesOrders route as I have some sorting on the controller that needs to be in place prior to redirecting.

App.SalesOrdersRoute = Ember.Route.extend({
  model: function () {
    return this.store.find('order');
  },

  setupController: function (controller, model) {
    controller.set('model', model);
    var firstObject = controller.get('sortedContent').get('firstObject');
    this.transitionTo('sales.orders.order', firstObject);
  }
});

App.SalesOrdersController = Ember.ArrayController.extend({
  sortProperties: ['orderNumber:desc'],
  sortedContent: Ember.computed.sort('model', 'sortProperties')
});

I have a jsbin that shows my issue.

Hitting any specific order will always redirect to the first order in the array (4 in this case).

I need it to keep the deep linked url and only redirect when no order is specified.

I feel like this question and this question are both similar to what I'm trying to do except neither addresses auto-selecting the first item if no sub-routes are specified.

2

There are 2 answers

1
Bavo Van Geit On BEST ANSWER

You should do the redirect in your SalesOrdersIndex route. The additional index route of each route will only be created when it matches the complete URL mapping. So for any url that isn't exactly "sales/orders" it will not be created. Just what you want.

App.SalesOrdersIndexRoute = Ember.Route.extend({
  setupController: function (controller, model) {
    controller.set('model', model);
    this.controllerFor('salesOrders').set('model',model);
   var firstObject = this.controllerFor('salesOrders').get('sortedContent').get('firstObject');
    this.transitionTo('sales.orders.order', firstObject);
  }  
}); 

jsbin: 4 3 2 1 redirect to 4

0
swastik On

One option could be to check the transition on the afterModel hook and redirect if the user is trying to access the sales.orders.index route.

Something like this:

afterModel: function(model, transition){
  if (transition.targetName === "sales.orders.index"){
    var first = model.objectAt(0);
    this.transitionTo('sales.orders.order', first);
  }
}

Here's an example.

That won't work with setupController as the setupController hook does not have access to the transition. In your case, since you just want to sort, you could do something like:

var first = model.sortBy('orderNumber').reverse().objectAt(0);

As far as I know, setupController is called after both redirect and afterModel so I'm not sure it's possible to get the sorted content from the controller through the afterModel and redirect hooks.