Binding to an array in ember with #each - ember.js

I was reading about how to observe an array and do something when elements were added or removed. See the official explanation here. The page says that if we observe with anArray.#each then it should fire in the case of adding an object to the array.
I tested that here and had two problems:
The observer I put on the component did not fire.
The dom did not update its displaying of the length of the array.
Any help appreciated, thanks.

You need to use pushObject when adding items to an array in Ember, it's how Ember is able to keep track of whether or not the array has changed. Likewise you need to always use get/set on your objects, also Ember's way of knowing that a property has changed on an object.
this.get('testArray').pushObject('foo');
http://emberjs.jsbin.com/hobarenu/2/edit

Related

Ember.js input action get element

I'm sorry I couldn't figure out something so basic and had to ask here, but in the newUser callback function, how do I get a reference to that input element?
{{input action="newUser"}}
I tried param=this this.$() this.get('element') Nothing worked in Ember 1.7
You could try
this.$('input')
which will return a jQuery-style element set on which you can do more jQuery-type things, or
this.get('element').querySelector('input')
this.get('element') will return the view element, so you need to poke down into it to find the input element, whether by tagname as above, or via some other selection mechanism such as id or class.
However, this assumes the action is defined within the view, where this.$ and this.get('element') are defined. It will not work if the action is defined on the controller or route. It is a common Ember pattern to have an action handler on the view, which does view-related things, and then sends some action along to the controller for it to do controller-related things.
However, if you are trying to retrieve the input element just in order to muck with its value, then you can do this much more easily by simply modifying the property bound to the input elements' value.
You don't even need a reference to the element to clear it. Just use data-binding:
http://emberjs.jsbin.com/telat/1/edit

Best way to have an updatable object in a partial?

jsbin
I am new to ember.js and trying to figure out the best way to accomplish an updatable list.
The list, inside a partial, is updated when a list item from another object is clicked. Is it better to save the clicked(chosen) items in a separate model? or is it better to use an array in the controller as I was trying to do in the above jsbin?
In either case, how is it accomplished? In my above attempt the totalValue seems to update fine, but the array does not which makes me think I was going about it wrong.
The chosenList is an array and ember array has it's own api methods in order to inform observes...
With this variation in your code, the property updates http://jsbin.com/eyatORO/3/edit
this.get('chosenList').addObject({
title:item.title,
value:item.value
});
Good Luck

How is Ember handling this controller .property()

I am displaying a list of Document titles on the site's sidebar area. To achieve this I created a documents property on the App.SidebarController
Document = require '../models/document'
SidebarController = Ember.Controller.extend
documents: (->
Document.find()
).property()
module.exports = SidebarController
This works fine, when I create a new Document in my application, this sidebar property get's updated automatically and I don't know why. It works no matter what I put in the .property() function. e.g.
.property('Document')
.property('App.Document')
Can somebody explain how this works? What would be the correct thing for the property() function to observe?
So you are basically saying that is works, but you would like to know why.
Here is my guess: When your controller gets rendered, your computed property gets computed for the first time and an instance of an array is returned. When you create a new Document, i think this very same array is updated (= Document is added). So it does work despite the fact, that you do not specify a dependent key on property(). This is because the right array is already in place. As i said just a guess, but this seems like an understandable explanation.
And what would be the correct thing to do?
IMHO one should not use such Data Access methods directly in a computed property. Instead you should call this Data Access method inside a Route and then assign it to the controller. This way you make sure, that the find() method gets executed when needed.

How to modify the sortProperties value dynamically inside an ember.js ArrayController

I'm using ember 1.0 pre and have a basic array controller that starts out with a default sort property of 'id'
PersonApp.PersonController = Ember.ArrayController.extend({
content: [],
sortProperties: ['id'],
updateSort: function(column) {
this.set('sortProperties', column);
}
});
I'd like to set this dynamically and have the dom updated for free. But when I do a simple setter (shown above) it doesn't update anything in my view or on the dom.
If I need the ability to update this dynamically how can I go about it?
The sortProperties must be an array, so I don't know if in your case, column is one.
Here is a js fiddle showing you dynamically setting it: http://jsfiddle.net/Sly7/jZVJA/22/
This answer does not respond to the original question, but I experienced this symptom and had a different root issue.
In my case, I was changing the sortProperties dynamically but this was having no effect on my array of models. The issue turned out to be that I was reading my backing array from a wrapper method, which failed to observe the sortProperties, so even though the sortProperties were updating, my template was not redrawing the underlying array.
Updating my wrapper method to observe sortProperties directly did the trick.

Emberjs Handlebars #each helper slow when bound to computed properties

I'm running into a performance issue when I render a list of items using the #each helper or a collection view bound to some computed properties of an Ember.ArrayController. Performance is fine with a small list of 10 - 20 items, but around 50 - 100 it starts to lag quite noticeably. Try checking off a few todos or clicking "Add Todo"
Example code is here: http://jsfiddle.net/Jonesy/ed3ZS/4/
I noticed that the childViews in the DOM get re-rendered with each change, which could very well be the intended behaviour at the moment, but I'd prefer to be able to just have a todo be removed from the DOM of unfinished todos list individually and appended to the bottom of the finished todos list, which would in theory be much less costly.
What I'm hoping to have answered is whether am I looking at a performance issue with Ember collection views, or is displaying a list populated from a computed property a bad idea, and if so, will I need to manually manage the todo model's location in the view layer as it changes from unfinished to finished and vice versa.
This is a side-effect of how {{#each}} (and CollectionView, which is what powers it) works.
Internally, CollectionView uses something called array observers. An array observer allows you to subscribe to mutations made to an array when they are done using Ember.Array's mutation methods (replace, pushObject, popObject, etc.) The API for array observers is described here.
What this means is that, if you push a new object into a collection view, it will insert render one new element in the DOM and leave the rest in place.
In the example you posted, however, the array is not being mutated--you're creating a brand new Array object every time a new item is added or removed. When the binding synchronizes, it replaces the old array with the new array. To {{#each}}, this is no different than removing all of the elements and then adding them back in.
The solution to the problem is to use a single array, instead of a computed property that returns a different array object each time it changes. You can see the Contacts app for an example of how to do this.
Obviously this is a very common pattern, and we'd like to add some kind of filtering that does the right thing by default to Ember.ArrayController down the road.