0

I have 2 models deliverHour and day. In an .hbs file, I have two nested each loops.

I am trying to display the delivery hours for each day. Apparently, once it reaches the second each loop, it doesnt render anything. Not even this line does not render!

Looking in Ember Inspector. I do not see any failed promises. The network tab doesn't even show Ember trying to attempt calling the delivery hour end point. The Data tab shows delivery-hour (0), which means no delivery hours in the store, which is strange.

Since the relationship for the day model has DS.hasMany('deliveryHour', { async: true }) I would have expected Ember to do an asynchronous call to the delivery hour api resource. No?

What am I missing here?

// Route
import Ember from 'ember';

export default Ember.Route.extend({
  model: function(params) {
    var addressId = this.checkoutCart.get('addressId');

    return Ember.RSVP.hash({
      address:       this.store.find('address', addressId),
      delivery:      this.store.createRecord('delivery'),
      days:          this.store.find('day')
    });
  },

  // You can use model.delivery to get delivery, etc
  // Since the model is a plain object you can just use setProperties
  // http://stackoverflow.com/questions/16463958/how-to-use-multiple-models-with-a-single-route-in-emberjs-ember-data
  setupController: function(controller, model) {
    controller.setProperties(model);
  },
});

// app/models/delivery-hour.js
import DS from 'ember-data';

export default DS.Model.extend({
  day:    DS.belongsTo('day', { async: true }),
  from:   DS.belongsTo('hour', { async: true }),
  to:     DS.belongsTo('hour', { async: true }),
  status: DS.attr('string')
});

// app/models/day.js
import DS from 'ember-data';

export default DS.Model.extend({
  deliveryHours: DS.hasMany('deliveryHour', { async: true }),
  name:          DS.attr('string'),
  dayOfTheWeek:  DS.attr('number')
});

// hbs
{{#each day in days}}
  <li>
    {{day.name}} // Returns something like 'Monday'
    {{day.deliveryHours}} // Returns something like <(subclass of DS.PromiseArray):ember770>
    {{day.deliveryHours.length}} // Returns 0

    {{#each deliveryHour in day.deliveryHours}}
      this line does not render!
      {{deliveryHour.hour}} <----- ideally, this is what i want to see
    {{/each}}
  </li>
{{/each}}

{{day.deliveryHours.length}} returns 0. I wanted to verify this. I am using Rails as my API. In Rails console, when I do Day.first.delivery_hours.count, it returns 4. Strange that Ember returns 0. The Network tab, in Ember Inspector, does not show Ember trying to call the delivery hours API endpoint.

On the top right corner of the screenshot, I click on the > $E. Then I go to the console tab of Ember inspector and paste: $E.get('deliveryHours'). I get Object { content: Getter, toString: makeToString/<(), isFulfilled: true, 4 more… }.

In the console of Ember Inspector, I also tried:

>> $E.get('deliveryHours').then(function(hours) { console.log(hours.get('length'));});
Object { _id: 156, _label: undefined, _state: undefined, _result: undefined, _subscribers: Array[0] }

enter image description here

Update: My API response for days returns as:

{
    "days": 
[
{

    "id": 1,
    "name": "Monday",
    "day_of_the_week": 1

},
{

    "id": 2,
    "name": "Tuesday",
    "day_of_the_week": 2

},
{

    "id": 3,
    "name": "Wednesday",
    "day_of_the_week": 3

},
{

    "id": 4,
    "name": "Thursday",
    "day_of_the_week": 4

},
{

    "id": 5,
    "name": "Friday",
    "day_of_the_week": 5

},
{

    "id": 6,
    "name": "Saturday",
    "day_of_the_week": 6
},
{
    "id": 7,
    "name": "Sunday",
    "day_of_the_week": 7
}
]
}

http://emberjs.com/guides/models/the-rest-adapter/#toc_relationships indicates that I should probably load the delivery_hours as an array of ID's. I've tried this too, same results..

Christian Fazzini
  • 18,642
  • 20
  • 100
  • 212
  • Strange. What if you try to print `{{day.deliveryHours.length}}`? If you send `days` to the console as $E via the inspector, does `$E.get('firstObject.deliveryHours')` work? Does it trigger a network request? – Buck Doyle Jan 23 '15 at 18:38
  • Oh, I forgot about it being asynchronous. Try this: `$E.get('firstObject.deliveryHours').then(function(hours) { console.log(hours.get('length'));});` – Buck Doyle Jan 24 '15 at 04:17
  • @BuckDoyle I made an edit, which includes your suggestions. By the way, I used `$E.get('deliveryHours')`, not `$E.get('firstObject.deliveryHours')` – Christian Fazzini Jan 24 '15 at 08:13

1 Answers1

1

That's because deliveryHours is an async property in your model, which is why {{day.deliverHours}} returns an unresolved promise, instead of the record array you were expecting.

You'll have to explicitly resolve it in an afterModel hook, like so:

// Route
import Ember from 'ember';

var RSVP = Ember.RSVP;

export default Ember.Route.extend({
  // ...

  afterModel: function(model) {
    return RSVP.all(
      model.days.map(function(day) {
        return day.get('deliveryHours');
      })
    );
  }

});
  • But isn't that the whole point of `async` to asynchronously load the relevant models when needed (with or without an `afterModel` hook? – Christian Fazzini Jan 24 '15 at 12:18
  • Yeah, ember-data will only load `async` relationships when requested. I just noticed you updated your question with your API response. I'm assuming you're using the `DS.ActiveModelAdapter` since you're using Rails, so you'll also need to include `delivery_hour_ids` [link](http://emberjs.com/api/data/classes/DS.ActiveModelAdapter.html#toc_json-structure) – Lauren Elizabeth Tan Jan 24 '15 at 13:41
  • Yeap, including `delivery_hours_ids` in the API payload seems to work. Don't know why the docs (http://emberjs.com/guides/models/the-rest-adapter/#toc_relationships) suggested `comments` instead of `commend_ids` – Christian Fazzini Jan 25 '15 at 11:43