186
186
* you want to shallow watch for changes (i.e. $watchCollection instead of $watch) you can use
187
187
* `=*` or `=*attr` (`=*?` or `=*?attr` if the property is optional).
188
188
*
189
+ * * `<` or `<attr` - set up one-way (one-directional) binding between a local scope property and the
190
+ * parent scope property of name defined via the value of the `attr` attribute. If no `attr`
191
+ * name is specified then the attribute name is assumed to be the same as the local name.
192
+ * Given `<dir my-attr="parentModel">` and directive definition of
193
+ * `scope: { localModel:'<myAttr' }`, then isolate scope property `localModel` will reflect the
194
+ * value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected
195
+ * in `localModel`, but changes in `localModel` will not reflect in `parentModel`. There are however
196
+ * two caveats:
197
+ * 1. one-way binding does not copy the value from the parent to the isolate scope, it simply
198
+ * sets the same value. That means if your bound value is an object, changes to its properties
199
+ * in the isolate scope will be reflected in the parent scope.
200
+ * 2. one-way binding watches changes to the **identity** of the parent value. That is important should
201
+ * you one-way bind an object, and then replace that object in the isolated scope. If you now change
202
+ * a property of the object in your parent scope, the change will not be propagated to the isolated
203
+ * scope, because the identity of the object has not changed. Instead you must assign a new object.
204
+ *
205
+ * One-way binding is useful if you do not plan to propagate changes to your isolated scope bindings
206
+ * back to the parent. However, it does not make this completely impossible.
207
+ *
208
+ * Same as with bi-directional bindings, you can also use shallow watch for changes (i.e. $watchCollection instead of $watch):
209
+ * `<*` or `<*attr` (`<*?` or `<*?attr` if the property is optional).
210
+ *
189
211
* * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope.
190
212
* If no `attr` name is specified then the attribute name is assumed to be the same as the
191
213
* local name. Given `<widget my-attr="count = count + value">` and widget definition of
@@ -826,7 +848,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
826
848
var EVENT_HANDLER_ATTR_REGEXP = / ^ ( o n [ a - z ] + | f o r m a c t i o n ) $ / ;
827
849
828
850
function parseIsolateBindings ( scope , directiveName , isController ) {
829
- var LOCAL_REGEXP = / ^ \s * ( [ @ & ] | = ( \* ? ) ) ( \? ? ) \s * ( \w * ) \s * $ / ;
851
+ var LOCAL_REGEXP = / ^ \s * ( [ @ & ] | [ = < ] ( \* ? ) ) ( \? ? ) \s * ( \w * ) \s * $ / ;
830
852
831
853
var bindings = { } ;
832
854
@@ -2962,7 +2984,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
2962
2984
optional = definition . optional ,
2963
2985
mode = definition . mode , // @, =, or &
2964
2986
lastValue ,
2965
- parentGet , parentSet , compare ;
2987
+ parentGet , parentSet , compare , removeWatch ;
2966
2988
2967
2989
switch ( mode ) {
2968
2990
@@ -3023,7 +3045,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
3023
3045
return lastValue = parentValue ;
3024
3046
} ;
3025
3047
parentValueWatch . $stateful = true ;
3026
- var removeWatch ;
3027
3048
if ( definition . collection ) {
3028
3049
removeWatch = scope . $watchCollection ( attrs [ attrName ] , parentValueWatch ) ;
3029
3050
} else {
@@ -3032,6 +3053,29 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
3032
3053
removeWatchCollection . push ( removeWatch ) ;
3033
3054
break ;
3034
3055
3056
+ case '<' :
3057
+ if ( ! hasOwnProperty . call ( attrs , attrName ) ) {
3058
+ if ( optional ) break ;
3059
+ attrs [ attrName ] = void 0 ;
3060
+ }
3061
+ if ( optional && ! attrs [ attrName ] ) break ;
3062
+
3063
+ parentGet = $parse ( attrs [ attrName ] ) ;
3064
+
3065
+ destination [ scopeName ] = parentGet ( scope ) ;
3066
+
3067
+ if ( definition . collection ) {
3068
+ removeWatch = scope . $watchCollection ( attrs [ attrName ] , function onParentCollectionValueChange ( newParentValue ) {
3069
+ destination [ scopeName ] = newParentValue ;
3070
+ } ) ;
3071
+ } else {
3072
+ removeWatch = scope . $watch ( attrs [ attrName ] , function onParentValueChange ( newParentValue ) {
3073
+ destination [ scopeName ] = newParentValue ;
3074
+ } ) ;
3075
+ }
3076
+ removeWatchCollection . push ( removeWatch ) ;
3077
+ break ;
3078
+
3035
3079
case '&' :
3036
3080
// Don't assign Object.prototype method to scope
3037
3081
parentGet = attrs . hasOwnProperty ( attrName ) ? $parse ( attrs [ attrName ] ) : noop ;
0 commit comments