mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-16 23:30:23 +00:00
fix(ngRepeat): correctly track elements even when the collection is initially undefined
Previously if the collection model was set to undefined on the first digest, the repeater would get confused and not use the correct tracking function for associating model with dom elements in the repeater. Closes #4145 Closes #3964
This commit is contained in:
parent
f8f8f754b0
commit
31c56f5400
2 changed files with 26 additions and 6 deletions
|
|
@ -218,7 +218,8 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
|
|||
return function($scope, $element, $attr){
|
||||
var expression = $attr.ngRepeat;
|
||||
var match = expression.match(/^\s*(.+)\s+in\s+(.*?)\s*(\s+track\s+by\s+(.+)\s*)?$/),
|
||||
trackByExp, trackByExpGetter, trackByIdFn, trackByIdArrayFn, trackByIdObjFn, lhs, rhs, valueIdentifier, keyIdentifier,
|
||||
trackByExp, trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn,
|
||||
lhs, rhs, valueIdentifier, keyIdentifier,
|
||||
hashFnLocals = {$id: hashKey};
|
||||
|
||||
if (!match) {
|
||||
|
|
@ -232,7 +233,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
|
|||
|
||||
if (trackByExp) {
|
||||
trackByExpGetter = $parse(trackByExp);
|
||||
trackByIdFn = function(key, value, index) {
|
||||
trackByIdExpFn = function(key, value, index) {
|
||||
// assign key, value, and $index to the locals so that they can be used in hash functions
|
||||
if (keyIdentifier) hashFnLocals[keyIdentifier] = key;
|
||||
hashFnLocals[valueIdentifier] = value;
|
||||
|
|
@ -275,6 +276,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
|
|||
childScope,
|
||||
key, value, // key/value of iteration
|
||||
trackById,
|
||||
trackByIdFn,
|
||||
collectionKeys,
|
||||
block, // last object information {scope, element, id}
|
||||
nextBlockOrder = [];
|
||||
|
|
@ -282,9 +284,9 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
|
|||
|
||||
if (isArrayLike(collection)) {
|
||||
collectionKeys = collection;
|
||||
trackByIdFn = trackByIdFn || trackByIdArrayFn;
|
||||
trackByIdFn = trackByIdExpFn || trackByIdArrayFn;
|
||||
} else {
|
||||
trackByIdFn = trackByIdFn || trackByIdObjFn;
|
||||
trackByIdFn = trackByIdExpFn || trackByIdObjFn;
|
||||
// if object, extract keys, sort them and use to determine order of iteration over obj props
|
||||
collectionKeys = [];
|
||||
for (key in collection) {
|
||||
|
|
|
|||
|
|
@ -841,6 +841,26 @@ describe('ngRepeat', function() {
|
|||
expect(newLis[1]).toEqual(lis[0]);
|
||||
expect(newLis[2]).toEqual(lis[1]);
|
||||
});
|
||||
|
||||
it('should be stable even if the collection is initially undefined', function () {
|
||||
scope.items = undefined;
|
||||
scope.$digest();
|
||||
|
||||
scope.items = [
|
||||
{ name: 'A' },
|
||||
{ name: 'B' },
|
||||
{ name: 'C' }
|
||||
];
|
||||
scope.$digest();
|
||||
|
||||
lis = element.find('li');
|
||||
scope.items.shift();
|
||||
scope.$digest();
|
||||
|
||||
var newLis = element.find('li');
|
||||
expect(newLis.length).toBe(2);
|
||||
expect(newLis[0]).toBe(lis[1]);
|
||||
});
|
||||
});
|
||||
|
||||
it('should grow multi-node repeater', inject(function($compile, $rootScope) {
|
||||
|
|
@ -861,8 +881,6 @@ describe('ngRepeat', function() {
|
|||
$rootScope.$digest();
|
||||
expect(element.text()).toEqual('T1:D1;T2:D2;T3:D3;');
|
||||
}));
|
||||
|
||||
|
||||
});
|
||||
|
||||
describe('ngRepeat animations', function() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue