Simple string input element item in ng-repeat not updating

3,465 views
Skip to first unread message

Peter Bacon Darwin

unread,
Mar 15, 2012, 9:53:48 AM3/15/12
to ang...@googlegroups.com
Is this a bug: http://jsfiddle.net/petebd/WSEMf/

The input correctly displays the value set by the controller both on initialization and when you update it with the ng-click method.
But if you manually change the value in the input element the model is not updated, even on a blur. What is more (and even weirder) is that if you change manually the value of say the second element and then click the update link, the model updates as expected but the first input takes on the value of the second input and the second input updates correctly!

I appreciate that this situation occur rarely because you would bind to a field on an object (e.g. item.field) rather than the item itself (e.g. item) but could appear in custom widgets (sorry directives :-)).

Regards,
Pete

Misko Hevery

unread,
Mar 15, 2012, 1:30:19 PM3/15/12
to ang...@googlegroups.com
this is expected, but requires you to understand more about scopes. BTW, here is the angular-zen way http://jsfiddle.net/mhevery/WSEMf/4/

You have items array with primitives: [1, 2]

when the ngRepeat unrolls it copies the primitive into a local scope under item. Then ng-model binds to it. When you update the model you are updating a copy, not the original. but when you update the original it couses the repeater to realized that something changed in the items array and it then recreates the ng-model, which means ti re-copies it over to items. Hence the strange behavior but it is expected.

Short answer: never iterate and input bind to primitives in ngRepeat, as you are making a copy of value rather the reference and any updates are written to local scope rather then the original location.

-- misko

--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To post to this group, send email to ang...@googlegroups.com.
To unsubscribe from this group, send email to angular+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/angular?hl=en.

Peter Bacon Darwin

unread,
Mar 15, 2012, 1:35:37 PM3/15/12
to ang...@googlegroups.com
Thanks for the quick and clear response.
OK, it is "expected" but not intuitive.  Since binding to a primitive in most other scenarios works as one would intuit.
Perhaps ng-repeat could check whether the item from the iteration is not a primitive or at least give a warning?  Perhaps even more powerfully, if the item is a primitive then perhaps there could be a clever way for the ng-repeat directive to understand this and track the changes more intuitively?
Pete

Misko Hevery

unread,
Mar 15, 2012, 1:42:17 PM3/15/12
to ang...@googlegroups.com
So the ngRepeat works as expected and it is intuitive. Since you are copying primitive to local name 'item'

The ng-model is intuitive too,

Trouble is that when they interact you got non-intuitive behavior, since ng-repeat makes a copy of primitive, and ng-model then binds to the copy. (not to the original)

Repeating over primitives (provided there is no input bind) works as expected, so there is no simple rule for this, as it is interaction between two components.

Its kind of like this

var items = [1,2]
var item = items[0]
item = 'change'
expect(items[0]).toBe('change');

each statement is self consistant but the end result is not

-- Misko

Peter Bacon Darwin

unread,
Mar 15, 2012, 2:27:55 PM3/15/12
to ang...@googlegroups.com

I totally understand and agree with what you say. I guess my issue was that while what you say here is explicit and transparent, the copying inside ng-repeat is hidden and I did not see it mentioned in the docs.
Regards
Pete
...from my mobile.

gleb...@gmail.com

unread,
Aug 3, 2012, 9:04:14 AM8/3/12
to ang...@googlegroups.com, mi...@hevery.com
On Thursday, March 15, 2012 6:30:19 PM UTC+1, Misko Hevery wrote:
this is expected, but requires you to understand more about scopes. BTW, here is the angular-zen way http://jsfiddle.net/mhevery/WSEMf/4/

I have a very similar use case here:

https://github.com/greenelephantlabs/kha/blob/master/priv/www/index.html#L61
https://github.com/greenelephantlabs/kha/blob/master/priv/www/js/app.js#L93

The issue here is that whenever a person presses a key input's focus will be lost. Using structure like {value: 'make'} is OK. But for this to be useful - is there a way to translate data incoming from server from ["make"] to [{value: "make"}] in a single place? And the same the other way around, when saving.

Cheers,
Gleb Peregud
Reply all
Reply to author
Forward
Message has been deleted
0 new messages