Ember - Automatically redirect to firstObject
Asked Answered
F

4

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?

Fume answered 13/1, 2013 at 16:6 Comment(1)
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 ?Insociable
H
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.

Hyperaesthesia answered 13/1, 2013 at 18:36 Comment(8)
Is this still suppose to work with ember 1.0.0rc2? I'm always getting this.modelFor('doctors').get('length') at 0.Ladner
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?Mckissick
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.Prognosis
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: github.com/emberjs/ember.js/issues/2116 and especially 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 promisesPetaliferous
@MattSchweers: I was banging my head as well for a couple days. Did you find any workaround?Elude
@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 placePetaliferous
Also, how can I make it redirect only when no doctor route is selected (no id is passed in from url)?Elbertine
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.Phipps
D
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

Diatomic answered 5/7, 2013 at 11:16 Comment(0)
E
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'));
  }
}
Eipper answered 21/3, 2014 at 23:39 Comment(0)
A
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);
  }
});
Acanthopterygian answered 29/8, 2015 at 14:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.