@@ -83,7 +83,7 @@ class NgRepeat {
83
83
String _valueIdentifier;
84
84
String _keyIdentifier;
85
85
String _listExpr;
86
- List <_Row > _rows ;
86
+ List <View > _views ;
87
87
Function _generateId = (key, value, index) => value;
88
88
Watch _watch;
89
89
@@ -131,109 +131,95 @@ class NgRepeat {
131
131
_watch = _scope.watch (
132
132
_listExpr,
133
133
(changes, _) {
134
- _onChange ((changes is CollectionChangeRecord ) ? changes : null );
134
+ if (changes is CollectionChangeRecord && changes != null ) {
135
+ _onCollectionChange (changes);
136
+ } else if (_views != null ) {
137
+ _views.forEach (_viewPort.remove);
138
+ _views = null ;
139
+ }
135
140
},
136
141
collection: true ,
137
142
formatters: formatters
138
143
);
139
144
}
140
145
141
- // Computes and executes DOM changes when the item list changes
142
- void _onChange (CollectionChangeRecord changes) {
143
- final iterable = (changes == null ) ? const [] : changes.iterable;
144
- final int length = (changes == null ) ? 0 : changes.length;
145
- final rows = new List <_Row >(length);
146
+ void _onCollectionChange (CollectionChangeRecord changes) {
147
+ final int length = changes.length;
148
+ final views = new List <View >(length);
146
149
final changeFunctions = new List <Function >(length);
147
150
final removedIndexes = < int > [];
148
- final int domLength = _rows == null ? 0 : _rows .length;
151
+ final int domLength = _views == null ? 0 : _views .length;
149
152
final leftInDom = new List .generate (domLength, (i) => domLength - 1 - i);
150
153
var domIndex;
151
154
152
- var addRow = (int index, value, View previousView) {
153
- var childContext = _updateContext (new PrototypeMap (_scope.context), index,
154
- length)..[_valueIdentifier] = value;
155
- var childScope = _scope.createChild (childContext);
156
- var view = _boundViewFactory (childScope);
157
- var nodes = view.nodes;
158
- rows[index] = new _Row (_generateId (index, value, index))
159
- ..view = view
160
- ..scope = childScope
161
- ..nodes = nodes
162
- ..startNode = nodes.first
163
- ..endNode = nodes.last;
164
- _viewPort.insert (view, insertAfter: previousView);
165
- };
155
+ Function addFn, moveFn, removeFn;
166
156
167
- // todo(vicb) refactor once GH-774 gets fixed
168
- if (_rows == null ) {
169
- _rows = new List <_Row >(length);
170
- for (var i = 0 ; i < length; i++ ) {
171
- changeFunctions[i] = (index, previousView) {
172
- addRow (index, iterable.elementAt (i), previousView);
173
- };
174
- }
157
+ if (_views == null ) {
158
+ addFn = changes.forEachItem;
159
+ moveFn = (_) {};
160
+ removeFn = (_) {};
175
161
} else {
176
- if (changes == null ) {
177
- _rows.forEach ((row) {
178
- _viewPort.remove (row.view);
179
- });
180
- leftInDom.clear ();
181
- } else {
182
- changes.forEachRemoval ((CollectionChangeItem removal) {
183
- var index = removal.previousIndex;
184
- var row = _rows[index];
185
- _viewPort.remove (row.view);
186
- leftInDom.removeAt (domLength - 1 - index);
187
- });
188
-
189
- changes.forEachAddition ((CollectionChangeItem addition) {
190
- changeFunctions[addition.currentIndex] = (index, previousView) {
191
- addRow (index, addition.item, previousView);
192
- };
193
- });
194
-
195
- changes.forEachMove ((CollectionChangeItem move) {
196
- var previousIndex = move.previousIndex;
197
- var value = move.item;
198
- changeFunctions[move.currentIndex] = (index, previousView) {
199
- var previousRow = _rows[previousIndex];
200
- var childScope = previousRow.scope;
201
- var childContext = _updateContext (childScope.context, index, length);
202
- if (! identical (childScope.context[_valueIdentifier], value)) {
203
- childContext[_valueIdentifier] = value;
204
- }
205
- rows[index] = _rows[previousIndex];
206
- // Only move the DOM node when required
207
- if (domIndex < 0 || leftInDom[domIndex] != previousIndex) {
208
- _viewPort.move (previousRow.view, moveAfter: previousView);
209
- leftInDom.remove (previousIndex);
210
- }
211
- domIndex-- ;
212
- };
213
- });
214
- }
162
+ addFn = changes.forEachAddition;
163
+ moveFn = changes.forEachMove;
164
+ removeFn = changes.forEachRemoval;
215
165
}
216
166
167
+ removeFn ((CollectionChangeItem removal) {
168
+ var index = removal.previousIndex;
169
+ _viewPort.remove (_views[index]);
170
+ leftInDom.removeAt (domLength - 1 - index);
171
+ });
172
+
173
+ addFn ((CollectionChangeItem addition) {
174
+ changeFunctions[addition.currentIndex] = (index, previousView) {
175
+ var childContext = _updateContext (new PrototypeMap (_scope.context), index,length)
176
+ ..[_valueIdentifier] = addition.item;
177
+ var childScope = _scope.createChild (childContext);
178
+ var view = views[index] = _boundViewFactory (childScope);
179
+ _viewPort.insert (view, insertAfter: previousView);
180
+ };
181
+ });
182
+
183
+ moveFn ((CollectionChangeItem move) {
184
+ var previousIndex = move.previousIndex;
185
+ var value = move.item;
186
+ changeFunctions[move.currentIndex] = (index, moveAfter) {
187
+ var previousView = _views[previousIndex];
188
+ var childScope = previousView.scope;
189
+ var childContext = _updateContext (childScope.context, index, length);
190
+ if (! identical (childScope.context[_valueIdentifier], value)) {
191
+ childContext[_valueIdentifier] = value;
192
+ }
193
+ views[index] = _views[previousIndex];
194
+ // Only move the DOM node when required
195
+ if (domIndex < 0 || leftInDom[domIndex] != previousIndex) {
196
+ _viewPort.move (previousView, moveAfter: moveAfter);
197
+ leftInDom.remove (previousIndex);
198
+ }
199
+ domIndex-- ;
200
+ };
201
+ });
202
+
217
203
var previousView = null ;
218
204
domIndex = leftInDom.length - 1 ;
219
205
for (var targetIndex = 0 ; targetIndex < length; targetIndex++ ) {
220
206
var changeFn = changeFunctions[targetIndex];
221
207
if (changeFn == null ) {
222
- rows [targetIndex] = _rows [targetIndex];
208
+ views [targetIndex] = _views [targetIndex];
223
209
if (domIndex < 0 || leftInDom[domIndex] != targetIndex) {
224
- _viewPort.move (rows [targetIndex].view , moveAfter: previousView);
210
+ _viewPort.move (views [targetIndex], moveAfter: previousView);
225
211
leftInDom.remove (targetIndex);
226
212
}
227
213
domIndex-- ;
228
214
// The element has not moved but `$last` and `$middle` might still need to be updated
229
- _updateContext (rows [targetIndex].scope.context, targetIndex, length);
215
+ _updateContext (views [targetIndex].scope.context, targetIndex, length);
230
216
} else {
231
217
changeFn (targetIndex, previousView);
232
218
}
233
- previousView = rows [targetIndex].view ;
219
+ previousView = views [targetIndex];
234
220
}
235
221
236
- _rows = rows ;
222
+ _views = views ;
237
223
}
238
224
239
225
PrototypeMap _updateContext (PrototypeMap context, int index, int length) {
@@ -248,14 +234,3 @@ class NgRepeat {
248
234
..[r'$even' ] = index.isEven;
249
235
}
250
236
}
251
-
252
- class _Row {
253
- final id;
254
- Scope scope;
255
- View view;
256
- dom.Element startNode;
257
- dom.Element endNode;
258
- List <dom.Node > nodes;
259
-
260
- _Row (this .id);
261
- }
0 commit comments