jdphenix
jdphenix

Reputation: 15425

Proper "Angular" way to pass behavior to directive?

When looking for information regarding Angular directives and passing behavior to directives, I get ended up being pointed in the direction of method binding on an isolate scope, i.e.

scope: {
  something: '&'
}

The documentation for this functionality is a bit confusing, and I don't think it'll end up doing what I want.

I ended up coming up with this snippet (simplified for brevity), that works by passing a scope function in HomeCtrl, and the directive does it's work and calls the function. (Just incase it matters, the real code passes back a promise from the directive).

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

angular.module('app')
  .directive('passingFunction',
    function() {
      var changeFn,
        bump = function() {
          console.log('bump() called');
          internalValue++;
          (changeFn || Function.prototype)(internalValue);
        },
        internalValue = 42;

      return {
        template: '<button ng-click="bump()">Click me!</button>',
        scope: {
          onChange: '<'
        },
        link: function(scope, element, attrs) {
          if (angular.isFunction(scope.onChange)) {
            changeFn = scope.onChange;
          }

          scope.bump = bump;
        }
      };
    })
  .controller('HomeCtrl',
    function($scope) {
      $scope.receive = function(value) {
        console.log('receive() called');
        $scope.receivedData = value;
      };
    });
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.4/angular.min.js"></script>
<div ng-app="app" ng-controller="HomeCtrl">
  <passing-function on-change="receive"></passing-function>
  <p>Data from directive: {{receivedData}}</p>
</div>

Is this a proper "Angular" way of achieving this? This seems to work.

Upvotes: 3

Views: 93

Answers (1)

Chris Stanley
Chris Stanley

Reputation: 2926

What you need is to pass the function to the directive. I'll make a very small example.

On controller:

$scope.thisFn = thisFn(data) { console.log(data); };

In html:

<my-directive passed-fn="thisFn()"></my-directive>

On directive:

.directive('myDirective', [
  () => {
    return {
      restrict: 'E',
      scope: {
        passFn: '&'
      },
      template: '<div id="myDiv" ng-click="passFn(data)"></div>',
      link: (scope) => { 
          scope.data = "test";
      }
    }
  }]);

Upvotes: 1

Related Questions