diff options
| author | Vojta Jina | 2012-03-28 13:47:57 -0700 |
|---|---|---|
| committer | Igor Minar | 2012-03-29 07:30:32 -0700 |
| commit | f2106692b1ebf00aa5f8b2accd75f014b6cd4faa (patch) | |
| tree | 1a8c97e04014c559da4e7cc6877dbe34ce7d6783 | |
| parent | 4557881cf84f168855fc8615e174f24d6c2dd6ce (diff) | |
| download | angular.js-f2106692b1ebf00aa5f8b2accd75f014b6cd4faa.tar.bz2 | |
fix($compile): properly clone attr.$observers in ng-repeat
The `attr` object was only shallow copied which caused all observers to be shared.
Fixing similar issue in ng-* boolean attributes as well as ng-src and ng-href.
| -rw-r--r-- | src/ng/compiler.js | 1 | ||||
| -rw-r--r-- | src/ng/directive/booleanAttrDirs.js | 6 | ||||
| -rw-r--r-- | test/ng/compilerSpec.js | 35 |
3 files changed, 40 insertions, 2 deletions
diff --git a/src/ng/compiler.js b/src/ng/compiler.js index a22c5d66..2e8de121 100644 --- a/src/ng/compiler.js +++ b/src/ng/compiler.js @@ -611,6 +611,7 @@ function $CompileProvider($provide) { } else { attrs = shallowCopy(templateAttrs); attrs.$element = jqLite(linkNode); + attrs.$observers = {}; } element = attrs.$element; diff --git a/src/ng/directive/booleanAttrDirs.js b/src/ng/directive/booleanAttrDirs.js index 7da52db0..f79c02ce 100644 --- a/src/ng/directive/booleanAttrDirs.js +++ b/src/ng/directive/booleanAttrDirs.js @@ -283,9 +283,10 @@ forEach(BOOLEAN_ATTR, function(propName, attrName) { var normalized = directiveNormalize('ng-' + attrName); ngAttributeAliasDirectives[normalized] = function() { return { + priority: 100, compile: function(tpl, attr) { - attr.$observers[attrName] = []; return function(scope, element, attr) { + attr.$observers[attrName] = []; scope.$watch(attr[normalized], function(value) { attr.$set(attrName, value); }); @@ -301,9 +302,10 @@ forEach(['src', 'href'], function(attrName) { var normalized = directiveNormalize('ng-' + attrName); ngAttributeAliasDirectives[normalized] = function() { return { + priority: 100, compile: function(tpl, attr) { - attr.$observers[attrName] = []; return function(scope, element, attr) { + attr.$observers[attrName] = []; attr.$observe(normalized, function(value) { attr.$set(attrName, value); }); diff --git a/test/ng/compilerSpec.js b/test/ng/compilerSpec.js index dc2e20cf..fb5e99e6 100644 --- a/test/ng/compilerSpec.js +++ b/test/ng/compilerSpec.js @@ -1374,6 +1374,41 @@ describe('$compile', function() { }); + it('should properly $observe inside ng-repeat', function() { + var spies = []; + + module(function($compileProvider) { + $compileProvider.directive('observer', function() { + return function(scope, elm, attr) { + spies.push(jasmine.createSpy('observer ' + spies.length)); + attr.$observe('some', spies[spies.length - 1]); + }; + }); + }); + + inject(function($compile, $rootScope) { + element = $compile('<div><div ng-repeat="i in items">'+ + '<span some="id_{{i.id}}" observer></span>'+ + '</div></div>')($rootScope); + + $rootScope.$apply(function() { + $rootScope.items = [{id: 1}, {id: 2}]; + }); + + expect(spies[0]).toHaveBeenCalledOnceWith('id_1'); + expect(spies[1]).toHaveBeenCalledOnceWith('id_2'); + spies[0].reset(); + spies[1].reset(); + + $rootScope.$apply(function() { + $rootScope.items[0].id = 5; + }); + + expect(spies[0]).toHaveBeenCalledOnceWith('id_5'); + }); + }); + + describe('$set', function() { var attr; beforeEach(function(){ |
