1

I have an HTML page using AngularJS.

This is basically a listing which can be filtered by clicking on some checkboxes.

I want to use jQuery 'garlic' plugin to memorize checkboxes states.

The plugin is working well, except that AngularJS "does not see" the checkbox states: the listing is not filtered according to checkboxes states. Even without using 'garlic' I have the same problem, I if do something like this :

$(document).ready(function() {
    $('#my-checkbox-tracked-by-angular).attr('checked',true_or_false).change();
});

The checkbox itself is visually updated but AngularJS is not triggered.

The only thing that worked to trigger AngularJS is to use click event :

$(document).ready(function() {
    $('#my-checkbox-tracked-by-angular).trigger("click");
});

AngularJS is updating the listing, but the click event is also switching the checkbox to the opposite state, and I do not want that.

Is there a way to tell Angular to refresh when a angular-tracked checkbox is updated outside angular ?

Note: I also tried :

$scope.$apply();

But $scope is undefined despite my code is after angular loading. I have AngularJS V1.2.1. How can I get access to $scope ?

Eric
  • 4,821
  • 6
  • 33
  • 60
  • use `$scope.$apply(function() { ... here you call jquery to do some actions... });` , it tells angular that you will do something and that he has to do some check after the function is called – Pierre Emmanuel Lallemant Nov 06 '18 at 16:48
  • It is better to incorporate the jQuery function into the AngularJS framework and manupulate the scope model. – georgeawg Nov 06 '18 at 21:53

1 Answers1

2

Is there a way to tell Angular to refresh when a angular-tracked checkbox is updated outside angular ?

Yes, there is something called "dirty checking" which can help you in order to achieve this (See scope docs).

In order to tell AngularJS to do dirty checking you can do $scope.$apply();. Something like:

$(document).ready(function() {
    $('#my-checkbox-tracked-by-angular').attr('checked',true_or_false).change();

    // do dirty checking!
    // wrap it inside $timeout in order to avoid Action Already In Progress
    // you can laverage this in your app. Maybe it's not necessary,
    // but that depends on your entire app architecture and interaction
    // between all angularjs elements (controllers, directives, etc)
    $timeout(function() {
        $scope.$apply();
    });
});

If, for any reason, you could not do this, maybe, you could use as a workaround to trigger the click event twice. It is not the best solution and surely not the cleanest one, but it will do the job. Something like:

$(document).ready(function() {
    $('#my-checkbox-tracked-by-angular).trigger("click").trigger("click");
});

Caution:

If you mix AngularJS and jQuery for DOM manipulation directly, do it cautiously, it can become a mess. In order to get some more background about why, read "Thinking in AngularJS" if I have a jQuery background?.

Additional readings:

lealceldeiro
  • 14,342
  • 6
  • 49
  • 80
  • 1
    It would be so much better and native to use [ngAttr](https://docs.angularjs.org/guide/interpolation) or just `ngModel` instead of that jQuery mess – Alon Eitan Nov 06 '18 at 18:12
  • 1
    @AlonEitan I agree with you. I just answered the specific question. I've been struggling in that mess in some occasions too (in a **very** similar situation where the OP is, while maintaining legacy code) and this is useful. That said, I should add that to the post. Thanks for your feedback! I'd really appreciate it :) – lealceldeiro Nov 06 '18 at 18:52
  • I do not have access to $scope nor $timeout it is undefined despite my code is after angular loading. I have AngularJS V1.2.1. How can I get access to these objects ? – Eric Nov 07 '18 at 09:20
  • @Eric you could try to "inject" them doing something like this https://gist.github.com/umidjons/1fb8ae674df4c71f85cf – lealceldeiro Nov 07 '18 at 13:29
  • Does not work. I also tried angular.element("#my-checkbox-tracked-by-angular").scope().$apply(); but does not work too. – Eric Nov 08 '18 at 16:26