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.
This commit is contained in:
Vojta Jina 2012-03-28 13:47:57 -07:00 committed by Igor Minar
parent 4557881cf8
commit f2106692b1
3 changed files with 40 additions and 2 deletions

View file

@ -611,6 +611,7 @@ function $CompileProvider($provide) {
} else {
attrs = shallowCopy(templateAttrs);
attrs.$element = jqLite(linkNode);
attrs.$observers = {};
}
element = attrs.$element;

View file

@ -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);
});

View file

@ -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(){