1

I'm trying to learn AngularJS, but there's one thing I can't wrap my head around.

What is the benefit of using "&" over "="? All the tutorials, demonstrations and documentation I've found tell me that & evaluates the expression in the parent scope. However, when I first tried doing callbacks to my controller from my directive, I just used a = binding to a function on the parent scope, and it worked fine.

For example, with a function on the controller's scope foo that takes a parameter bar, I could do a directive declaration like

scope: { callback: '=' },
template: '<div ng-click="callback(value)"></div>'

and include the directive like

<my-directive callback="foo"></my-directive>

To achieve the same with &, it seems like I have to do

scope: { callback: '&' },
template: '<div ng-click="callback({bar:value})"></div>'

and

<my-directive callback="foo(bar)"></my-directive>

From this, I don't really see the advantage. Have I misunderstood &?

EDIT: I suppose a valid addition to my question is: Is it a bad idea to bind to parent scope functions using = instead of &?

2
  • Is the capability to execute an expression against the parent's context a benefit for you? see my answer below. Commented Sep 12, 2014 at 13:04
  • added update, with an example of a beneficial scenario. Commented Sep 12, 2014 at 13:12

4 Answers 4

1

The difference it seems is that with the & binding, the user of the directive fixes what function is called on a parent scope and which parameters are used, while an = binding simply means passing a reference function reference which the directive can call with whatever arguments.

= isn't meant for that though, it exists mainly for synchronizing properties between nested scopes, while & is meant give the directive a way to interact with the 'outside' world without having knowledge about the outside world.

example of both

<div ng-app="app" ng-controller="ParentCtrl as parentCtrl">
    <bind-dir func-is="parentCtrl.func" func-and="parentCtrl.func(arg)"></bind-dir>
</div>
var app = angular.module('app', []);

app.controller('ParentCtrl', function () {
    this.func = function (arg) {
        alert(arg);
    }
})

app.directive('bindDir', function () {
    return {
        scope: {
            funcIs: '=',
            funcAnd: '&'
        },
        template: '<button ng-click="funcIs(\'=\')">=</button><button ng-click="funcAnd({arg:\'&\'})">&amp;</button>'
    }
});
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, with the added example this makes it much clearer.
0

Official docs.

@ or @attr - bind a local scope property to the value of DOM attribute. The result is always a string since DOM attributes are strings.


= or =attr - set up bi-directional binding between a local scope property and the parent scope property of name defined via the value of the attr attribute.


& or &attr - provides a way to execute an expression in the context of the parent scope.


Further reading: Understanding-Scopes.

Comments

0

'=' gives two way data binding. This means that if you alter the value of the expression within the directive it also alters in the controller. This is called polluting the controller.

'&' is nicer and more modular. You can pass in the function and it will be executed in the scope of the controller but you are unable to change the function in the controller scope.

Please see http://jsfiddle.net/b6ww0rx8/ and it will be a bit clearer.

<div ng-app="myApp">
    <div ng-controller="MyController">
        <div my-directive
            callback1="aFunction"
            callback2="anotherFunction()">

            </div>
        <button ng-click="test()">click me</button>
    </div>
</div>

angular.module('myApp', [])

.controller('MyController', function($scope) {

    $scope.aFunction = function() {
        console.log('abc');
    };
    $scope.anotherFunction = function() {
        console.log('def');
    };
    $scope.test = function () {
        console.log($scope.aFunction);
        console.log($scope.anotherFunction);

    };
    console.log($scope.aFunction);
    console.log($scope.anotherFunction);
})

.directive('myDirective', function(){
    return {
        scope: {
            callback1: '=',
            callback2: '&'
        },
        link: function (scope, element, attrs) {
            scope.callback1 = 123;
            scope.callback1 = 456;
        }
    }
}); 

Comments

0

Is the capability to execute an expression against the parent's context a benefit for you? The first example below executes myLocalModel as a function, unlike the '=', you get the result already.

template: "{{ myLocalModel() }}"

begin added update 01

example, you might have 2 attributes with expression, and you only want to execute either one depending on a condition. that could save execution time. is it beneficial for you?

end update 01

the '&'

, Execute expression against a parent's context. http://ngtutorial.com/learn/directive.html#/exec-expr

angular.module("myApp", []).directive("myCustom", function(){
  return {
    restrict: 'EA',
    scope: {
        myLocalModel: '&theElementsAttrName',
    },
    // note that myLocalModel is a function
    template: "{{ myLocalModel() }}"
  };
});
........

<body ng-app="myApp">

<div ng-init="ParentModel='the parents value';
              ParentNum1=100;
              ParentNum2=200"></div>

    <div ng-controller="CreateChildScopeController">
        my-custom 1) <my-custom the-elements-attr-name="ParentModel + ' ---> adding more'"></my-custom><br/>
        my-custom 2) <my-custom the-elements-attr-name="ParentNum1 + 12"></my-custom><br/>
    </div>

    my-custom 3) <my-custom the-elements-attr-name="ParentNum2 + 12"></my-custom><br/>

</body>


.... output

my-custom 1) the parents value ---> adding more
my-custom 2) 112
my-custom 3) 212

the '='

,Sync with existing model. http://ngtutorial.com/learn/directive.html#/sync-existing

angular.module("myApp", []).directive("myCustom", function(){
  return {
    restrict: 'EA',
    scope: {
        myLocalModel: '=theElementsAttrName',
    },
    template: "{{ myLocalModel }}"
  };
});

.....

<body ng-app="myApp">

<div ng-init="ParentModel='the parents value';
              ParentNum1=100;
              ParentNum2=200"></div>

    <div ng-controller="CreateChildScopeController">
        my-custom 1) <my-custom the-elements-attr-name="ParentModel"></my-custom><br/>
        my-custom 2) <my-custom the-elements-attr-name="ParentNum1"></my-custom><br/>
    </div>

    my-custom 3) <my-custom the-elements-attr-name="ParentNum2"></my-custom><br/>

</body>

..... output

my-custom 1) the parents value
my-custom 2) 100
my-custom 3) 200

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.