Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit d348a38

Browse files
feat($compile): allow $watchCollection to be used in bi-directional bindings
an asterisk can be specified in the binding definition to use $watchCollection instead of $watch. e.g. scope: { prop: '=*' }
1 parent 89c57a8 commit d348a38

File tree

2 files changed

+38
-5
lines changed

2 files changed

+38
-5
lines changed

src/ng/compile.js

+10-5
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,9 @@
164164
* value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected
165165
* in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent
166166
* scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You
167-
* can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional.
167+
* can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional. If
168+
* you want to shallow watch for changes (i.e. $watchCollection instead of $watch) you can use
169+
* `=*` or `=*attr` (`=?*` or `=?*attr` if the property is optional).
168170
*
169171
* * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope.
170172
* If no `attr` name is specified then the attribute name is assumed to be the same as the
@@ -691,7 +693,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
691693
var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;
692694

693695
function parseIsolateBindings(scope, directiveName) {
694-
var LOCAL_REGEXP = /^\s*([@=&])(\??)\s*(\w*)\s*$/;
696+
var LOCAL_REGEXP = /^\s*([@=&])(\??)(\*?)\s*(\w*)\s*$/;
695697

696698
var bindings = {};
697699

@@ -706,9 +708,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
706708
}
707709

708710
bindings[scopeName] = {
709-
attrName: match[3] || scopeName,
711+
attrName: match[4] || scopeName,
710712
mode: match[1],
711-
optional: match[2] === '?'
713+
optional: match[2] === '?',
714+
collection: match[3] == '*'
712715
};
713716
});
714717

@@ -1894,7 +1897,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
18941897
return lastValue = parentValue;
18951898
};
18961899
parentValueWatch.$stateful = true;
1897-
var unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);
1900+
var unwatch = !definition.collection
1901+
? scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal)
1902+
: scope.$watchCollection(attrs[attrName], parentValueWatch);
18981903
isolateScope.$on('$destroy', unwatch);
18991904
break;
19001905

test/ng/compileSpec.js

+28
Original file line numberDiff line numberDiff line change
@@ -3065,6 +3065,8 @@ describe('$compile', function() {
30653065
optref: '=?',
30663066
optrefAlias: '=? optref',
30673067
optreference: '=?',
3068+
colref: '=*',
3069+
colrefAlias: '=* colref',
30683070
expr: '&',
30693071
exprAlias: '&expr'
30703072
},
@@ -3562,6 +3564,32 @@ describe('$compile', function() {
35623564
});
35633565

35643566

3567+
describe('collection object reference', function() {
3568+
it('should update local when origin changes', inject(function() {
3569+
$rootScope.collection = [{
3570+
name: 'Gabriel',
3571+
value: 18
3572+
}, {
3573+
name: 'Tony',
3574+
value: 91
3575+
}];
3576+
$rootScope.query = "";
3577+
$rootScope.$apply();
3578+
3579+
compile('<div><span my-component colref="collection | filter:query">');
3580+
3581+
expect(componentScope.colref).toEqual($rootScope.collection);
3582+
expect(componentScope.colrefAlias).toEqual(componentScope.colref);
3583+
3584+
$rootScope.query = "Gab";
3585+
$rootScope.$apply();
3586+
3587+
expect(componentScope.colref).toEqual([$rootScope.collection[0]]);
3588+
expect(componentScope.colrefAlias).toEqual([$rootScope.collection[0]]);
3589+
}));
3590+
});
3591+
3592+
35653593
describe('executable expression', function() {
35663594
it('should allow expression execution with locals', inject(function() {
35673595
compile('<div><span my-component expr="count = count + offset">');

0 commit comments

Comments
 (0)