189
189
* equality check is done by value (using the {@link angular.equals} function). It's also possible
190
190
* to watch the evaluated value shallowly with {@link ng.$rootScope.Scope#$watchCollection
191
191
* `$watchCollection`}: use `=*` or `=*attr` (`=*?` or `=*?attr` if the attribute is optional).
192
+ *
193
+ * * `<` or `<attr` - set up a one-way (one-directional) binding between a local scope property and an
194
+ * expression passed via the attribute `attr`. The expression is evaluated in the context of the
195
+ * parent scope. If no `attr` name is specified then the attribute name is assumed to be the same as the
196
+ * local name. You can also make the binding optional by adding `?`: `<?` or `<?attr`.
197
+ *
198
+ * For example, given `<my-component my-attr="parentModel">` and directive definition of
199
+ * `scope: { localModel:'<myAttr' }`, then the isolated scope property `localModel` will reflect the
200
+ * value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected
201
+ * in `localModel`, but changes in `localModel` will not reflect in `parentModel`. There are however
202
+ * two caveats:
203
+ * 1. one-way binding does not copy the value from the parent to the isolate scope, it simply
204
+ * sets the same value. That means if your bound value is an object, changes to its properties
205
+ * in the isolated scope will be reflected in the parent scope (because both reference the same object).
206
+ * 2. one-way binding watches changes to the **identity** of the parent value. That means the
207
+ * {@link ng.$rootScope.Scope#$watch `$watch`} on the parent value only fires if the reference
208
+ * to the value has changed. In most cases, this should not be of concern, but can be important
209
+ * to know if you one-way bind to an object, and then replace that object in the isolated scope.
210
+ * If you now change a property of the object in your parent scope, the change will not be
211
+ * propagated to the isolated scope, because the identity of the object on the parent scope
212
+ * has not changed. Instead you must assign a new object.
213
+ *
214
+ * One-way binding is useful if you do not plan to propagate changes to your isolated scope bindings
215
+ * back to the parent. However, it does not make this completely impossible.
192
216
*
193
217
* * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope. If
194
218
* no `attr` name is specified then the attribute name is assumed to be the same as the local name.
@@ -829,7 +853,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
829
853
var EVENT_HANDLER_ATTR_REGEXP = / ^ ( o n [ a - z ] + | f o r m a c t i o n ) $ / ;
830
854
831
855
function parseIsolateBindings ( scope , directiveName , isController ) {
832
- var LOCAL_REGEXP = / ^ \s * ( [ @ & ] | = ( \* ? ) ) ( \? ? ) \s * ( \w * ) \s * $ / ;
856
+ var LOCAL_REGEXP = / ^ \s * ( [ @ & < ] | = ( \* ? ) ) ( \? ? ) \s * ( \w * ) \s * $ / ;
833
857
834
858
var bindings = { } ;
835
859
@@ -2965,7 +2989,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
2965
2989
optional = definition . optional ,
2966
2990
mode = definition . mode , // @, =, or &
2967
2991
lastValue ,
2968
- parentGet , parentSet , compare ;
2992
+ parentGet , parentSet , compare , removeWatch ;
2969
2993
2970
2994
switch ( mode ) {
2971
2995
@@ -3026,7 +3050,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
3026
3050
return lastValue = parentValue ;
3027
3051
} ;
3028
3052
parentValueWatch . $stateful = true ;
3029
- var removeWatch ;
3030
3053
if ( definition . collection ) {
3031
3054
removeWatch = scope . $watchCollection ( attrs [ attrName ] , parentValueWatch ) ;
3032
3055
} else {
@@ -3035,6 +3058,24 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
3035
3058
removeWatchCollection . push ( removeWatch ) ;
3036
3059
break ;
3037
3060
3061
+ case '<' :
3062
+ if ( ! hasOwnProperty . call ( attrs , attrName ) ) {
3063
+ if ( optional ) break ;
3064
+ attrs [ attrName ] = void 0 ;
3065
+ }
3066
+ if ( optional && ! attrs [ attrName ] ) break ;
3067
+
3068
+ parentGet = $parse ( attrs [ attrName ] ) ;
3069
+
3070
+ destination [ scopeName ] = parentGet ( scope ) ;
3071
+
3072
+ removeWatch = scope . $watch ( parentGet , function parentValueWatchAction ( newParentValue ) {
3073
+ destination [ scopeName ] = newParentValue ;
3074
+ } , parentGet . literal ) ;
3075
+
3076
+ removeWatchCollection . push ( removeWatch ) ;
3077
+ break ;
3078
+
3038
3079
case '&' :
3039
3080
// Don't assign Object.prototype method to scope
3040
3081
parentGet = attrs . hasOwnProperty ( attrName ) ? $parse ( attrs [ attrName ] ) : noop ;
0 commit comments