mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-16 23:30:23 +00:00
fix($compile): Allow literals in isolate scope references
When a component uses an isolate scope reference and the the component is used with an object literal a new object is created on every evaluation. Therefore the compiler needs to compare the values of the parent and the isolate scope using object equality and not object reference equality. Fixes #5296.
This commit is contained in:
parent
9396d55414
commit
43072e3812
2 changed files with 65 additions and 5 deletions
|
|
@ -1400,7 +1400,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|||
optional = (match[2] == '?'),
|
||||
mode = match[1], // @, =, or &
|
||||
lastValue,
|
||||
parentGet, parentSet;
|
||||
parentGet, parentSet, compare;
|
||||
|
||||
isolateScope.$$isolateBindings[scopeName] = mode + attrName;
|
||||
|
||||
|
|
@ -1423,6 +1423,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|||
return;
|
||||
}
|
||||
parentGet = $parse(attrs[attrName]);
|
||||
if (parentGet.literal) {
|
||||
compare = equals;
|
||||
} else {
|
||||
compare = function(a,b) { return a === b; };
|
||||
}
|
||||
parentSet = parentGet.assign || function() {
|
||||
// reset the change, or we will throw this exception on every $digest
|
||||
lastValue = isolateScope[scopeName] = parentGet(scope);
|
||||
|
|
@ -1433,10 +1438,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|||
lastValue = isolateScope[scopeName] = parentGet(scope);
|
||||
isolateScope.$watch(function parentValueWatch() {
|
||||
var parentValue = parentGet(scope);
|
||||
|
||||
if (parentValue !== isolateScope[scopeName]) {
|
||||
if (!compare(parentValue, isolateScope[scopeName])) {
|
||||
// we are out of sync and need to copy
|
||||
if (parentValue !== lastValue) {
|
||||
if (!compare(parentValue, lastValue)) {
|
||||
// parent changed and it has precedence
|
||||
isolateScope[scopeName] = parentValue;
|
||||
} else {
|
||||
|
|
@ -1445,7 +1449,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|||
}
|
||||
}
|
||||
return lastValue = parentValue;
|
||||
});
|
||||
}, null, parentGet.literal);
|
||||
break;
|
||||
|
||||
case '&':
|
||||
|
|
|
|||
|
|
@ -2492,6 +2492,62 @@ describe('$compile', function() {
|
|||
|
||||
expect(lastRefValueInParent).toBe('new');
|
||||
}));
|
||||
|
||||
describe('literal objects', function() {
|
||||
it('should copy parent changes', inject(function() {
|
||||
compile('<div><span my-component reference="{name: name}">');
|
||||
|
||||
$rootScope.name = 'a';
|
||||
$rootScope.$apply();
|
||||
expect(componentScope.reference).toEqual({name: 'a'});
|
||||
|
||||
$rootScope.name = 'b';
|
||||
$rootScope.$apply();
|
||||
expect(componentScope.reference).toEqual({name: 'b'});
|
||||
}));
|
||||
|
||||
it('should not change the component when parent does not change', inject(function() {
|
||||
compile('<div><span my-component reference="{name: name}">');
|
||||
|
||||
$rootScope.name = 'a';
|
||||
$rootScope.$apply();
|
||||
var lastComponentValue = componentScope.reference;
|
||||
$rootScope.$apply();
|
||||
expect(componentScope.reference).toBe(lastComponentValue);
|
||||
}));
|
||||
|
||||
it('should complain when the component changes', inject(function() {
|
||||
compile('<div><span my-component reference="{name: name}">');
|
||||
|
||||
$rootScope.name = 'a';
|
||||
$rootScope.$apply();
|
||||
componentScope.reference = {name: 'b'};
|
||||
expect(function() {
|
||||
$rootScope.$apply();
|
||||
}).toThrowMinErr("$compile", "nonassign", "Expression '{name: name}' used with directive 'myComponent' is non-assignable!");
|
||||
|
||||
}));
|
||||
|
||||
it('should work for primitive literals', inject(function() {
|
||||
test('1', 1);
|
||||
test('null', null);
|
||||
test('undefined', undefined);
|
||||
test("'someString'", 'someString');
|
||||
|
||||
|
||||
function test(literalString, literalValue) {
|
||||
compile('<div><span my-component reference="'+literalString+'">');
|
||||
|
||||
$rootScope.$apply();
|
||||
expect(componentScope.reference).toBe(literalValue);
|
||||
dealoc(element);
|
||||
|
||||
}
|
||||
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue