Using ng-click vs bind within link function of Angular Directive

113,329

Solution 1

You may use a controller in directive:

angular.module('app', [])
  .directive('appClick', function(){
     return {
       restrict: 'A',
       scope: true,
       template: '<button ng-click="click()">Click me</button> Clicked {{clicked}} times',
       controller: function($scope, $element){
         $scope.clicked = 0;
         $scope.click = function(){
           $scope.clicked++
         }
       }
     }
   });

Demo on plunkr

More about directives in Angular guide. And very helpfull for me was videos from official Angular blog post About those directives.

Solution 2

I think it is fine because I've seen many people doing this way.

If you are just defining the event handler within the directive, you do not have to define it on the scope, though. Following would be fine.

myApp.directive('clickme', function() {
  return function(scope, element, attrs) {
    var clickingCallback = function() {
      alert('clicked!')
    };
    element.bind('click', clickingCallback);
  }
});

Solution 3

Shouldn't it simply be:

<button ng-click="clickingCallback()">Click me<button>

Why do you want to write a new directive just to map your click event to a callback on your scope ? ng-click already does that for you.

Share:
113,329
ehfeng
Author by

ehfeng

Currently at Sentry (sentry.io)

Updated on July 05, 2022

Comments

  • ehfeng
    ehfeng almost 2 years

    In the link function, is there a more "Angular" way to bind a function to a click event?

    Right now, I'm doing...

    myApp.directive('clickme', function() {   
      return function(scope, element, attrs) {
        scope.clickingCallback = function() {alert('clicked!')};
        element.bind('click', scope.clickingCallback);   
    } });
    

    Is this the Angular way of doing it or is it an ugly hack? Perhaps I shouldn't be so concerned, but I'm new to this framework and would like to know the "correct" way of doing things, especially as the framework moves forward.

  • Mark Rajcok
    Mark Rajcok over 11 years
    In clickingCallback, if you are changing any model/scope data, you'll want to call scope.$apply(), or put the contents of the method inside scope.$apply(function() { ...contents here...});
  • ehfeng
    ehfeng over 11 years
    I actually want to add the ng-click attribute to the element itself, not the template element (in your case, the button). Do you know how to do that?
  • ehfeng
    ehfeng over 11 years
    Never mind, I figured it out - I can use the "replace" option within the directive.
  • turbo2oh
    turbo2oh almost 11 years
    @Maxim Grach why not just put the button HTML in the HTML? It seems like a lot of work to display a button that calls a controller method and less obvious when viewing the HTML. PS I'm learning angular as well.
  • Maxim Grach
    Maxim Grach almost 11 years
    @turbo2oh this example is very simple and out of real life. But It shows how you can use angular directives.
  • JacobF
    JacobF about 10 years
    I'm also curious about the opions on this one. ng-click versus element.bind()
  • Bill'o
    Bill'o over 9 years
    @Maxim Grach I think that writing scope: {} would be more correct syntax-wise
  • Estevez
    Estevez about 9 years
    Maybe just to make that part reusabel, repeatable the code elsewhere.
  • Fred
    Fred almost 9 years
    @MaximGrach using scope: {} would isolate the scope, while using true allows shared scope.
  • Alisson Reinaldo Silva
    Alisson Reinaldo Silva about 7 years
    @Estevez that's exactly my use case.