Search code examples
meteoriron-router

Iron Router waitOn not working when setting data on a route in Meteor 1.0.2


I'm defining a route that will show an appointment for a patient. I would like the template to show both the patient information and the appointment information.

I have this published:

Meteor.publish('userAppointment', function(appointmentId){
  check(appointmentId, String);
  var userId = Appointments.findOne(appointmentId).patientId;
  return [
    Appointments.find({_id: appointmentId}),
    Meteor.users.find({_id: userId}, {fields: {profile: true, emails: true}})
  ];
});

Unfortunately Iron Router doesn't seem to be successfully waiting on the data subscription to complete before it tries to set the data context.

Note where I put debugger:

Router.route('/admin/appointment/:id', {
  name: 'AppointmentShow',
  waitOn: function(){
    return [
      Meteor.subscribe("userAppointment", this.params.id)
    ]
  },
  data: function(){
    var appointmentId = this.params.id;
    debugger

    var patientId = Appointments.findOne(appointmentId).patientId;

    return {
      appointment: Appointments.findOne(appointmentId),
      patient: Meteor.users.findOne(patientId)
    }
  }
});

At the time when debugger stops the code, when I do Meteor.users.find().fetch() and Appointments.find().fetch() in the console only the currently logged-in user (me) is available and there are no appointments available.

I expect to see two users (me and the patient) and one appointment available because that's the data that should be available after the waitOn has finished subscribing.

Am I missing something here?

EDIT----- Still doesn't make sense to me ------

When I change my route to this:

Router.route('/admin/appointment/:id', {
  name: 'AppointmentShow',
  waitOn: function(){
    return [
      Meteor.subscribe("userAppointment", this.params.id)
    ]
  },
  data: function(){
    var appointmentId = this.params.id;
    return {
      appointment: Appointments.findOne(appointmentId),
      // patient: Meteor.users.findOne(Appointments.findOne(appointmentId).patientId)
    }
  }
});

Appointments.findOne(appointmentId) returns an object:

{
  _id: "23efref34qr2",
  reason: "coughing",
  patientId: "785g45g4f"
}

When my data function only returns

appointment: Appointments.findOne(appointmentId)

it works. But if I have it also return

patient: Meteor.users.findOne(Appointments.findOne(appointmentId).patientId)

I get an error message (can't read property 'patientId' of undefined.) Huh? It was just defined on the line above!


Solution

  • To clarify, I think you should be allowing your data function to run (and rerun when collections are populated), but be careful to make sure your function doesn't throw an error when it runs before data is available. This is a general Meteor pattern.

    data: function(){ 
      var appointmentId = this.params.id,
            appointment = Appointments.findOne(appointmentId);
         return { appointment: appointment,
        patient: Meteor.users.findOne(appointment ? appointment.patientId : null) } 
      }
    

    Sorry about the formatting, I'm doing this from an awful phone...