How to call a custom directive's action in AngularJS?

328 views Asked by At

In AngularJS you can make a button to call an action like this:

<div ng-controller="myController">
  <button ng-click="onButtonClicked()">Click me</button>
</div>

So, I'm inserting a custom directive like this:

and in my-canvas.js directive file's link function I replace the tag with a KineticJS canvas. Then, User manipulate the canvas by dragging around Kinetic shapes and, finally, when User does with the shapes what he's required to do, I want the directive to call an action defined on myController. I'm thinking about something like this:

<div ng-controller="myController">
  <my-canvas ng-success="onScenarioSuccess" />
</div>

but I can't figure out how the correct way to do it.

How can I make a directive to call it's action/event programmatically?

2

There are 2 answers

0
Beyers On

When you want your directive to expose an API for binding to behaviors you should use an isolate scope and use the & local scope property. This allows you to pass in a function that the directive can invoke. Here is a simple example:

.directive('testDirective', function () {
    return {
        restrict: 'E',
        scope: {
            action: '&'
        },
        template: '<button ng-click="action()">Test</button>'
    };
});

And use it like:

<test-directive action="myControllerFunction()"></test-directive>

As per the documentation:

The & binding allows a directive to trigger evaluation of an expression in the context of the original scope, at a specific time. Any legal expression is allowed, including an expression which contains a function call. Because of this, & bindings are ideal for binding callback functions to directive behaviors.

There'are some more detail in the documentation.

4
Chandermani On

If you want to expose a custom event like ng-success and want to call a function on the event. You can either do what @Beyers has mentioned using isolated scope.

Or else look at the source code of ng-click, it just wraps the javascript event inside $scope.apply, using the $parse service to evaluate the expression passed to it. Something like this can be added in your link function

var fn = $parse(attr['ngSuccess']);
element.on('someEvent', function (event) {
    var callback = function () {
        fn(scope, {
            $event: event
        });
    };
    scope.$apply(callback);
});

The advantage of this mechanism is that isolated scope is not created.