Search code examples
javascriptangularjsangularjs-scopeangularjs-ng-clickangularjs-watch

ng-click value change + $scope.watch bind not working properly


I have a scope variable '$scope.searchType' which is equal to 'createdAt' by default. In my HTML I have options that change the scope variable value:

<ul class="dropdown-menu" role="menu">
    <li><a ng-click="searchType = 'Anything'">Anything</a></li>
    <li><a ng-click="searchType = 'Payment'">Payment</a></li>
    <li><a ng-click="searchType = 'Total'">Total</a></li>
    <li><a ng-click="searchType = 'Tax'">Tax</a></li>
    <li><a ng-click="searchType = 'Payment Method'">Payment Method</a></li>
</ul>

In my controller I have the following to listen for changes:

$scope.$watch('searchType', function(newValue) {
    if(newValue == 'Payment') {
        $scope.searchTypeFilter = 'id';
        $scope.searchFiltered = true;
    } else if(newValue == 'Total') {
        $scope.searchTypeFilter = 'total';
        $scope.searchFiltered = true;
    } else if(newValue == 'Tax') {
        $scope.searchTypeFilter = 'tax';
        $scope.searchFiltered = true;
    } else if(newValue == 'Payment Method') {
        $scope.searchTypeFilter = 'paymentType';
        $scope.searchFiltered = true;
    } else {
        $scope.searchTypeFilter = '';
        $scope.searchFiltered = false;
        $scope.search = '';
    }
}, true);

For some reason the $scope.$watch never gets called. I cannot figure out how this doesn't work since it used to. This is the '$scope.searchType' declaration:

$scope.sortType = 'createdAt';

Solution

  • You don't need to add a $watch because you have a click event that will set your filter variable.

    Also your if/else can be simplified with a js object.

    Please have a look at the demo below or this fiddle.

    angular.module('demoApp', [])
    .controller('mainController', MainController);
    
    function MainController($scope) {
        var filterMapping = {
            
            Payment: 'id',
            Total: 'total',
            Tax: 'tax',
            'Payment Method': 'paymentType',
            Default: ''
        };
        
        this.setNewFilter = function(name) {
            $scope.searchTypeFilter = filterMapping[name] || filterMapping['Default'];
            $scope.searchFiltered = $scope.searchTypeFilter != '' ? true: false;
        };
      
        this.setNewFilter(''); // init filter to anything
    }
    
    MainController.$inject = ['$scope'];
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <div ng-app="demoApp" ng-controller="mainController as ctrl">
    <ul class="dropdown-menu" role="menu">
        <li><a ng-click="ctrl.setNewFilter('Anything')">Anything</a></li>
        <li><a ng-click="ctrl.setNewFilter('Payment')">Payment</a></li>
        <li><a ng-click="ctrl.setNewFilter('Total')">Total</a></li>
        <li><a ng-click="ctrl.setNewFilter('Tax')">Tax</a></li>
        <li><a ng-click="ctrl.setNewFilter('Payment Method')">Payment Method</a></li>
    </ul>
        {{searchFiltered}}<br/>
    {{searchTypeFilter}}    
    </div>