General state in the Ember component

I tried to create a simple list with the addition of a widget as an Emberjs component.

Below is the code I used:

HTML:

<!DOCTYPE html> <html> <head> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script src="http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0/handlebars.js"></script> <script src="http://cdnjs.cloudflare.com/ajax/libs/ember.js/1.0.0/ember.min.js"></script> <meta charset=utf-8 /> <title>Ember Component example</title> </head> <body> <script type="text/x-handlebars" id="components/appendable-list"> <h2> An appendable list </h2> <ul> {{#each item in myList}} <li> {{item}} </li> {{/each}} </ul> {{input type="text" value=newItem}} <button {{action 'append'}}> Append Item </button> </script> <script type="text/x-handlebars"> {{appendable-list}} {{appendable-list}} </script> </body> </html> 

JavaScript:

 App = Ember.Application.create(); App.AppendableListComponent = Ember.Component.extend({ theList: Ember.ArrayProxy.create({ content: [] }), actions: { appendItem: function(){ var newItem = this.get('newItem'); this.get('theList').pushObject(newItem); } } }); 

In this case, the list is split between two instances (that is, it is added to one addition to another)

Here is the JsBin to check this out: http://jsbin.com/arACoqa/7/edit?html,js,output

If I do the following, it works:

 window.App = Ember.Application.create(); App.AppendableListComponent = Ember.Component.extend({ didInsertElement: function(){ this.set('myList', Ember.ArrayProxy.create({content: []})); }, actions: { append: function(){ var newItem = this.get('newItem'); this.get('myList').pushObject(newItem); } } }); 

Here is JsBin: http://jsbin.com/arACoqa/8/edit?html,js,output

What am I doing wrong? Thanks in advance!

+5
source share
2 answers

After you declare a component, every time you use it in your template, a new instance will be created, and, most importantly, the init hook will be called every time you create an instance of a new instance, so different arrays of myList have the safest way. to use component init hook to initialize the array, so try the following:

 App.AppendableListComponent = Ember.Component.extend({ myList: null, init: function(){ this._super(); this.set('myList', Ember.ArrayProxy.create({content: []})); }, actions: { append: function(){ var newItem = this.get('newItem'); this.get('myList').pushObject(newItem); } } }); 

It is also important to call this._super(); inside init , and everything will work as expected.

See a working demo here .

Hope this helps.

+7
source

When you use extend(hash) any value present in the hash will be copied to any instantiated instance. And since the array is an object, your reference will be the same for all created objects:

 App.MyObject = Ember.Object.extend({ text: [] }); obj1 = App.MyObject.create(); obj2 = App.MyObject.create(); obj1.get('text') === obj2.get('text') // true obj1.get('text').pushObject('lorem'); obj1.get('text'); // ["lorem"] obj2.get('text').pushObject('ipsum'); obj2.get('text'); // ["lorem", "ipsum"] 

didInsertElement is didInsertElement for each new view created, and each view is a different instance. Thus, with your implementation, you will always have a new instance of Ember.ArrayProxy for each view, then there is no general state:

 didInsertElement: function() { // each call for this method have a diferent instance this.set('myList', Ember.ArrayProxy.create({content: []})); } 
+4
source

Source: https://habr.com/ru/post/976221/


All Articles