poashoas
poashoas

Reputation: 1894

AngularJS watch not working

A watch is not working. I ng-include the following content:

<form class="search">
    <div class="searchbar">
        <input type="search" value="" data-ng-model="searchKeyword" placeholder="zoeken">
        <button type="submit"><i class="glyphicon glyphicon-search"></i></button>
    </div>
</form>

like this:

<div ng-include src="filterPath" onload="initiateSearch()"></div>

The onload function is doing this:

(function(){
    var appController = angular.module('ListerAppController', []);

    appController.controller('ListerCtrl', ['$scope', '$rootScope', '$http', '$filter', '$timeout', '$sharedFactories', 'History', '$location',
        function($scope, $rootScope, $http, $filter, $timeout, $sharedFactories, History, $location) {
            $scope.initiateSearch = function () {
            // This is what you will bind the filter to
                $scope.filterText = '';

                // Instantiate these variables outside the watch
                var tempFilterText = '',
                    filterTextTimeout;

                $scope.$watch('searchKeyword', function (val) {
                    if (filterTextTimeout) $timeout.cancel(filterTextTimeout);

                    tempFilterText = val;

                    filterTextTimeout = $timeout(function() {
                        $scope.filterText = tempFilterText;
                        $scope.pageCount = function() {
                            return Math.ceil( $scope.itemsfiltered.length / $scope.itemsPerPage );
                    };
                }, 350); // delay 250 ms
            });
        };
    }]);
})();

Everything seems to go allright but... the $watch on searchKeyword never fires the function when I start typing in the input element called searchKeyword.

Upvotes: 17

Views: 41153

Answers (4)

Libu Mathew
Libu Mathew

Reputation: 2996

The simplest one is to pass true as the last argument of $watch.

For more reading:

https://github.com/mbenford/ngTagsInput/issues/174

Upvotes: 0

daksh_019
daksh_019

Reputation: 862

Just to add to the list of possible solutions:

While using forms:

Using ng-pattern will supress the call to $watch unless and until the input is validated by ng-pattern.

So just in case, if anyone is using ng-pattern, try $watch after removing ng-pattern.

For more reading:

Angular.js - ng-change not firing when ng-pattern is $invalid

Upvotes: 2

DevLounge
DevLounge

Reputation: 8447

Have you tried adding true, as bellow?

$scope.$watch('searchKeyword', function (val) {
 /* your logic here */                    
}, true);

If you're curious about what the true is, here's the function signature from the docs:

$watch(watchExpression, listener, [objectEquality]);

When objectEquality == true, inequality of the watchExpression is determined according to the angular.equals function. To save the value of the object for later comparison, the angular.copy function is used. This therefore means that watching complex objects will have adverse memory and performance implications.

So apparently the significant thing is that it checks the equality of the old value and new value in a different way. I could see this being necessary if (correct me if I'm wrong) the value you're watching is, e.g., an array as opposed to a string.

Upvotes: 46

Carl
Carl

Reputation: 1258

The watch has to be an attribute of the object, not the object itself, see the example here https://docs.angularjs.org/api/ng/type/$rootScope.Scope on how to add a watch, and the use of the model here https://docs.angularjs.org/api/ng/directive/input. You could try this (I have not tested it)

data-ng-model="search.keyword"

and in your controller:

$scope.search = {}

...

$scope.$watch('search.keyword', ... 

Upvotes: 39

Related Questions