Passing A Promise From The Model To A Component


#1

Hi, I’m my template I’m try to pass in a property of my model to a component.

{{display-notifications notifications=model.notifications}}

Where model has notifications: DS.hasMany('notification', {async:true, inverse: 'user'}),

The problem is inside my component the notification promise hasn’t been fulfilled yet. Any tips how how I can fix this?


#2

Your {{display-notifications}} component will have to deal with a notifications promise, or try something like ember-promise-helpers or ember-resolve-promise-helper.

{{display-notifications notifications=(await model.notifications)}}
{{!-- OR (respective to each addon mentioned above) --}}
{{display-notifications notifications=(resolve-promise model.notifications)}}

#3

Is there anyway I can do this in the controller instead, wait for the promise for model.notifications to resolve and then access it?


#4

One thing that I like to do is deal with resolving promises in the didReceiveAttrs hook like so:

{{display-notifications notifications=(readonly model.notifications)}}
didReceiveAttrs() {
    Promise.resolve(this.get('notifications')).then(x => {
        this.set('notifications', x);
    });
}

This way the component can handle normalization of the attributes into a form it expects, and usage remains consistent.


#5

Another alternative is to use ember-concurrency, and define it as a task in your controller, and then go from there:

import { task } from 'ember-concurrency';

export default Ember.Controller.extend({
  loadNotifications: task(function * (promise) {
    let notifications = yield promise;
    this.set('notifications', notifications);
  })
});

Then you can trigger that in the template with

  <button onclick={{perform loadNotifications model.notifications}}>
    Load Notifications
  </button>

Then you can also see state, via {{if loadNotifications.isRunning 'Loading..'}}.

<button onclick={{perform loadNotifications model.notifications}}>
  Load Notifications
</button>

{{#if loadNotifications.isRunning}}
  Loading notifications..
{{else if notifications}}
  {{#each notifications as |notification|}}
    {{notification.title}}
  {{else}}
    No notifications available.
  {{/each}}
{{/if}}

#6

Thanks for the replies, I was able to get it working with

notificationsCount: Ember.computed(function() {
    if(this.get('model') != null){
      return DS.PromiseArray.create({
      promise: this.get('model.notifications').then(notifications => {
          return notifications;
        })
      });
    }
  }).property('model.notifications.@each.isRead'),

With a component {{display-notifications notifications=notificationsCount}}