Skip to content

Commit 3d0fcf9

Browse files
committed
fix(WatchGroup): Handle watching elements of array that were removed.
Closes dart-archive#1046
1 parent 1c7c0ba commit 3d0fcf9

File tree

2 files changed

+53
-3
lines changed

2 files changed

+53
-3
lines changed

lib/change_detection/ast_parser.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,11 @@ _operation_logical_and(left, right) => toBool(left) && toBool(right);
193193
_operation_logical_or(left, right) => toBool(left) || toBool(right);
194194

195195
_operation_ternary(condition, yes, no) => toBool(condition) ? yes : no;
196-
_operation_bracket(obj, key) => obj == null ? null : obj[key];
196+
_operation_bracket(obj, key) {
197+
if (obj is! List || (key is int && key >= 0 && key < obj.length)) {
198+
return obj[key];
199+
}
200+
}
197201

198202
class ArrayFn extends FunctionApply {
199203
// TODO(misko): figure out why do we need to make a copy?

test/directive/ng_repeat_spec.dart

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,6 @@ main() {
327327
expect(element.text).toEqual('misko:0|shyam:1|frodo:2|');
328328
});
329329

330-
331330
it(r'should expose iterator position as $first, $middle and $last when iterating over arrays',
332331
() {
333332
element = compile(
@@ -401,6 +400,54 @@ main() {
401400
expect(element.text).toEqual('a|b|Xc|d|X');
402401
});
403402

403+
describe('nested watching', () {
404+
it('should not error when the first item is being watched and it is removed', () {
405+
element = compile(
406+
'<ul>'
407+
' <li ng-repeat="i in items">'
408+
' <input ng-model="items[\$index]">'
409+
' </li>'
410+
'</ul>');
411+
scope.context['items'] = ['misko', 'shyam', 'frodo'];
412+
scope.apply();
413+
expect(element.children.length).toEqual(3);
414+
scope.context['items'].remove('misko');
415+
scope.apply();
416+
expect(element.children.length).toEqual(2);
417+
});
418+
419+
it('should not error when the last item is being watched and it is removed', () {
420+
element = compile(
421+
'<ul>'
422+
' <li ng-repeat="i in items">'
423+
' <input ng-model="items[\$index]">'
424+
' </li>'
425+
'</ul>');
426+
scope.context['items'] = ['misko', 'shyam', 'frodo'];
427+
scope.apply();
428+
expect(element.children.length).toEqual(3);
429+
scope.context['items'].remove('frodo');
430+
scope.apply();
431+
expect(element.children.length).toEqual(2);
432+
});
433+
434+
it('should not error when an items are being watched and multiple items are removed '
435+
'at the same time', () {
436+
element = compile(
437+
'<ul>'
438+
' <li ng-repeat="i in items">'
439+
' <input ng-model="items[\$index]">'
440+
' </li>'
441+
'</ul>');
442+
scope.context['items'] = ['misko', 'shyam', 'frodo', 'igor'];
443+
scope.apply();
444+
expect(element.children.length).toEqual(4);
445+
scope.context['items'].remove('shyam');
446+
scope.context['items'].remove('frodo');
447+
scope.apply();
448+
expect(element.children.length).toEqual(2);
449+
});
450+
});
404451

405452
describe('stability', () {
406453
var a, b, c, d, lis;
@@ -420,7 +467,6 @@ main() {
420467
lis = element.querySelectorAll('li');
421468
});
422469

423-
424470
it(r'should preserve the order of elements', () {
425471
scope.context['items'] = [a, c, d];
426472
scope.apply();

0 commit comments

Comments
 (0)