mirror of
https://github.com/zhigang1992/angular.js.git
synced 2026-01-12 22:45:52 +08:00
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
This commit is contained in:
committed by
Caitlin Potter
parent
9ad6c77568
commit
40bbc98178
@@ -164,7 +164,9 @@
|
||||
* value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected
|
||||
* in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent
|
||||
* scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You
|
||||
* can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional.
|
||||
* can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional. If
|
||||
* you want to shallow watch for changes (i.e. $watchCollection instead of $watch) you can use
|
||||
* `=*` or `=*attr` (`=*?` or `=*?attr` if the property is optional).
|
||||
*
|
||||
* * `&` 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
|
||||
@@ -691,7 +693,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;
|
||||
|
||||
function parseIsolateBindings(scope, directiveName) {
|
||||
var LOCAL_REGEXP = /^\s*([@=&])(\??)\s*(\w*)\s*$/;
|
||||
var LOCAL_REGEXP = /^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/;
|
||||
|
||||
var bindings = {};
|
||||
|
||||
@@ -706,9 +708,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
}
|
||||
|
||||
bindings[scopeName] = {
|
||||
attrName: match[3] || scopeName,
|
||||
mode: match[1],
|
||||
optional: match[2] === '?'
|
||||
mode: match[1][0],
|
||||
collection: match[2] === '*',
|
||||
optional: match[3] === '?',
|
||||
attrName: match[4] || scopeName
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1890,7 +1893,12 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
return lastValue = parentValue;
|
||||
};
|
||||
parentValueWatch.$stateful = true;
|
||||
var unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);
|
||||
var unwatch;
|
||||
if (definition.collection) {
|
||||
unwatch = scope.$watchCollection(attrs[attrName], parentValueWatch);
|
||||
} else {
|
||||
unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);
|
||||
}
|
||||
isolateScope.$on('$destroy', unwatch);
|
||||
break;
|
||||
|
||||
|
||||
@@ -3065,6 +3065,8 @@ describe('$compile', function() {
|
||||
optref: '=?',
|
||||
optrefAlias: '=? optref',
|
||||
optreference: '=?',
|
||||
colref: '=*',
|
||||
colrefAlias: '=* colref',
|
||||
expr: '&',
|
||||
exprAlias: '&expr'
|
||||
},
|
||||
@@ -3562,6 +3564,53 @@ describe('$compile', function() {
|
||||
});
|
||||
|
||||
|
||||
describe('collection object reference', 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 colref="collection | filter:query">');
|
||||
|
||||
expect(componentScope.colref).toEqual($rootScope.collection);
|
||||
expect(componentScope.colrefAlias).toEqual(componentScope.colref);
|
||||
|
||||
$rootScope.query = "Gab";
|
||||
$rootScope.$apply();
|
||||
|
||||
expect(componentScope.colref).toEqual([$rootScope.collection[0]]);
|
||||
expect(componentScope.colrefAlias).toEqual([$rootScope.collection[0]]);
|
||||
}));
|
||||
|
||||
it('should update origin scope when isolate scope changes', inject(function () {
|
||||
$rootScope.collection = [{
|
||||
name: 'Gabriel',
|
||||
value: 18
|
||||
}, {
|
||||
name: 'Tony',
|
||||
value: 91
|
||||
}];
|
||||
|
||||
compile('<div><span my-component colref="collection">');
|
||||
|
||||
var newItem = {
|
||||
name: 'Pablo',
|
||||
value: 10
|
||||
};
|
||||
componentScope.colref.push(newItem);
|
||||
componentScope.$apply();
|
||||
|
||||
expect($rootScope.collection[2]).toEqual(newItem);
|
||||
}));
|
||||
});
|
||||
|
||||
|
||||
describe('executable expression', function() {
|
||||
it('should allow expression execution with locals', inject(function() {
|
||||
compile('<div><span my-component expr="count = count + offset">');
|
||||
|
||||
Reference in New Issue
Block a user