Search code examples
angularjsangularjs-directivecustom-directive

How to call a controller function, inside a directive link function using '&' with a parameter?


I'm trying to pass a parameter into a function, inside of a directive link function, similar to this question: Angular: calling controller function inside a directive link function using &

However, while I've seen a few examples, like this one: Passing Parameters from a Directive to a function and I've seen a parameter value get set inside the link inside a directive. Yet, I've not seen any where you are passing a primitive, like a number in as a parameter to the directive which passes that into the controller function.

I've tried multiple things, but haven't figured out the syntax.

HTML CODE:

<!DOCTYPE html>
<html>

  <head>
    <script data-require="[email protected]" data-semver="1.4.2" src="https://code.angularjs.org/1.4.2/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body>
    <div id="app" ng-app="app">
    <div ng-controller="mainCtrl">
          <my-directive ctrl-fn="ctrlFn(count)"></my-directive> 
        </div>
      </div>
  </body>

</html>

SCRIPT.JS

var app = angular.module('app', []);

app.controller("mainCtrl", function($scope) {
  $scope.count = 0;
  $scope.ctrlFn = function() {
      $scope.count = 0;
      console.log('In mainCtrl ctrlFn!');
      $scope.count += count;
     // console.log("count is: " + JSON.stringify($scope.count));
    //Call service here
  };  
})


.directive('myDirective', function() {
  return {
    restrict: 'E',
    scope: {
      'count' : '&',
      'ctrlFn' : '&'
    },
    template: "<div><button ng-click='ctrlFn({count: 10})'>Click Here</button></div>",
    link: function(scope, element, attributes) {
      var count = null;
      scope.ctrlFn = scope.ctrlFn({count: count});
      //scope.text = scope.fn({ count: 0 });
    }
  };
});

My plunker is here: http://plnkr.co/edit/6uDntNeqe0g343PmeCED?p=preview

Can a primitive get passed in as a parameter in this use case? If so, what am I missing here?

Aftermath:

In case someone is looking for this syntax: ctrlFn({count: 10}) in the angularjs docs, it's mentioned here under custom directives:

Often it's desirable to pass data from the isolate 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 function. For example, the hideDialog function takes a message to display when the dialog is hidden. This is specified in the directive by calling close({message: 'closing for now'}). Then the local variable message will be available within the on-close expression.


Solution

  • You've made two mistakes:

    • scope.ctrlFn = scope.ctrlFn({count: count}); - this line overrides passed reference to a function and sets it to be value returned by this function (undefined in this case)

    • to pass count value to your direcive you should use = instead of &

    Below is code of simplified example.

    script.js:

    var app = angular.module('app', []);
    
    app.controller("mainCtrl", function($scope) {
      $scope.count = 0;
      $scope.ctrlFn = function(count) {
          console.log(count)
          console.log('In mainCtrl ctrlFn!', count);
          $scope.count += count;
        //Call service here
      };  
    })
    
    
    .directive('myDirective', function() {
      return {
        restrict: 'E',
        scope: {
          'count' : '=',
          'ctrlFn' : '&'
        },
        template: "<div><button ng-click='ctrlFn({ count: 100 })'>Click Here</button></div>"
      };
    })
    

    index.html:

    <!DOCTYPE html>
    <html>
    
      <head>
        <script data-require="[email protected]" data-semver="1.4.2" src="https://code.angularjs.org/1.4.2/angular.js"></script>
        <link rel="stylesheet" href="style.css" />
        <script src="script.js"></script>
      </head>
    
      <body>
        <div id="app" ng-app="app">
        <div ng-controller="mainCtrl"> {{count}}
              <my-directive ctrl-fn="ctrlFn(count)"></my-directive> 
            </div>
          </div>
      </body>
    
    </html>