Search code examples
javascriptangularjsangularjs-watch

What happens behind the scenes when binding to a function in AngularJS


Can anyone explain what happens behind the scenes when you bind to a function in AngularJS? What kind of watch does it create? I have a feeling it would create two watches (in my example below) one for each property that makes up the return value. However I'm certainly not sure about this but it feels like something we shouldn't do.

e.g.

<div ng-show="vm.someFunc()">

JS

vm.someFunc = function() {  
    return vm.property1 || vm.property2;
}

Solution

  • If you created the angular scope method "vm.someFunc()", this will continuously get polled. You can verify this by setting a breakpoint in this method, it will continuously keep getting hit. If you check the task manager and show the browser running your website, the memory keeps going up and won't stop.

    In my opinion, scope functions should only be used when using event triggers: click event, change event, keypressed are some of the examples.

    Showing or hiding aren't events, so this is why it gets polled like that.To fix and provide the same functionality, turn this into a scope variable.
    change the html tag from:

    <div ng-show="vm.someFunc()">
    

    to

    <div ng-show="vm.someFunc">
    

    And in your controller:

    $scope.KeyPressed = false;
    $scope.Tags = '';
    

    then create a watch event on what you want to watch for:

    //initialize showtag when page loads
    $scope.vm.someFunc = $scope.KeyPressed && $scope.Tags !== '';
    
    //watch for any new changes on keypressed
    $scope.$watch('KeyPressed', function (newValue, oldValue) {
         if (newValue && $scope.Tags !== '') {
             $scope.vm.someFunc= true;
         } else {
             $scope.vm.someFunc= false;
         }
    }
    
    //watch for any new changes on keypressed
    $scope.$watch('Tags', function (newValue, oldValue) {
         if (newValue !== "" && $scope.KeyPressed) {
             $scope.vm.someFunc= true;
         } else {
             $scope.vm.someFunc= false;
         }
    }
    

    Or you can change to a "watchCollection" instead of having multiple watches like:

    $watchCollection('[KeyPressed, Tags]', function (newValue) { }
    

    newValue[0] is the value of KeyPressed, and newValue[1] is the value of Tags

    Or to go along with the accepted answer and minimize the amount of watches:

    $scope.TruthyVal= function () {
        return $scope.KeyPressed && $scope.Tags !== '';
    };
    
    $scope.$watch('TruthyVal', function (newValue, oldValue) {
         if (newValue) {
             $scope.vm.someFunc= true;
         } else {
             $scope.vm.someFunc= false;
         }
    }