What is the difference between & vs @ and = in angularJS
I am very new to AngularJS. can anybody explain me the difference among these AngularJS operators: &, @ and =
when isolating scope with proper example.
Solution 1:
@
allows a value defined on the directive attribute to be passed to the directive's isolate scope. The value could be a simple string value (myattr="hello"
) or it could be an AngularJS interpolated string with embedded expressions (myattr="my_{{helloText}}"
). Think of it as "one-way" communication from the parent scope into the child directive. John Lindquist has a series of short screencasts explaining each of these. Screencast on @ is here: https://egghead.io/lessons/angularjs-isolate-scope-attribute-binding
&
allows the directive's isolate scope to pass values into the parent scope for evaluation in the expression defined in the attribute. Note that the directive attribute is implicitly an expression and does not use double curly brace expression syntax. This one is tougher to explain in text. Screencast on & is here: https://egghead.io/lessons/angularjs-isolate-scope-expression-binding
=
sets up a two-way binding expression between the directive's isolate scope and the parent scope. Changes in the child scope are propagated to the parent and vice-versa. Think of = as a combination of @ and &. Screencast on = is here: https://egghead.io/lessons/angularjs-isolate-scope-two-way-binding
And finally here is a screencast that shows all three used together in a single view: https://egghead.io/lessons/angularjs-isolate-scope-review
Solution 2:
I would like to explain the concepts from the perspective of JavaScript prototype inheritance. Hopefully help to understand.
There are three options to define the scope of a directive:
-
scope: false
: Angular default. The directive's scope is exactly the one of its parent scope (parentScope
). -
scope: true
: Angular creates a scope for this directive. The scope prototypically inherits fromparentScope
. -
scope: {...}
: isolated scope is explained below.
Specifying scope: {...}
defines an isolatedScope
. An isolatedScope
does not inherit properties from parentScope
, although isolatedScope.$parent === parentScope
. It is defined through:
app.directive("myDirective", function() {
return {
scope: {
... // defining scope means that 'no inheritance from parent'.
},
}
})
isolatedScope
does not have direct access to parentScope
. But sometimes the directive needs to communicate with the parentScope
. They communicate through @
, =
and &
. The topic about using symbols @
, =
and &
are talking about scenarios using isolatedScope
.
It is usually used for some common components shared by different pages, like Modals. An isolated scope prevents polluting the global scope and is easy to share among pages.
Here is a basic directive: http://jsfiddle.net/7t984sf9/5/. An image to illustrate is:
@
: one-way binding
@
simply passes the property from parentScope
to isolatedScope
. It is called one-way binding
, which means you cannot modify the value of parentScope
properties. If you are familiar with JavaScript inheritance, you can understand these two scenarios easily:
If the binding property is a primitive type, like
interpolatedProp
in the example: you can modifyinterpolatedProp
, butparentProp1
would not be changed. However, if you change the value ofparentProp1
,interpolatedProp
will be overwritten with the new value (when angular $digest).-
If the binding property is some object, like
parentObj
: since the one passed toisolatedScope
is a reference, modifying the value will trigger this error:TypeError: Cannot assign to read only property 'x' of {"x":1,"y":2}
=
: two-way binding
=
is called two-way binding
, which means any modification in childScope
will also update the value in parentScope
, and vice versa. This rule works for both primitives and objects. If you change the binding type of parentObj
to be =
, you will find that you can modify the value of parentObj.x
. A typical example is ngModel
.
&
: function binding
&
allows the directive to call some parentScope
function and pass in some value from the directive. For example, check JSFiddle: & in directive scope.
Define a clickable template in the directive like:
<div ng-click="vm.onCheck({valueFromDirective: vm.value + ' is from the directive'})">
And use the directive like:
<div my-checkbox value="vm.myValue" on-check="vm.myFunction(valueFromDirective)"></div>
The variable valueFromDirective
is passed from the directive to the parent controller through {valueFromDirective: ...
.
Reference: Understanding Scopes
Solution 3:
Not my fiddle, but http://jsfiddle.net/maxisam/QrCXh/ shows the difference. The key piece is:
scope:{
/* NOTE: Normally I would set my attributes and bindings
to be the same name but I wanted to delineate between
parent and isolated scope. */
isolatedAttributeFoo:'@attributeFoo',
isolatedBindingFoo:'=bindingFoo',
isolatedExpressionFoo:'&'
}