user3222157 user3222157 - 5 months ago 35
AngularJS Question

How to combine multiple filter value in single watch variable?

I have tried to do multiple filter with update pagination using angular watch concept. But end up with creating multiple watch function for every filter value. I Knew its wrong way to do. I need help to overcome this issue.

In html i had three inputs value to do filter .One is by date , title and any(search.$) .

**Html code** :

<div ng-controller="ShowAnnouncementListing">
<form role="form">
<div class="form-group">
<div class="col-xs-3">
<label for="ex1">Title</label>
<input class="form-control" ng-model="search.title" id="ex1" type="text">
</div>
<div class="col-xs-3">
<label for="ex2">Published Date</label>
<input class="form-control" ng-model="search.date" uib-datepicker-popup="{{format}}" ng-model="date" id="ex2" type="text">
</div>
<div class="col-xs-3">
<label for="ex3">Keywords</label>
<input class="form-control" ng-model="search.$" id="ex3" type="text">
</div>
</div>
</form>

<table class="table announcementList-table">
<thead>
<tr class="announcement-header">
<th style="width: 76px;"> Type </th>
<th> Published Date </th>
<th> Announcements </th>
</tr>
</thead>
<tbody>
<tr class="announcementList-National-section" ng-repeat="announcement in filtered = announcementListData | filter:search.date | filter:search.$ | filter:search.title | startFrom:(currentPage-1)*entryLimit | limitTo:entryLimit">
<td class="announcementList-table-National-segment">
<span class="National-label">{{announcement.type}}
</span>
<span class="announcementList-National-segment-triangle"></span>
</td>
<td class="announcementList-published-date-TD">
<span class="national-date-segment">
<span class="national-day-label"> {{announcement.date}} </span>
<p> {{announcement.month}}</p>
</span>
</td>
<td class="announcementList-announcement-title-TD">
<span class="national-segment-content"> <span class="national-segment-text"> {{announcement.title}} </span>{{announcement.desc}}</span>
</td>
</tr>
<tbody>
</table>

<pagination page="currentPage" max-size="noOfPages" total-items="totalItems" items-per-page="entryLimit"></pagination>


</div>

**JS code** :

var announcementJsonData = [
{
"title":"Annoncement1",
"desc":"Lorem ipsum dolor sit, consectetur adipiscing elit. Aliquam adipiscing massa lacus.",
"date":"05",
"month":"July",
"type":"National",
"img":"image.jpg"
},
{
"title":"Annoncement2",
"desc":"Lorem ipsum dolor sit, consectetur adipiscing elit. Aliquam adipiscing massa lacus.",
"date":"15",
"month":"August",
"type":"Regionl",
"img":"image.jpg"
},
{
"title":"Annoncement3",
"desc":"Lorem ipsum dolor sit, consectetur adipiscing elit. Aliquam adipiscing massa lacus.",
"date":"28",
"month":"June",
"type":"Regionl",
"img":"image.jpg"
},
{
"title":"Annoncement4",
"desc":"Lorem ipsum dolor sit, consectetur adipiscing elit. Aliquam adipiscing massa lacus.",
"date":"21",
"month":"July",
"type":"National",
"img":"image.jpg"
},
{
"title":"Annoncement5",
"desc":"Lorem ipsum dolor sit, consectetur adipiscing elit. Aliquam adipiscing massa lacus.",
"date":"10",
"month":"July",
"type":"National",
"img":"image.jpg"
},
{
"title":"Annoncement6",
"desc":"Lorem ipsum dolor sit, consectetur adipiscing elit. Aliquam adipiscing massa lacus.",
"date":"14",
"month":"July",
"type":"National",
"img":"image.jpg"
},
{
"title":"Annoncement7",
"desc":"Lorem ipsum dolor sit, consectetur adipiscing elit. Aliquam adipiscing massa lacus.",
"date":"07",
"month":"July",
"type":"National",
"img":"image.jpg"
},
{
"title":"Annoncement8",
"desc":"Aorem ipsum dolor sit, consectetur adipiscing elit. Aliquam adipiscing massa lacus.",
"date":"23",
"month":"July",
"type":"National",
"img":"image.jpg"
},
{
"title":"Annoncement9",
"desc":"Lorem ipsum dolor sit, consectetur adipiscing elit. Aliquam adipiscing massa lacus.",
"date":"17",
"month":"July",
"type":"National",
"img":"image.jpg"
},
{
"title":"Annoncement10",
"desc":"Lorem ipsum dolor sit, consectetur adipiscing elit. Aliquam adipiscing massa lacus.",
"date":"16",
"month":"August",
"type":"National",
"img":"image.jpg"
},
{
"title":"Annoncement11",
"desc":"Lorem ipsum dolor sit, consectetur adipiscing elit. Aliquam adipiscing massa lacus.",
"date":"05",
"month":"September",
"type":"National",
"img":"image.jpg"
}

];

var sampleApp = angular.module('sampleApp', ['ngRoute','ui.bootstrap']);

sampleApp.filter('startFrom', function () {
return function (input, start) {
if (input) {
start = +start;
return input.slice(start);
}
return [];
};
});

sampleApp.controller('ShowAnnouncementListing',['$scope','filterFilter',function($scope , filterFilter) {

$scope.message = "This is Announcement Listing page";
$scope.announcementListData = announcementJsonData;

/* $scope.announcementListData = announcementJsonData;
$scope.totalItems = $scope.announcementListData.length;
$scope.viewby = 5;
$scope.currentPage = 1;
$scope.itemsPerPage = $scope.viewby ;
$scope.maxSize = 5; //Number of pager buttons to show */

/* $scope.setPage = function (pageNo) {
$scope.currentPage = pageNo;
}; */

/* $scope.pageChanged = function() {
console.log('Page changed to: ' + $scope.currentPage);
}; */

/* $scope.setItemsPerPage = function(num) {
$scope.itemsPerPage = num;
$scope.currentPage = 1; //reset to first paghe
} */


// create empty search model (object) to trigger $watch on update
$scope.search = {};

$scope.resetFilters = function () {
// needs to be a function or it won't trigger a $watch
$scope.search = {};
};

// pagination controls
$scope.currentPage = 1;
$scope.totalItems = $scope.announcementListData.length;
$scope.entryLimit = 5; // items per page
$scope.noOfPages = Math.ceil($scope.totalItems / $scope.entryLimit);

// $watch search to update pagination
$scope.$watch('search.date', function (newVal, oldVal) {
$scope.filtered = filterFilter($scope.announcementListData, newVal);
$scope.totalItems = $scope.filtered.length;
$scope.noOfPages = Math.ceil($scope.totalItems / $scope.entryLimit);
$scope.currentPage = 1;

}, true);

$scope.$watch('search.$', function (newVal, oldVal) {
$scope.filtered = filterFilter($scope.announcementListData, newVal);
$scope.totalItems = $scope.filtered.length;
$scope.noOfPages = Math.ceil($scope.totalItems / $scope.entryLimit);
$scope.currentPage = 1;

}, true);

$scope.$watch('search.title', function (newVal, oldVal) {
$scope.filtered = filterFilter($scope.announcementListData, newVal);
$scope.totalItems = $scope.filtered.length;
$scope.noOfPages = Math.ceil($scope.totalItems / $scope.entryLimit);
$scope.currentPage = 1;

}, true);


}]);

Answer

You can pull the function out of the $watch declaration, and then reference it.

$scope.$watch('search.date', updateSearch, true);
$scope.$watch('search.$', updateSearch, true);
$scope.$watch('search.title', updateSearch, true);

function updateSearch(newVal) {           
  $scope.filtered = filterFilter($scope.announcementListData, newVal);
  $scope.totalItems = $scope.filtered.length;
  $scope.noOfPages = Math.ceil($scope.totalItems / $scope.entryLimit);
  $scope.currentPage = 1;
}

Alternatively, if you only wanted a single watch declaration you could do something like this:

$scope.$watch(function(){
   return {date: $scope.search.date, $: $scope.search.$, title: $scope.search.title}
  }, function(searchParams){
    // searchParams will now only get run when the object created above changes, 
    // so if any of the fields change, it should pass the updated object in to this function
    $scope.filtered = filterFilter($scope.announcementListData, searchParams);
    $scope.totalItems = $scope.filtered.length;
    $scope.noOfPages = Math.ceil($scope.totalItems / $scope.entryLimit);
    $scope.currentPage = 1;
  }, true);
Comments