-
Notifications
You must be signed in to change notification settings - Fork 27.5k
Conversation
This commits adds test for angular#933 and simplifies the implementation of the fix Closes angular#933
In cases when we reuse elements in a repeater but associate them with a new scope (see angular#933 - repeating over array of primitives) it's possible for the internal ngModel state and the scope state to get out of sync. This change ensure that the two are always sync-ed up even in cases where we reassociate an element with a different (but similar) scope. In the case of repeating over array of primitives it's still possible to run into issue if we iterate over primitives and use form controls or similar widgets without ngModel - oh well, we'd likely need a special repeater for primitives to deal with this properly, even then there might be cornercases. Closes angular#933
I'm reverting changes that were originally done to ngRepeat to fix angular#933, because these are now not necessary after the previous changes to keep ngModel always synced with the DOM.
selector => cssClasses
We need to watch $index in addition to cssClasses because only then we can correctly respond to shrinking or reordered repeaters. Closes angular#1076
HI @IgorMinar, This repeater fix still has a problem with input controls that are bound to model[$index] losing focus when the input changes. See this Plnkr: http://plnkr.co/edit/aEIdRO?p=preview. I have set it up to use your build of AngularJS (this branch). Not sure how I make a unit test to demonstrate this. I think what you need to do, if you see the my-repeat directive, is not to create a new scope if the value that is being iterated is a primitive, but instead to just update the model. This also has a performance improvement that the DOM is not being modified as much - i.e. only items bound to the changed model have to update, whereas at the moment the whole transclusion is being destroyed and rebuild on every change. Pete |
I don't fully understand this, and I don't see how you can automatically switch between index affinity and object affinity, so I am skeptical of this. Could you better explain the logic of the repeater. Also I think we should write a $watch function which is a simple look which '===' elements to see if anything changes before going through the expensive repeat algorithm. |
This unit test needs to pass:
Currently if you change items[1] to equal items[2], the repeater moves the elements around and any input box that was in the 1th position loses focus. Trying to move scopes/elements for primitives values is too prone to error. If it is to be done it needs to ensure that you are not stealing a different items element/scope. I believe these are cases that need to be considered:
This will mean that objects are reused if they move and that scope/elements are reused if their index doesn't change. This seems like the least likely to cause application developer confusion. |
Just reviewed with Igor. I agree with merging this. This only fixes the symptom, not the issue. Long term, let's try the Misko's idea for optimizing |
+1 if you feel it should be merged. On Mon, Nov 26, 2012 at 2:46 PM, Vojta Jina notifications@git.luolix.topwrote:
|
Can you please address the issue of input boxes losing focus when you change a primitive type? |
@petebacondarwin yes, this change fails the input box focus test. this is an expected behavior because the repeater uses identity affinity instead of index affinity. the solution you described relies purely on index affinity, which means that would make the repeater unstable (there is no affinity between model identity and cloned DOM view). the stability is an important feature that you need when you start building more complex uis with repeaters (and these are never built with model composed of primitive values). the test you wrote proves that the repeater is unstable and uses index affinity. as misko mentioned the more we think about this the more it looks like the best choice for us is to internally implement stable repeater with affinity to object identity for objects/non-primitive values and unstable repeater (one with affinity to index/position) for primitives. I looked at your |
the current change doesn't try to use index affinity for changing primitive values. it always uses object affinity, which turns into lame index affinity for primitives.
yes, but that's for a separate PR. |
@petebacondarwin how many and which of the existing ngRepeat tests fail if you try to use your repeater instead of ours? |
Hi Igor, There are only 2 tests failing - once I had removed dealloc, changed
Tomorrow I will add back in the object key iteration, which is fairly Thanks again, On 26 November 2012 15:54, Igor Minar notifications@github.com wrote:
|
@petebacondarwin sounds good. I'm going to go ahead and merge what we have so far and then we can work with your changes and see if they can resolve the remaining issues. |
OK. Thanks. On 26 November 2012 19:15, Igor Minar notifications@github.com wrote:
|
this landed. @petebacondarwin please open a new PR with your changes. |
@IgorMinar @petebacondarwin Things got definitivelly better in 1.0.3 but there are still some issues: Opened issue: #1389 I guess you are aware of this one but just for the record. |
I have reverted the original fix for #933 because it was making the repeater unstable and in general was causing a lot of churn in the DOM. The current fix via ngModel is not ideal, but better IMO.
I also added proper fix for #1076. Similar fix was originally submitted by an external contributor, Misko dismissed it and accepted only tests because these tests were now passing thanks to the repeater changes - but that was only because the repeater was inefficient and was rebuilding the dom on every digest.