0

Here is the simple scenario of an Angularjs filter in template:

<input ng-model="query">         
<li ng-repeat="item in filtered = (prosItems.results |filter:mySearch)">

Because I need to filter on specific fields only from prosItems.results, i created in the controller a specific function:

$scope.mySearch = function (item){
            if ($scope.query) {
                var searchTerm = $scope.query.toLocaleLowerCase();
                return item.firstName.toLowerCase().indexOf(searchTerm)!==-1 ||
                    item.lastName.toLowerCase().indexOf(searchTerm)!==-1 ||
                    item.company.toLowerCase().indexOf(searchTerm)!==-1 ||
                    item.city.toLowerCase().indexOf(searchTerm)!==-1   ||
                    item.state.toLowerCase().indexOf(searchTerm)!==-1    ||
                    item.country.toLowerCase().indexOf(searchTerm)!==-1;
            } else {
                return true;
            }
        };

Problem is when any property of an iteration is undefined, for example if user hasn't specified a "company" on an entry, I will get that error as soon as I type something in the input field:

Cannot call method 'toLowerCase' of undefined

I could imagine solution if I had only one property to iterate trough, but since i have several, I don't see practical way of doing so. Do you see any way to solve this issue practically ?

2 Answers 2

2

what about something like this:

var fields = ['firstName', 'lastName', 'company', 'etc'];
for(var i = 0, l = fields.length; i < l; i ++){
   if(item[fields[i]] && item[fields[i]].toLowerCase().indexOf(searchTerm)!==-1){
       return true;
   }
}
return false; 
Sign up to request clarification or add additional context in comments.

6 Comments

Nice. Could even remove the hasMatch variable and replace with 'return true' or 'return false' as appropriate.
that seems to do the job also tks
@GruffBunny yea, good point. Some linter I was using in another language... ActionScript maybe? Was always yelling at me not to return from inside a loop. I forget why.
works like a charm, but a general question: the "return true" returns a boolean for each matching case, or the corresponding items themselves ?
The filter only needs to return true once, if any of the conditions are met. So as soon as it hits "return true;" the loop will stop and the function is done.
|
0

I tried dead simple:

$scope.mySearch = function (item){
            if ($scope.query) {
                var searchTerm = $scope.query.toLocaleLowerCase();
                var  city = item.city || 'null',
                    state = item.state ||  'null',
                    company = item.company || 'null',
                    country = item.country || 'null';
                return item.firstName.toLowerCase().indexOf(searchTerm)!==-1 ||
                    item.lastName.toLowerCase().indexOf(searchTerm)!==-1 ||
                    company.toLowerCase().indexOf(searchTerm)!==-1 ||
                    city.toLowerCase().indexOf(searchTerm)!==-1 ||
                    state.toLowerCase().indexOf(searchTerm)!==-1 ||
                    country.toLowerCase().indexOf(searchTerm)!==-1;
            } else {
                return true;
            }
        };

seems to do the job, but is it good practice ?

1 Comment

No, for a few reasons. What if someone searches for things starting with "nu"... 'null'.indexOf('nu') would return 0... or anything with 'll' etc.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.