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

Commit 40bbc98

Browse files
gabrielmaldicaitp
authored andcommittedOct 23, 2014
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: '=*' } Closes #9725
1 parent 9ad6c77 commit 40bbc98

File tree

2 files changed

+63
-6
lines changed

2 files changed

+63
-6
lines changed
 

‎src/ng/compile.js

+14-6
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,
710-
mode: match[1],
711-
optional: match[2] === '?'
711+
mode: match[1][0],
712+
collection: match[2] === '*',
713+
optional: match[3] === '?',
714+
attrName: match[4] || scopeName
712715
};
713716
});
714717

@@ -1890,7 +1893,12 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
18901893
return lastValue = parentValue;
18911894
};
18921895
parentValueWatch.$stateful = true;
1893-
var unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);
1896+
var unwatch;
1897+
if (definition.collection) {
1898+
unwatch = scope.$watchCollection(attrs[attrName], parentValueWatch);
1899+
} else {
1900+
unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);
1901+
}
18941902
isolateScope.$on('$destroy', unwatch);
18951903
break;
18961904

‎test/ng/compileSpec.js

+49
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,53 @@ describe('$compile', function() {
35623564
});
35633565

35643566

3567+
describe('collection object reference', function () {
3568+
it('should update isolate scope when origin scope 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+
it('should update origin scope when isolate scope changes', inject(function () {
3592+
$rootScope.collection = [{
3593+
name: 'Gabriel',
3594+
value: 18
3595+
}, {
3596+
name: 'Tony',
3597+
value: 91
3598+
}];
3599+
3600+
compile('<div><span my-component colref="collection">');
3601+
3602+
var newItem = {
3603+
name: 'Pablo',
3604+
value: 10
3605+
};
3606+
componentScope.colref.push(newItem);
3607+
componentScope.$apply();
3608+
3609+
expect($rootScope.collection[2]).toEqual(newItem);
3610+
}));
3611+
});
3612+
3613+
35653614
describe('executable expression', function() {
35663615
it('should allow expression execution with locals', inject(function() {
35673616
compile('<div><span my-component expr="count = count + offset">');

0 commit comments

Comments
 (0)
This repository has been archived.