17

I'd like an Ember path /clinic/1 to automatically redirect to show the first doctor: /clinic/1/doctor/1.

Each clinic has many doctors.

Unfortunately if I use this code:

var doctor = clinicController.get('content.doctors.firstObject');
router.transitionTo('clinic.doctor.index', doctor);

... it does not work, as content.doctors.length is still 0 when this code runs in app_router.js.

Any ideas?

Chris Nolet
  • 8,714
  • 7
  • 67
  • 92
  • What version of ember do you use ? I think this code is before the new routing. Anyway, could make a jsfiddle or jsbin showing the example ? – sly7_7 Jan 13 '13 at 17:14

4 Answers4

24

You should be able to do this:

App.DoctorsRoute = Ember.Route.extend({
  model: function() {
    return App.Doctor.find();
  },

  redirect: function() {
    var doctor = this.modelFor('doctors').get('firstObject');
    this.transitionToRoute('doctor', doctor);
  }
});

This will work because:

  • If the model hook returns an object that hasn't loaded yet, the rest of the hooks won't run until the model is fully loaded.
  • If the redirect hook transitions to another route, the rest of the hooks won't run.

Note that as of 2426cb9, you can leave off the implicit .index when transitioning.

Kingpin2k
  • 47,277
  • 10
  • 78
  • 96
Yehuda Katz
  • 28,535
  • 12
  • 89
  • 91
  • Is this still suppose to work with ember 1.0.0rc2? I'm always getting `this.modelFor('doctors').get('length')` at 0. – Sébastien Grosjean - ZenCocoon Apr 18 '13 at 23:02
  • 1
    I'm trying this approach but it doesn't seem to work on the initial load. I believe this is because the data has not loaded yet. However, If I navigate away and come back, then it will work since at that time, the data HAS loaded. any advice @Yahuda? – Ben Apr 29 '13 at 03:46
  • 1
    Also have problem that data has not loaded, when try this.modelFor. However when try console.log(this.modelFor('categories').get('isLoaded')); Returns me true, but content.length 0. – polianych Apr 30 '13 at 12:52
  • 1
    Was banging my head on this for ages and could absolutely not get it to work. I had child views rendering in the wrong parent or issues with my model not loaded. NOW I get why: https://github.com/emberjs/ember.js/issues/2116 and especially https://github.com/emberjs/ember.js/issues/1642 cover the problem. Sounds like the workaround I am going to try will not involve Ember Data, as Ember Data apparently always returns promises –  May 01 '13 at 17:26
  • @MattSchweers: I was banging my head as well for a couple days. Did you find any workaround? – Paulo Scardine May 13 '13 at 17:22
  • @PauloScardine I wish I could say I had but after I posted that comment, I have not had a chance to revisit my code. I am watching the GitHub issues I mentioned and there has been no progress on those items, so the the only real answer on my end will be ripping out Ember Data and rewriting my view/routing logic, which has not happened yet. Will update if I get a working solution in place –  May 14 '13 at 20:35
  • Also, how can I make it redirect only when no doctor route is selected (no id is passed in from url)? – wen Jun 12 '13 at 18:12
  • 2
    So is this not working anymore? When I try this I get an error in my console saying `Uncaught TypeError: Cannot call method 'get' of undefined`. For some reason `this.modelFor('doctors')` is returning undefined. It seems like the redirect hook is getting called before the model has finished loading. – Ryan Jul 03 '13 at 22:49
2

Redirecting on the Route doesn't work for me in my ember-data based app as the data isn't loaded at the point of redirection, but this does work for me...

In the roles controller I transition to the role route for the firstObject loaded.

Application.RolesController = Ember.ArrayController.extend({

    selectFirstObject: function () {
        if (this.get('content').get('isLoaded')) {
            var role = this.get('firstObject');
            this.transitionToRoute('role', role);
        }
    }.observes('content.isLoaded')

});

HTH, gerry

1

As an update, if you don't want to redirect because you have a nested route, you'll want to use conditional redirect based on the intended route.

redirect has two arguments passed to it, the model and the transition object. The transition has the property targetName where you can conditionally redirect based on its value.

redirect: function(model, transition){
  if(transition.targetName ==='doctors.index'){
    this.transitionTo('doctor', model.get('firstObject'));
  }
}
Kingpin2k
  • 47,277
  • 10
  • 78
  • 96
1

For EmberCLI users, you'd achieve the same by doing the following:

//app/routes/clinics/show.js
import Ember from 'ember';

export default Ember.Route.extend({
  redirect: function(model) {
    var firstDoctor = model.get('doctors.firstObject');
    this.transitionTo('doctor', firstDoctor);
  }
});
Constant Meiring
  • 3,285
  • 3
  • 40
  • 52