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

Commit 507cf31

Browse files
thorn0gkalpak
authored andcommitted
docs($compile): refine explanation of isolate scope =-binding
The current version of this paragraph is in many ways inaccurate and confusing. Closes #13921
1 parent 9141491 commit 507cf31

File tree

1 file changed

+32
-29
lines changed

1 file changed

+32
-29
lines changed

src/ng/compile.js

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -166,35 +166,38 @@
166166
* is bound to the parent scope, via matching attributes on the directive's element:
167167
*
168168
* * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is
169-
* always a string since DOM attributes are strings. If no `attr` name is specified then the
170-
* attribute name is assumed to be the same as the local name.
171-
* Given `<widget my-attr="hello {{name}}">` and widget definition
172-
* of `scope: { localName:'@myAttr' }`, then widget scope property `localName` will reflect
173-
* the interpolated value of `hello {{name}}`. As the `name` attribute changes so will the
174-
* `localName` property on the widget scope. The `name` is read from the parent scope (not
175-
* component scope).
176-
*
177-
* * `=` or `=attr` - set up bi-directional binding between a local scope property and the
178-
* parent scope property of name defined via the value of the `attr` attribute. If no `attr`
179-
* name is specified then the attribute name is assumed to be the same as the local name.
180-
* Given `<widget my-attr="parentModel">` and widget definition of
181-
* `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the
182-
* value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected
183-
* in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent
184-
* scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You
185-
* can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional. If
186-
* you want to shallow watch for changes (i.e. $watchCollection instead of $watch) you can use
187-
* `=*` or `=*attr` (`=*?` or `=*?attr` if the property is optional).
188-
*
189-
* * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope.
190-
* If no `attr` name is specified then the attribute name is assumed to be the same as the
191-
* local name. Given `<widget my-attr="count = count + value">` and widget definition of
192-
* `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to
193-
* a function wrapper for the `count = count + value` expression. Often it's desirable to
194-
* pass data from the isolated scope via an expression to the parent scope, this can be
195-
* done by passing a map of local variable names and values into the expression wrapper fn.
196-
* For example, if the expression is `increment(amount)` then we can specify the amount value
197-
* by calling the `localFn` as `localFn({amount: 22})`.
169+
* always a string since DOM attributes are strings. If no `attr` name is specified then the
170+
* attribute name is assumed to be the same as the local name. Given `<my-component
171+
* my-attr="hello {{name}}">` and the isolate scope definition `scope: { localName:'@myAttr' }`,
172+
* the directive's scope property `localName` will reflect the interpolated value of `hello
173+
* {{name}}`. As the `name` attribute changes so will the `localName` property on the directive's
174+
* scope. The `name` is read from the parent scope (not the directive's scope).
175+
*
176+
* * `=` or `=attr` - set up a bidirectional binding between a local scope property and an expression
177+
* passed via the attribute `attr`. The expression is evaluated in the context of the parent scope.
178+
* If no `attr` name is specified then the attribute name is assumed to be the same as the local
179+
* name. Given `<my-component my-attr="parentModel">` and the isolate scope definition `scope: {
180+
* localModel: '=myAttr' }`, the property `localModel` on the directive's scope will reflect the
181+
* value of `parentModel` on the parent scope. Changes to `parentModel` will be reflected in
182+
* `localModel` and vice versa. Optional attributes should be marked as such with a question mark:
183+
* `=?` or `=?attr`. If the binding expression is non-assignable, or if the attribute isn't
184+
* optional and doesn't exist, an exception ({@link error/$compile/nonassign `$compile:nonassign`})
185+
* will be thrown upon discovering changes to the local value, since it will be impossible to sync
186+
* them back to the parent scope. By default, the {@link ng.$rootScope.Scope#$watch `$watch`}
187+
* method is used for tracking changes, and the equality check is based on object identity.
188+
* However, if an object literal or an array literal is passed as the binding expression, the
189+
* equality check is done by value (using the {@link angular.equals} function). It's also possible
190+
* to watch the evaluated value shallowly with {@link ng.$rootScope.Scope#$watchCollection
191+
* `$watchCollection`}: use `=*` or `=*attr` (`=*?` or `=*?attr` if the attribute is optional).
192+
*
193+
* * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope. If
194+
* no `attr` name is specified then the attribute name is assumed to be the same as the local name.
195+
* Given `<my-component my-attr="count = count + value">` and the isolate scope definition `scope: {
196+
* localFn:'&myAttr' }`, the isolate scope property `localFn` will point to a function wrapper for
197+
* the `count = count + value` expression. Often it's desirable to pass data from the isolated scope
198+
* via an expression to the parent scope. This can be done by passing a map of local variable names
199+
* and values into the expression wrapper fn. For example, if the expression is `increment(amount)`
200+
* then we can specify the amount value by calling the `localFn` as `localFn({amount: 22})`.
198201
*
199202
* In general it's possible to apply more than one directive to one element, but there might be limitations
200203
* depending on the type of scope required by the directives. The following points will help explain these limitations.

0 commit comments

Comments
 (0)