2

I want to trap on-click event of button. The id of button is dynamically generated inside the ng-repeat.

.set(ng-repeat='button in ['4', '3' , '2', '1' ]')
   button(id='{{$index}}') button {{button}}


Button 4
Button 3
Button 2
Button 1

Above where do i put the my-dir directive attribute/class?

.my-dir
  .set ...

The above does not work.

and

.my-dir.set ...

executes the link function multiple times.

/* below code in greater details, if above statement is not clear enough */

Directive is

myApp.directive('myDir', function() {
var linkFn = function(scope, element, attrs) {

  alert('inside linkFn');
  $('button').on('click', function() { alert('button clicked');});
} 

  return {
    restrict: 'C', 
    link: linkFn
  }
});

using ng-repeat the class my-dir can be put either in the scope of ng-repeat or outside it

case 1: my-dir is outside scope of ng-repeat

.my-dir
  .set(ng-repeat='button in buttons')
    button(id='id{{$index}}') {{item}}

now the above code $('.set').on('click', function() { alert('button clicked');}); does not get executed!

case 2: my-dir is inside ng-repeat

(in controller) $scope.buttons=['4', '3', '2', '1']

.set(ng-repeat='button in buttons').my-dir
    button(id='id{{$index}}') button {{item}}

now when you press button 4 "button clicked" shows up in alert box 4 times. For button 3 3 times and so on.

Sangram Singh
  • 7,161
  • 15
  • 50
  • 79
  • Why can you not use `ng-click`? Also, ID's should not contains spaces, it is not like class where it can have multiple (see http://stackoverflow.com/questions/192048/can-an-html-element-have-multiple-ids) – TheSharpieOne Sep 26 '13 at 19:54
  • for DOM manipulation, Directives are recommended. I want to change css upon click of button. I am not using space in `ids` – Sangram Singh Sep 26 '13 at 19:58
  • Sorry about that, the formatting was off and it appeared that the id field contained spaces. – TheSharpieOne Sep 26 '13 at 20:12
  • If you are using Jade, consider adding corresponding tag. – vittore Sep 26 '13 at 20:16

1 Answers1

5

The main problem with setting the directive on the wrapping element is that the directive will run before the ng-repeat has unrolled. So there are no buttons in the element when the on method is called. You can use the on method a little differently to allow it to be more like the old jquery live method. Apply it to the parent element and pass an optional selector(in your case, 'button') to tell it what elements to trigger on. This is also good for when buttons are added and removed.

$(element).on('click', 'button', function () {
    // do something here.
    alert($(this).text() + ' clicked');
});

HTML

<div ng-app="myApp" ng-controller="myCtrl">
    <div class="myDir">
        <button ng-repeat="button in buttons" id="{{button}}">Button {{button}}</button>
    </div>
</div>

JS:

var app = angular.module("myApp", []).directive('myDir', function () {
    var linkFn = function (scope, element, attrs) {
        $(element).on('click', 'button', function () {
            alert($(this).text() + ' clicked');
        });
    }

    return {
        restrict: 'C',
        link: linkFn
    }
});

function myCtrl($scope) {
    $scope.buttons = ['4', '3', '2', '1'];
}

Fiddle: http://jsfiddle.net/JjB3B/

TheSharpieOne
  • 25,646
  • 9
  • 66
  • 78