feat($compile): add one-way collection bindings
Closes #14039 Closes #16553 Closes #15874
This commit is contained in:
committed by
Martin Staffa
parent
f6e189dde0
commit
f9d1ca20c3
+7
-2
@@ -339,6 +339,11 @@
|
||||
* One-way binding is useful if you do not plan to propagate changes to your isolated scope bindings
|
||||
* back to the parent. However, it does not make this completely impossible.
|
||||
*
|
||||
* By default, the {@link ng.$rootScope.Scope#$watch `$watch`}
|
||||
* method is used for tracking changes, and the equality check is based on object identity.
|
||||
* It's also possible to watch the evaluated value shallowly with
|
||||
* {@link ng.$rootScope.Scope#$watchCollection `$watchCollection`}: use `<*` or `<*attr`
|
||||
*
|
||||
* * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope. If
|
||||
* no `attr` name is specified then the attribute name is assumed to be the same as the local name.
|
||||
* Given `<my-component my-attr="count = count + value">` and the isolate scope definition `scope: {
|
||||
@@ -1068,7 +1073,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
var bindingCache = createMap();
|
||||
|
||||
function parseIsolateBindings(scope, directiveName, isController) {
|
||||
var LOCAL_REGEXP = /^([@&<]|=(\*?))(\??)\s*([\w$]*)$/;
|
||||
var LOCAL_REGEXP = /^([@&]|[=<](\*?))(\??)\s*([\w$]*)$/;
|
||||
|
||||
var bindings = createMap();
|
||||
|
||||
@@ -3615,7 +3620,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
var initialValue = destination[scopeName] = parentGet(scope);
|
||||
initialChanges[scopeName] = new SimpleChange(_UNINITIALIZED_VALUE, destination[scopeName]);
|
||||
|
||||
removeWatch = scope.$watch(parentGet, function parentValueWatchAction(newValue, oldValue) {
|
||||
removeWatch = scope[definition.collection ? '$watchCollection' : '$watch'](parentGet, function parentValueWatchAction(newValue, oldValue) {
|
||||
if (oldValue === newValue) {
|
||||
if (oldValue === initialValue || (isLiteral && equals(oldValue, initialValue))) {
|
||||
return;
|
||||
|
||||
@@ -5148,6 +5148,9 @@ describe('$compile', function() {
|
||||
owOptref: '<?',
|
||||
owOptrefAlias: '<? owOptref',
|
||||
$owOptrefAlias: '<? $owOptref$',
|
||||
owColref: '<*',
|
||||
owColrefAlias: '<* owColref',
|
||||
$owColrefAlias: '<* $owColref$',
|
||||
expr: '&',
|
||||
optExpr: '&?',
|
||||
exprAlias: '&expr',
|
||||
@@ -6327,6 +6330,112 @@ describe('$compile', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('one-way collection bindings', function() {
|
||||
it('should update isolate scope when origin scope changes', inject(function() {
|
||||
$rootScope.collection = [{
|
||||
name: 'Gabriel',
|
||||
value: 18
|
||||
}, {
|
||||
name: 'Tony',
|
||||
value: 91
|
||||
}];
|
||||
$rootScope.query = '';
|
||||
$rootScope.$apply();
|
||||
|
||||
compile('<div><span my-component ow-colref="collection | filter:query" $ow-colref$="collection | filter:query">');
|
||||
|
||||
expect(componentScope.owColref).toEqual($rootScope.collection);
|
||||
expect(componentScope.owColrefAlias).toEqual(componentScope.owColref);
|
||||
expect(componentScope.$owColrefAlias).toEqual(componentScope.owColref);
|
||||
|
||||
$rootScope.query = 'Gab';
|
||||
$rootScope.$apply();
|
||||
|
||||
expect(componentScope.owColref).toEqual([$rootScope.collection[0]]);
|
||||
expect(componentScope.owColrefAlias).toEqual([$rootScope.collection[0]]);
|
||||
expect(componentScope.$owColrefAlias).toEqual([$rootScope.collection[0]]);
|
||||
}));
|
||||
|
||||
it('should not update isolate scope when deep state within origin scope changes', inject(function() {
|
||||
$rootScope.collection = [{
|
||||
name: 'Gabriel',
|
||||
value: 18
|
||||
}, {
|
||||
name: 'Tony',
|
||||
value: 91
|
||||
}];
|
||||
$rootScope.$apply();
|
||||
|
||||
compile('<div><span my-component ow-colref="collection" $ow-colref$="collection">');
|
||||
|
||||
expect(componentScope.owColref).toEqual($rootScope.collection);
|
||||
expect(componentScope.owColrefAlias).toEqual(componentScope.owColref);
|
||||
expect(componentScope.$owColrefAlias).toEqual(componentScope.owColref);
|
||||
|
||||
componentScope.owColref = componentScope.owColrefAlias = componentScope.$owColrefAlias = undefined;
|
||||
$rootScope.collection[0].name = 'Joe';
|
||||
$rootScope.$apply();
|
||||
|
||||
expect(componentScope.owColref).toBeUndefined();
|
||||
expect(componentScope.owColrefAlias).toBeUndefined();
|
||||
expect(componentScope.$owColrefAlias).toBeUndefined();
|
||||
}));
|
||||
|
||||
it('should update isolate scope when origin scope changes', inject(function() {
|
||||
$rootScope.gab = {
|
||||
name: 'Gabriel',
|
||||
value: 18
|
||||
};
|
||||
$rootScope.tony = {
|
||||
name: 'Tony',
|
||||
value: 91
|
||||
};
|
||||
$rootScope.query = '';
|
||||
$rootScope.$apply();
|
||||
|
||||
compile('<div><span my-component ow-colref="[gab, tony] | filter:query" $ow-colref$="[gab, tony] | filter:query">');
|
||||
|
||||
expect(componentScope.owColref).toEqual([$rootScope.gab, $rootScope.tony]);
|
||||
expect(componentScope.owColrefAlias).toEqual([$rootScope.gab, $rootScope.tony]);
|
||||
expect(componentScope.$owColrefAlias).toEqual([$rootScope.gab, $rootScope.tony]);
|
||||
|
||||
$rootScope.query = 'Gab';
|
||||
$rootScope.$apply();
|
||||
|
||||
expect(componentScope.owColref).toEqual([$rootScope.gab]);
|
||||
expect(componentScope.owColrefAlias).toEqual([$rootScope.gab]);
|
||||
expect(componentScope.$owColrefAlias).toEqual([$rootScope.gab]);
|
||||
}));
|
||||
|
||||
it('should update isolate scope when origin literal object content changes', inject(function() {
|
||||
$rootScope.gab = {
|
||||
name: 'Gabriel',
|
||||
value: 18
|
||||
};
|
||||
$rootScope.tony = {
|
||||
name: 'Tony',
|
||||
value: 91
|
||||
};
|
||||
$rootScope.$apply();
|
||||
|
||||
compile('<div><span my-component ow-colref="[gab, tony]" $ow-colref$="[gab, tony]">');
|
||||
|
||||
expect(componentScope.owColref).toEqual([$rootScope.gab, $rootScope.tony]);
|
||||
expect(componentScope.owColrefAlias).toEqual([$rootScope.gab, $rootScope.tony]);
|
||||
expect(componentScope.$owColrefAlias).toEqual([$rootScope.gab, $rootScope.tony]);
|
||||
|
||||
$rootScope.tony = {
|
||||
name: 'Bob',
|
||||
value: 42
|
||||
};
|
||||
$rootScope.$apply();
|
||||
|
||||
expect(componentScope.owColref).toEqual([$rootScope.gab, $rootScope.tony]);
|
||||
expect(componentScope.owColrefAlias).toEqual([$rootScope.gab, $rootScope.tony]);
|
||||
expect(componentScope.$owColrefAlias).toEqual([$rootScope.gab, $rootScope.tony]);
|
||||
}));
|
||||
});
|
||||
|
||||
describe('executable expression', function() {
|
||||
it('should allow expression execution with locals', inject(function() {
|
||||
compile('<div><span my-component expr="count = count + offset" $expr$="count = count + offset">');
|
||||
|
||||
Reference in New Issue
Block a user