Function does not execute without setTimeout

2

I'm having a problem executing a function when I click on icheck . In case, the function is only called if I give a setTimeout of 1 millisecond, less than that or without timeout the function is not executed. How can I do to execute this function without using timeout ?

vm.selecionaFiltros = function(){
    $('.marcas').iCheck({
        checkboxClass: 'icheckbox_minimal',
        radioClass: 'iradio_minimal',
    });

    $timeout(function() {
        $('.marcas').on('ifChanged', function (event) {
            console.log('1');
        });
    }, 100);
}
    
asked by anonymous 06.07.2016 / 23:04

1 answer

2

If this vm.selecionaFiltros function is called automatically, the possible problem is that it is happening outside the scope of AngularJs .

What does this mean?

It means that digest cycle has passed, so the changes will not be applied. digest cycle is a process of AngularJs (also known as dirty checking ) that compares all bindings through watchers ( {{meuEscopo}} or ng-bind="meuEscopo" - each element of this in your view generates a new watcher ) to check if that data has changed and, if so, update the view with this new value.

If your function runs after digest cycle means that no matter how much the changes occur AngularJs does not yet "know" it.

When digest cycle is triggered?

They are always fired when the application loads or through interactions with AngularJS functions, for example, ngClick , ngChange , ngBlur , etc. Or, within controller or directive , using $timeout (which is what you are doing) and $interval , and finally through a manual call, explained better below.

How to resolve?

The way to resolve this would be by manually calling digest cycle .

There are 2 methods to get the same end result:

  • $scope.$digest()
  • $scope.$apply()

Both are similar and will give you the same end result. However, $scope.$apply() will trigger the $rootScope.$digest() event that affects all scopes and their child elements while $scope.$digest() affects only the local scope and its child elements, giving you a better performance, as it will not affect the application as a whole.

Simple example, assuming that in the same view as this ng-repeat you have a directive that shows the weather, it has no connection to that list and has its own scope, since it comes from a directive . If you call $scope.$digest() , digest cycle will not check the watchers that belongs to it, so you have more performance. But if you call $scope.$apply() , how it will fire $rootScope.$digest() instead of $scope.$digest() - that is, the global cycle, that climate directive and all your watchers and child too will be validated by the cycle.

When to use one or the other?

If you are sure that the called function will only affect values that are within that scope, call $scope.$digest() . But if you know that interaction with these functions can interfere with scopes that are out of the current range, use $scope.$apply() .

Example: Assuming this list of ng-repeat is to select which type of temperature is displayed in directive . Celsius , Kelvin or Fahrenheit , so if I click on one of these elements of ng-repeat , I need to change an element outside my scope, so I call $scope.$apply() .

So, your code looks like this:

vm.selecionaFiltros = function(){
    $('.marcas').iCheck({
        checkboxClass: 'icheckbox_minimal',
        radioClass: 'iradio_minimal',
    });

    $('.marcas').on('ifChanged', function (event) {
        console.log('1');
        $scope.$digest(); //aqui
    });

    $scope.$digest(); //ou aqui
}

If you want, you can still remove the function declaration using vm and use a simple JS function.

function selecionaFiltros() {
    [...]
}

//chamada da função
selecionaFiltros();

The vm at the front serves to execute a function that is called through the view , with ng-click , ng-blur , etc ..

Note : Just to remember, since you're using syntax of vm , you need to inject $scope before you can use it.

    
12.07.2016 / 00:22