Monojit Sarkar Monojit Sarkar - 5 months ago 27
AngularJS Question

AngularJS Directive and one way data binding

i was reading an article on directive isolated scope from here https://blog.umur.io/2013/07/02/angularjs-directives-using-isolated-scope-with-attributes/

here is the code



<div ng-app="myApp" ng-controller="myController">
<div my-directive
my-text="hello {{ bar }}"
my-two-way-bind="foo"
my-one-way-bind="bar"></div>
</div>


angular.module("myApp",[])
.directive("myDirective", function () {
return {
restrict: "A",
scope: {
text: "@myText",
twoWayBind: "=myTwoWayBind",
oneWayBind: "&myOneWayBind"
},
template: 'text: {{text}} twoWayBind: {{twoWayBind}} oneWayBind: {{oneWayBind}}',
link: function (scope, element, attr) {
alert(scope.oneWayBind());
}
};
}).controller("myController", function ($scope) {
$scope.foo = {name: "Manoj"};
$scope.bar = "qwe";
});


i understand the above code and code is running but one thing is not clear that when i try to access oneWayBind variable of isolated scope from link function this way like
alert(scope.oneWayBind)
then it does not work and got no value but when i try to access like function
alert(scope.oneWayBind())
then it works.....do not understand why?

other scope variable works when i try to access like
alert(scope.text) or alert(scope.twoWayBind)
these all are working without function like access but why we have to access oneWayBind variable of isolated scope like function.

please some one help me to understand. jsfiddle https://jsfiddle.net/tridip/v3c7gyen/1/

Answer

The reason you have to access the "one-way binding" in this way is because & denotes that the attribute expects an expression. The variable scope.oneWayBind is ALWAYS set to a function (even if you don't set the attribute to anything in your html code) that when called, evaluates the expression passed into that attribute. You showed that it can be called like this to get the value

scope.oneWayBind()

whereas this

scope.oneWayBind

will just return a reference to the function wrapping the expression passed in.

For reference: https://docs.angularjs.org/api/ng/service/$compile#-scope-

& or &attr - ... Given <my-component my-attr="count = count + value"> and the isolate scope definition scope: { localFn:'&myAttr' }, the isolate scope property localFn will point to a function wrapper for the count = count + value expression...


You can also do this with & properties:

scope.oneWayBind({someProperty: 'someValue'})

which will cause someProperty to be locally available to the expression passed to one-way-bind. In other words, one-way-bind="method(someProperty)" will cause scope.oneWayBind({someProperty: 'someValue'}) to actually do method('someValue').

This is documented in the same section of that angular docs page:

Often it's desirable to pass data from the isolated scope via an expression to the parent scope. This can be done by passing a map of local variable names and values into the expression wrapper fn. For example, if the expression is increment(amount) then we can specify the amount value by calling the localFn as localFn({amount: 22}).

Comments