TheIntrepidSpiff
TheIntrepidSpiff

Reputation: 189

AngularJS $scope.$watch on multiple filters

I have been tinkering with no luck, at first I thought I had it but now I can't get the results of multiple filters to remain consistent.

My issue is that when I select a filter on the front-end, the first one I use works, but when I then choose a second filter on top of that, the filtered.length and number of pages resets, but the data displayed is correct. Below is what's in my controller

    $scope.list= response.data;
        var memberList = $scope.list;

        $scope.currentPage = 1; //current page
        $scope.maxSize = 5; //pagination max size
        $scope.entryLimit = 25; //max rows for data table

        $scope.listLength = memberList.length;
        $scope.noOfPages = 22;


        $scope.$watch('filterA', 
            function(term) {
                $scope.filtered = filterFilter($scope.list, term);
                $scope.noOfPages = Math.ceil($scope.filtered.length/25);
                $scope.listLength = $scope.filtered.length;
        }, true);
        $scope.$watch('filterB', 
            function(term) {
                $scope.filtered = filterFilter($scope.list, term);
                $scope.noOfPages = Math.ceil($scope.filtered.length/25);
                $scope.listLength = $scope.filtered.length;
        }, true);
        $scope.$watch('filterC', 
            function(term) {
                $scope.filtered = filterFilter($scope.list, term);
                $scope.noOfPages = Math.ceil($scope.filtered.length/25);
                $scope.listLength = $scope.filtered.length;
        }, true);   
        $scope.$watch('filterD', 
            function(term) {
                $scope.filtered = filterFilter($scope.list, term);
                $scope.noOfPages = Math.ceil($scope.filtered.length/25);
                $scope.listLength = $scope.filtered.length;
        }, true);

And then in the view, I've got 4 inputs...one is search, the others dropdown. When I use any more than one of the filters, the length does not update.

<input type="text" ng-model="filterA">
<input type="text" ng-model="filterB">
<input type="text" ng-model="filterC">
<input type="text" ng-model="filterD">

{{filtered.length}}
<uib-pagination total-items="filtered.length" items-per-page="25" next-text="Next" previous-text="Previous" ng-model="currentPage" max-size="maxSize" class="pagination-sm" boundary-link-numbers="true" boundary-links="true" num-pages="noOfPages"></uib-pagination>
 <table>
   <tbody>
      <tr ng-repeat="post in filtered | filterA | filterB | filterC | filterD | startFrom:(currentPage-1)*entryLimit | limitTo:entryLimit">
         <td>{{post.name}}</td>
       </tr>
    </tbody>
   </table>

Upvotes: 0

Views: 996

Answers (1)

JLRishe
JLRishe

Reputation: 101680

Hopefully, it's quite clear what's happening here. Every time one of your $watch expression fires, you are applying the most recently changed filter to the original list, so that's the only one that has any effect.

Probably your best bet is to apply all four filters every time one changes. Here's one way you can do that:

function applyFilters() {
    var filters = ['filterA', 'filterB', 'filterC', 'filterD'];

    $scope.filtered = filters.reduce(function (l, name) {
        return filterFilter(l, $scope[name]);
    }, $scope.list);
    $scope.noOfPages = Math.ceil($scope.filtered.length/25);
    $scope.listLength = $scope.filtered.length;
}

$scope.$watch('filterA', applyFilters, true);
$scope.$watch('filterB', applyFilters, true);
$scope.$watch('filterC', applyFilters, true);   
$scope.$watch('filterD', applyFilters, true);

I'm pretty sure you should also remove the | filterA | filterB | filterC | filterD from your view. If you're already filtering in your watch expression, then those can't be doing anything useful.

Upvotes: 1

Related Questions