aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVojta Jina2012-03-28 13:47:57 -0700
committerIgor Minar2012-03-29 07:30:32 -0700
commitf2106692b1ebf00aa5f8b2accd75f014b6cd4faa (patch)
tree1a8c97e04014c559da4e7cc6877dbe34ce7d6783
parent4557881cf84f168855fc8615e174f24d6c2dd6ce (diff)
downloadangular.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.js1
-rw-r--r--src/ng/directive/booleanAttrDirs.js6
-rw-r--r--test/ng/compilerSpec.js35
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(){