Dhana Dhana - 6 months ago 59
Javascript Question

AngularJS single select filtering is not working for Name, Description and Field4 checkbox values?

I have filtering like following: means, if I select

multiple checkboxes
(say: one checkbox from
Name
and one checkbox from
Description
dropdowns), then those respective matched data is coming fine of
Name
and
Description
columns, and similarly for other selections also(like with
Description
and
Field4
and
Field4
and Name
dropdowns
).

If I select all three checkboxes from all dropdowns(like
name 1
,
description 1
and
field4 1
then it's matched data is coming fine of
Name
,
Description
and
Field4
columns.

But what I need is now: the data is not filtering with the single checkbox or individual checkbox selection(Like: if I select any either
Name
or
Description
or
field4
dropdown checkbox, then the selected checkbox related data is not coming). So that I can filter the data with three cases: single selection, any two dropdown checkbox selection, all three dropdown checkbox selection.

Code is given below and Created.

html:

<div ng-controller="TestCtrl">
<table id="items" class="table table-striped table-condensed table-hover" border="1">
<thead>
<tr>
<th class="id" custom-sort order="'id'" sort="sort">Id&nbsp;</th>
<th class="name" custom-sort order="'name'" sort="sort">Name&nbsp;</th>
<th class="description" custom-sort order="'description'" sort="sort">Description&nbsp;</th>
<th class="field4" custom-sort order="'field4'" sort="sort">Field 4&nbsp;</th>
<th class="field5" custom-sort order="'field5'" sort="sort">Field 5&nbsp;</th>
</tr>
</thead>
<tfoot>
<td colspan="6">
<div class="pagination pull-right">
<ul>
<li ng-class="{disabled: currentPage == 0}">
<a href ng-click="prevPage()">« Prev</a>
</li>

<li ng-repeat="n in range(pagedItems.length, currentPage, currentPage + gap) "
ng-class="{active: n == currentPage}"
ng-click="setPage()">
<a href ng-bind="n + 1">1</a>
</li>

<li ng-class="{disabled: (currentPage) == pagedItems.length - 1}">
<a href ng-click="nextPage()">Next »</a>
</li>
</ul>
</div>
</td>
</tfoot>

<tbody>
<tr ng-repeat="item in pagedItems[currentPage] | orderBy:sort.sortingOrder:sort.reverse | filter:filterItems">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.description}}</td>
<td>{{item.field4}}</td>
<td>{{item.field5}}</td>
</tr>
</tbody>

</table>
<h4>Filters</h4>

<div>
<div class="dropdown">
<a href="#" data-toggle="dropdown" class="btn btn-default dropdown-toggle">Select Name<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><input type="checkbox" data-ng-model='pagedItems.name' data-ng-true-value='name 1' data-ng-false-value='false' /> name1</li>
<li><input type="checkbox" data-ng-model='pagedItems.name' data-ng-true-value='name 2' data-ng-false-value='false' /> name2</li>
<li><input type="checkbox" data-ng-model='pagedItems.name' data-ng-true-value='name 3' data-ng-false-value='false' /> name3</li>
</ul>
</div><br><br>
<div class="dropdown">
<a href="#" data-toggle="dropdown" class="btn btn-default dropdown-toggle">Select Description <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><input type="checkbox" data-ng-model='pagedItems.description' data-ng-true-value='description 1' data-ng-false-value='false' /> description 1</li>
<li><input type="checkbox" data-ng-model='pagedItems.description' data-ng-true-value='description 2' data-ng-false-value='false' /> description 2</li>

</ul>
</div><br><br>
<div class="dropdown">
<a href="#" data-toggle="dropdown" class="btn btn-default dropdown-toggle">Select Field4 <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><input type="checkbox" data-ng-model='pagedItems.field4' data-ng-true-value='field4 1' data-ng-false-value='false' /> field4 1</li>
<li><input type="checkbox" data-ng-model='pagedItems.field4' data-ng-true-value='field4 2' data-ng-false-value='false' /> field4 2</li>
<li><input type="checkbox" data-ng-model='pagedItems.field4' data-ng-true-value='field4 3' data-ng-false-value='false' /> field4 3</li>

</ul>
</div>
</div>

</div>


controller:

var testmodule = angular.module('myModule', []);

testmodule.controller('TestCtrl', function ($scope, $filter) {

// init
$scope.sort = {
sortingOrder : 'id',
reverse : false
};

$scope.gap = 2;

$scope.filteredItems = [];
$scope.groupedItems = [];
$scope.itemsPerPage = 4;
$scope.pagedItems = [];
$scope.currentPage = 0;
$scope.items = [
{"id":1,"name":"name 1","description":"description 1","field4":"field4 1","field5":"field5 1"},
{"id":2,"name":"name 2","description":"description 2","field4":"field4 2","field5":"field5 2"},
{"id":3,"name":"name 3","description":"description 1","field4":"field4 3","field5":"field5 3"},
{"id":4,"name":"name 1","description":"description 1","field4":"field4 1","field5":"field5 4"},
{"id":5,"name":"name 2","description":"description 1","field4":"field4 2","field5":"field5 5"},
{"id":6,"name":"name 3","description":"description 2","field4":"field4 3","field5":"field5 6"},
{"id":7,"name":"name 3","description":"description 1","field4":"field4 1","field5":"field5 7"},
{"id":8,"name":"name 2","description":"description 2","field4":"field4 2","field5":"field5 8"},
{"id":9,"name":"name 1","description":"description 2","field4":"field4 3","field5":"field5 9"},
{"id":10,"name":"name 1","description":"description 1","field4":"field4 1","field5":"field5 10"}

];

var searchMatch = function (haystack, needle) {
if (!needle) {
return true;
}
return haystack.toLowerCase().indexOf(needle.toLowerCase()) !== -1;
};

$scope.filterItems = function(item) {
//all three selection to get matched data, working fine
if ($scope.pagedItems.name !== undefined && $scope.pagedItems.description !== undefined && $scope.pagedItems.field4 !== undefined && $scope.pagedItems.name !== "false" && $scope.pagedItems.description !== "false" && $scope.pagedItems.field4 !== "false") {
if(item.name === $scope.pagedItems.name && item.description === $scope.pagedItems.description && item.field4 === $scope.pagedItems.field4) return true;

}


else
// individual
/* if (item.name === $scope.pagedItems.name) return true;
if (item.description === $scope.pagedItems.description) return true;
if (item.field4 === $scope.pagedItems.field4) return true;*/

//any two selection to get matched data, working fine
if ((item.name === $scope.pagedItems.name && item.description === $scope.pagedItems.description) ||

(item.description === $scope.pagedItems.description && item.field4 === $scope.pagedItems.field4) ||
(item.field4 === $scope.pagedItems.field4 &&
item.name === $scope.pagedItems.name)) {return true;

}
else {
//individual selection to get their data, but it is not working
if(item.name === $scope.pagedItems.nameOne ||
item.name === $scope.pagedItems.nameTwo ||
item.name === $scope.pagedItems.nameThree)
{ return true;}

return false;
}
}


// init the filtered items
$scope.search = function () {
$scope.filteredItems = $filter('filter')($scope.items, function (item) {
for(var attr in item) {
if (searchMatch(item[attr], $scope.query))
return true;
}
return false;
});
// take care of the sorting order
if ($scope.sort.sortingOrder !== '') {
$scope.filteredItems = $filter('orderBy')($scope.filteredItems, $scope.sort.sortingOrder, $scope.sort.reverse);
}
$scope.currentPage = 0;
// now group by pages
$scope.groupToPages();
};


// calculate page in place
$scope.groupToPages = function () {
$scope.pagedItems = [];

for (var i = 0; i < $scope.filteredItems.length; i++) {
if (i % $scope.itemsPerPage === 0) {
$scope.pagedItems[Math.floor(i / $scope.itemsPerPage)] = [ $scope.filteredItems[i] ];
} else {
$scope.pagedItems[Math.floor(i / $scope.itemsPerPage)].push($scope.filteredItems[i]);
}
}
};

$scope.range = function (size,start, end) {
var ret = [];
console.log(size,start, end);

if (size < end) {
end = size;
start = size-$scope.gap;
}
for (var i = start; i < end; i++) {
ret.push(i);
}
console.log(ret);
return ret;
};

$scope.prevPage = function () {
if ($scope.currentPage > 0) {
$scope.currentPage--;
}
};

$scope.nextPage = function () {
if ($scope.currentPage < $scope.pagedItems.length - 1) {
$scope.currentPage++;
}
};

$scope.setPage = function () {
$scope.currentPage = this.n;
};

// functions have been describe process the data for display
$scope.search();



});


testmodule.$inject = ['$scope', '$filter'];

testmodule.directive("customSort", function() {
return {
restrict: 'A',
transclude: true,
scope: {
order: '=',
sort: '='
},
template :
' <a ng-click="sort_by(order)" style="color: #555555;">'+
' <span ng-transclude></span>'+
' <i ng-class="selectedCls(order)"></i>'+
'</a>',
link: function(scope) {

// change sorting order
scope.sort_by = function(newSortingOrder) {
var sort = scope.sort;

if (sort.sortingOrder == newSortingOrder){
sort.reverse = !sort.reverse;
}

sort.sortingOrder = newSortingOrder;
};


scope.selectedCls = function(column) {
if(column == scope.sort.sortingOrder){
return ('icon-chevron-' + ((scope.sort.reverse) ? 'down' : 'up'));
}
else{
return'icon-sort'
}
};
}// end link
}
});


How can I do this ? Please help me and Thanks in advance.

Answer

I updated a bit more code to get it working.

$scope.filterItems = function(item) {
        if ($scope.pagedItems.name !== undefined && $scope.pagedItems.description !== undefined && $scope.pagedItems.name !== "false" && $scope.pagedItems.description !== "false") {
        if(item.name === $scope.pagedItems.name && item.description === $scope.pagedItems.description) return true;
    } else {
            if (item.name === $scope.pagedItems.name) return true;
        if (item.description === $scope.pagedItems.description) return true;
        if ((item.description.indexOf($scope.pagedItems.description) > -1 && 
             $scope.pagedItems.description !== '')) return true;
    }
    return false;
}

And the HTML:

<div>
    <div class="dropdown">
    <a href="#" data-toggle="dropdown" class="btn btn-default dropdown-toggle">Select Name<b class="caret"></b></a>
    <ul class="dropdown-menu">
        <li><input type="checkbox" data-ng-model='pagedItems.name' data-ng-true-value='name 1' data-ng-false-value='false' /> name1</li>
        <li><input type="checkbox" data-ng-model='pagedItems.name' data-ng-true-value='name 2' data-ng-false-value='false' /> name2</li>
        <li><input type="checkbox" data-ng-model='pagedItems.name' data-ng-true-value='name 3' data-ng-false-value='false' /> name3</li>
    </ul>
</div><br><br>
<div class="dropdown">
    <a href="#" data-toggle="dropdown" class="btn btn-default dropdown-toggle">Select Description <b class="caret"></b></a>
    <ul class="dropdown-menu">
        <li><input type="checkbox" data-ng-model='pagedItems.description' data-ng-true-value='description 1' data-ng-false-value='false' /> description 1</li>
        <li><input type="checkbox" data-ng-model='pagedItems.description' data-ng-true-value='description 2' data-ng-false-value='false' /> description 2</li>

    </ul>
</div>
</div>

By changing from nameOne to name (same for description) I was able to simplify your if statements and make the combined match work without a gigantic if statement.

I updated your fiddle, you can find it here