mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-17 07:40:22 +00:00
feat($compile): '=?' makes '=' binding optional
If you bind using '=' to a non-existant parent property, the compiler will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception, which is right because the model doesn't exist. This enhancement allow to specify that a binding is optional so it won't complain if the parent property is not defined. In order to mantain backward compability, the new behaviour must be specified using '=?' instead of '='. The local property will be undefined is these cases. Closes #909 Closes #1435
This commit is contained in:
parent
30162b769c
commit
ac899d0da5
3 changed files with 39 additions and 3 deletions
|
|
@ -336,7 +336,9 @@ compiler}. The attributes are:
|
|||
Given `<widget my-attr="parentModel">` and widget definition of
|
||||
`scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the
|
||||
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`.
|
||||
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.
|
||||
|
||||
* `&` 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
|
||||
|
|
|
|||
|
|
@ -768,13 +768,14 @@ function $CompileProvider($provide) {
|
|||
$element = attrs.$$element;
|
||||
|
||||
if (newIsolateScopeDirective) {
|
||||
var LOCAL_REGEXP = /^\s*([@=&])\s*(\w*)\s*$/;
|
||||
var LOCAL_REGEXP = /^\s*([@=&])(\??)\s*(\w*)\s*$/;
|
||||
|
||||
var parentScope = scope.$parent || scope;
|
||||
|
||||
forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {
|
||||
var match = definiton.match(LOCAL_REGEXP) || [],
|
||||
attrName = match[2]|| scopeName,
|
||||
attrName = match[3] || scopeName,
|
||||
optional = (match[2] == '?'),
|
||||
mode = match[1], // @, =, or &
|
||||
lastValue,
|
||||
parentGet, parentSet;
|
||||
|
|
@ -796,6 +797,9 @@ function $CompileProvider($provide) {
|
|||
}
|
||||
|
||||
case '=': {
|
||||
if (optional && !attrs[attrName]) {
|
||||
return;
|
||||
}
|
||||
parentGet = $parse(attrs[attrName]);
|
||||
parentSet = parentGet.assign || function() {
|
||||
// reset the change, or we will throw this exception on every $digest
|
||||
|
|
|
|||
|
|
@ -1857,6 +1857,9 @@ describe('$compile', function() {
|
|||
ref: '=',
|
||||
refAlias: '= ref',
|
||||
reference: '=',
|
||||
optref: '=?',
|
||||
optrefAlias: '=? optref',
|
||||
optreference: '=?',
|
||||
expr: '&',
|
||||
exprAlias: '&expr'
|
||||
},
|
||||
|
|
@ -1993,6 +1996,33 @@ describe('$compile', function() {
|
|||
});
|
||||
|
||||
|
||||
describe('optional object reference', function() {
|
||||
it('should update local when origin changes', inject(function() {
|
||||
compile('<div><span my-component optref="name">');
|
||||
expect(componentScope.optRef).toBe(undefined);
|
||||
expect(componentScope.optRefAlias).toBe(componentScope.optRef);
|
||||
|
||||
$rootScope.name = 'misko';
|
||||
$rootScope.$apply();
|
||||
expect(componentScope.optref).toBe($rootScope.name);
|
||||
expect(componentScope.optrefAlias).toBe($rootScope.name);
|
||||
|
||||
$rootScope.name = {};
|
||||
$rootScope.$apply();
|
||||
expect(componentScope.optref).toBe($rootScope.name);
|
||||
expect(componentScope.optrefAlias).toBe($rootScope.name);
|
||||
}));
|
||||
|
||||
it('should not throw exception when reference does not exist', inject(function() {
|
||||
compile('<div><span my-component>');
|
||||
|
||||
expect(componentScope.optref).toBe(undefined);
|
||||
expect(componentScope.optrefAlias).toBe(undefined);
|
||||
expect(componentScope.optreference).toBe(undefined);
|
||||
}));
|
||||
});
|
||||
|
||||
|
||||
describe('executable expression', function() {
|
||||
it('should allow expression execution with locals', inject(function() {
|
||||
compile('<div><span my-component expr="count = count + offset">');
|
||||
|
|
|
|||
Loading…
Reference in a new issue