samedi 26 novembre 2016

Ember Computed Property on Array

I'm an Ember newbie, so forgive me if I've missed something obvious (I've spent time Googling this issue and still can't find a solution) but it seems to me that Ember computed properties aren't working as documented/intended on array properties like length.

I'm trying to build my own queue:

// app/custom-objects/processing-queue-item.js
import Ember from 'ember';

export default Ember.Object.extend({
  payload: null,
  extraContext: null,
  processingState: 'pending', // pending, succeeded, failed
  processingOutcome: null,    // null for pending, result for      succeeded, error for failed

  toString() {
    return `{ProcessingQueueItem: processingState=${this.get('processingState')}, processingOutcome=${this.get('processingOutcome')}, extraContext=${this.get('extraContext')}, payload=${this.get('payload')}}`;
  }
});

// app/custom-objects/processing-queue.js
import Ember from 'ember';
import ProcessingQueueItem from './processing-queue-item';

export default Ember.Object.extend(Ember.Enumerable, {
  queueName: null,

init() {
  this.set('items', []);
  this.get('items');
  this.get('items.length');
  this.get('length'); // Force observation
},

/*
 * Public API
 */

enqueue(payload, extraContext = null) {
 let itemToEnqueue = ProcessingQueueItem.create({ payload: payload, extraContext: extraContext });

 this.get('items').pushObject(itemToEnqueue);
 this.scheduleProcessing();

 return itemToEnqueue;
},

toString() {
  return `{ProcessingQueue: queueName=${this.get('queueName')}, length=${this.get('length')}}`;
},

 /*
  * Internal API
  */

scheduleProcessing() {
  Ember.run(() => {
    this.maybeProcessAnItem();
  });
},

maybeProcessAnItem() {
  console.log(`maybe process an item ${this}`);
},

/*
 * Ember.Enumerable mixin
 */

length: Ember.computed('items.length', function() {
  return this.get('items.length');
}),

nextObject(index, previousObject, context) {
  return this.get('items').nextObject(index, previousObject, context);
}
});

This class is incomplete, but I want to start displaying queue contents in a template to help with debugging but I can't get that to work. Here are my controller and template:

// app/controllers/dashboard.js
import Ember from 'ember';
import ProcessingQueue from '../custom-objects/processing-queue';

export default Ember.Controller.extend({
  init() {
  this._super(...arguments);
  this.set('processingQueue', ProcessingQueue.create({ queueName: 'DashboardQueue' }));
  this.get('processingQueue');
  this.get('processingQueue.length');
  this.get('queueLength');
 },

 queueLength: Ember.computed('processingQueue.length', function() {
   return this.get('processingQueue.length');
 }),
});

// app/templates/dashboard.hbs
<h1>Dashboard</h1>

<h2>Queue Length: ''</h2>

<p></p>




The problem is, in the <h2>Queue Length: ''</h2>, the queue length is always undefined until I add items to the queue. But this is not true, the queue has an empty array and a length of 0. Using $E from the dashboard controller from EmberInspector I can see that $E.get('processingQueue.length') and $E.get('queueLength') are both undefined.

What's strange is that as soon as I add items to the queue, the queue length becomes defined, 1, 2, 3, ... and keeps up and syncs the template as I add queue items. So the first $E.get('processingQueue').enqueue('foo') automagically updates the template to show a queue length of '0', then '1' and so on.

Why is it undefined though before I've enqueued any items? I tried adding gets all over the place according to Unconsumed Computed Properties Do No Trigger Observers but that doesn't seem to help.

Any ideas? It's entirely possible that I misunderstand something about computed properties here, but I don't understand what and why ... I've tried volatile(), [], @each and all that and I can't get that to make a difference either. Something is not right ...

Any help would be hugely appreciated and I'd be willing to add to the Wiki, write a blog post and maybe release my queue as open source as a thank you. :-)

Thanks! And thanks again for making Ember so awesome!




Aucun commentaire:

Enregistrer un commentaire