Syl
Syl

Reputation: 3829

dynamic looping on a controller property

I am using ember 2.17.

I added this property to a controller:

export default Controller.extend({
  newAttachments: new Array()
  ...
})

I add elements in it through this controller action:

setAttachment(file) {
  console.log('trying');
  this.get('newAttachments').push(file);
}

When I use the action, the message is displayed in the console, and in Ember inspector I can see the array is no longer empty :

enter image description here

However, the following code in the view has no output :

{{#each newAttachments as |file|}}
  <p>in loop</p>
{{/each}}

Why is it not displaying anything? In a component it would work, why not here ?

Upvotes: 1

Views: 69

Answers (1)

jelhan
jelhan

Reputation: 6338

Ember can't observe native arrays. Therefor the framework doesn't know that a value is pushed into the array. You should use ember's own Ember.NativeArray and it's pushObject method instead. That one ensures that the framework is informed if an entry is added to or removed from array. Changed code would look like this:

import { A } from '@ember/array';

export default Controller.extend({
  newAttachments: A(),

  setAttachment(file){
    this.get('newAttachments').pushObject(file)
  }
})

You shouldn't add the array as a property of an EmberObject as this might introduce a leak between instances. That's not a production issue in that case cause controllers are singletons in ember.js. But you might see strange behavior in tests. Refactoring for native classes will resolve that issues as class fields are not leaked between instances. For old EmberObject based classes initializing the value in init hook or using a computed property are common ways to deal with that issue:

// computed property
import { computed } from '@ember/object';
import { A } from '@ember/array';

export default Controller.extend({
  newAttachments: computed(() => A()),
});
// init hook
import { A } from '@ember/array';

export default Controller.extend({
  init() {
    this._super(...arguments);

    this.set('newAttachments', A());
  }
});

Please note that you don't need to use get() if running Ember >= 3.1.

Upvotes: 3

Related Questions