简体   繁体   中英

Angular filter search issue

Okay so i was unsure what to call this question.

Usually you want to filter an ng-repeat on an id field however this poses a problem.

Say for instance you have the following array:

    $scope.objList = [
{id: 1, name:'A'},
{id: 2, name:'B'},
{id: 3, name:'C'},
{id: 4, name:'D'},
{id: 5, name:'E'},
{id: 6, name:'F'},
{id: 7, name:'G'},
{id: 8, name:'H'},
{id: 9, name:'I'},
{id: 10, name:'J'},
{id: 11, name:'K'}
];

Now you make the following ng-repeat :

<div ng-repeat="obj in objList | filter:search">
    <div>
     {{obj.id}}     {{obj.name}}
    </div>
</div>

if you then set the search equal to: search.id = 1

You will get the following result:

1 A
10 J
11 K

So i guess my question is how can i avoid this so that the only result that comes is 1 A .

Please note that i do know that in this example i would be able to just search for the name key however the above example is just to make a point.

You can find a fiddle of this issue here:

Fiddle

You should add :true to match exact search.

 ng-repeat="obj in objList | filter:search:true"

 var myApp = angular.module('myApp',[]); //myApp.directive('myDirective', function() {}); //myApp.factory('myService', function() {}); function MyCtrl($scope) { $scope.name = 'Superhero'; $scope.search = {}; $scope.objSelect = [{id: 1, name: 'A'}]; $scope.objList = [ {id: 1, name:'A'}, {id: 2, name:'B'}, {id: 3, name:'C'}, {id: 4, name:'D'}, {id: 5, name:'E'}, {id: 6, name:'F'}, {id: 7, name:'G'}, {id: 8, name:'H'}, {id: 9, name:'I'}, {id: 10, name:'J'}, {id: 11, name:'K'} ]; } 
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div ng-app="myApp" ng-controller="MyCtrl"> <select class="form-control" ng-model="search" ng-options="item.id as item.name for item in objSelect" fix-select-null> <option value=""></option> </select> <div ng-repeat="obj in objList | filter:search:true"> <div> {{obj.id}} {{obj.name}} </div> </div> </div> 

The problem is that you are using a very old version of angularjs wich doesn't support comparator yet. Are you able to upgrade? I believe angularjs v1.2.30 and above already supports comparator otherwise I sugest using a function as the expression for the filterFilter (ie, obj in objList | filter:myFilterExpression where myFilterExpression = function (value) : boolean

Fast Solution

Upgrade angularjs to v1.2.30 at least and use comparator like so:

obj in objList | filter:search:true

Use a function as the expression

obj in objList | filter:myFilter

$scope.myFilter = function (item) {
    return /* my filter criteria */;
};

if you can't get rid of angularjs v1.0.1

You can apply a decorator to the filterFilter within the angularjs module and override the original filter with v1.2.30 filter logic (which by the way, I stole from angularjs repositorie ) that already has the comparator function in it. So that you can use the fast solution without having to upgrade.

 (function() { // begin hack angular.module('ng') .config(['$provide', function($provide) { $provide.decorator('filterFilter', ['$delegate', function($delegate) { var filterFilterv1_0_1 = $delegate; return filterFilterv1_2_30(); }]); }]); function filterFilterv1_2_30() { return function(array, expression, comparator) { if (!angular.isArray(array)) return array; var comparatorType = typeof(comparator), predicates = []; predicates.check = function(value) { for (var j = 0; j < predicates.length; j++) { if (!predicates[j](value)) { return false; } } return true; }; if (comparatorType !== 'function') { if (comparatorType === 'boolean' && comparator) { comparator = function(obj, text) { return angular.equals(obj, text); }; } else { comparator = function(obj, text) { if (obj && text && typeof obj === 'object' && typeof text === 'object') { for (var objKey in obj) { if (objKey.charAt(0) !== '$' && hasOwnProperty.call(obj, objKey) && comparator(obj[objKey], text[objKey])) { return true; } } return false; } text = ('' + text).toLowerCase(); return ('' + obj).toLowerCase().indexOf(text) > -1; }; } } var search = function(obj, text) { if (typeof text === 'string' && text.charAt(0) === '!') { return !search(obj, text.substr(1)); } switch (typeof obj) { case 'boolean': case 'number': case 'string': return comparator(obj, text); case 'object': switch (typeof text) { case 'object': return comparator(obj, text); default: for (var objKey in obj) { if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) { return true; } } break; } return false; case 'array': for (var i = 0; i < obj.length; i++) { if (search(obj[i], text)) { return true; } } return false; default: return false; } }; switch (typeof expression) { case 'boolean': case 'number': case 'string': // Set up expression object and fall through expression = { $: expression }; // jshint -W086 case 'object': // jshint +W086 for (var key in expression) { (function(path) { if (typeof expression[path] === 'undefined') return; predicates.push(function(value) { return search(path == '$' ? value : (value && value[path]), expression[path]); }); })(key); } break; case 'function': predicates.push(expression); break; default: return array; } var filtered = []; for (var j = 0; j < array.length; j++) { var value = array[j]; if (predicates.check(value)) { filtered.push(value); } } return filtered; }; } })();// end hack var myApp = angular.module('myApp', []); //myApp.directive('myDirective', function() {}); //myApp.factory('myService', function() {}); function MyCtrl($scope) { $scope.name = 'Superhero'; $scope.search = {}; $scope.objSelect = [{ id: 1, name: 'A' }]; $scope.objList = [{ id: 1, name: 'A' }, { id: 2, name: 'B' }, { id: 3, name: 'C' }, { id: 4, name: 'D' }, { id: 5, name: 'E' }, { id: 6, name: 'F' }, { id: 7, name: 'G' }, { id: 8, name: 'H' }, { id: 9, name: 'I' }, { id: 10, name: 'J' }, { id: 11, name: 'K' } ]; } 
 <div ng-app="myApp" ng-controller="MyCtrl"> <select class="form-control" ng-model="search" ng-options="item.id as item.name for item in objSelect" fix-select-null> <option value=""></option> </select> <div ng-repeat="obj in objList | filter:search:true"> <div> {{obj.id}} {{obj.name}} </div> </div> </div> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.js"></script> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM