2

This is a two part question:

Part 1

What's the difference between binding to an event, say click using the ngClick attribute, vs using the element.bind('click')? For instance, I can have

HTML

<div ng-click="doStuff()">

JS

// Link function of a directive
link: function(scope, element, attrs)
{
    scope.doStuff = function() { // doing stuff //}
}

OR, I could ignore the ng-click inside my <div> and straight forward jump to the directive:

link: function(scope, element, attrs)
{
    element.bind('click', function() 
    {
        // doing stuff
    });
}

Part 2

Now, clearly there is a difference in what I can only assume is the $digest cycle. I have the following function that runs upon ng-click to create a new entry, and this entry is then gets a class added to it:

$('.cell').removeClass('selected');

scope.shift.createTask(scope.grid);

scope.schedule.modified();

// Wait until the DOM is digested before finding the last entry
$timeout(function(){
    var elem = element.closest('.shift').find('.task:last-child');
    activateTask(elem);
},0); 

The above code works fine if I use the ng-click method. But when I use the element.bind('click') method, the last entry with the $timeout doesn't add the class. It always seems to be one behind (i.e. the first task added and nothing happens. The second task added, and the first task gets the class)

Kousha
  • 32,871
  • 51
  • 172
  • 296
  • 1
    Essentially, `ngClick` triggers a digest cycle, while `bind` doesn't. – Blackhole Jul 20 '14 at 20:07
  • Part 2 : probably because you are changing the scope from outside angular and when you do that you need to tell angular using `$apply` – charlietfl Jul 20 '14 at 20:28
  • Highly suggested reading: [how-do-i-think-in-angularjs-if-i-have-a-jquery-background](http://stackoverflow.com/questions/14994391/how-do-i-think-in-angularjs-if-i-have-a-jquery-background) – charlietfl Jul 20 '14 at 20:31
  • Thanks @charlietfl. I'll definitely read that – Kousha Jul 20 '14 at 20:48

1 Answers1

0

If you look at the source code for ngClick, it binds to the click event and calls the function within the $apply block:

   ngEventDirectives[directiveName] = ['$parse', function($parse) {
       return {
           compile: function($element, attr) {
            var fn = $parse(attr[directiveName]);
               return function ngEventHandler(scope, element) {
             element.on(lowercase(name), function(event) {
             scope.$apply(function() {
                  fn(scope, {$event:event});
             });
        });
      };
    }
  };
}];

I suggest that to fix your issue, put more into your $timeout block. It is likely there is some code that needs to be in the same context as the $apply block that $timeout uses :

// Wait until the DOM is digested before finding the last entry
$timeout(function(){

    $('.cell').removeClass('selected');

       scope.shift.createTask(scope.grid);

       scope.schedule.modified();

       var elem = element.closest('.shift').find('.task:last-child');

       activateTask(elem);
   },0); 
Kousha
  • 32,871
  • 51
  • 172
  • 296
Michael Kang
  • 52,003
  • 16
  • 103
  • 135