Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular ui-select filtering only one field

THE SITUATION:

I have an angular app using angular ui-select to search and select people from a database.

It is working fine, except one thing. The user should be able to filter among the people using two criteria: name and email.

Using the normal angular filter I am able to filter only one of them. If I try to filter both fields, it does not work anymore.

WORKING EXAMPLE WITH ONE FIELD:

 <ui-select multiple ng-model="database_people.selectedPeople" theme="select2" ng-disabled="disabled" style="width:100%">

    <ui-select-match placeholder="Select person...">{{$item.name}} &lt; {{$item.email}} &gt;</ui-select-match>

    <ui-select-choices repeat="person2 in list_people | filter: {name: $select.search, db_data_type_id: 5}">

            <div ng-bind-html="person2.name | highlight: $select.search"></div>

                <small>
                    email: <span ng-bind-html="''+person2.email | highlight: $select.search"></span>
               </small>

    </ui-select-choices>

 </ui-select>


NOT WORKING EXAMPLE WITH TWO FIELDS IN THE FILTER:

 <ui-select multiple ng-model="database_people.selectedPeople" theme="select2" ng-disabled="disabled" style="width:100%">

    <ui-select-match placeholder="Select person...">{{$item.name}} &lt; {{$item.email}} &gt;</ui-select-match>

    <ui-select-choices repeat="person2 in list_people | filter: {name: $select.search, email: $select.search, db_data_type_id: 5}">

            <div ng-bind-html="person2.name | highlight: $select.search"></div>

                <small>
                    email: <span ng-bind-html="''+person2.email | highlight: $select.search"></span>
               </small>

    </ui-select-choices>

 </ui-select>

The strange thing is that it actually works BUT only for the first character. When I type the first character it highlights it in both fields, name and email. But when I type the second character it does not work anymore (I got no error in console).


ATTEMP USING PROPSFILTER FROM ANGULAR SAMPLES:

 <ui-select multiple ng-model="database_people.selectedPeople" theme="select2" ng-disabled="disabled" style="width:100%">

    <ui-select-match placeholder="Select person...">{{$item.name}} &lt; {{$item.email}} &gt;</ui-select-match>

    <ui-select-choices repeat="person2 in list_people | propsFilter: {name: $select.search, email: $select.search, db_data_type_id: 5}">

            <div ng-bind-html="person2.name | highlight: $select.search"></div>

                <small>
                    email: <span ng-bind-html="''+person2.email | highlight: $select.search"></span>
               </small>

    </ui-select-choices>

 </ui-select>

In this case it broke completely, there is no data anymore in the select2 and I get some errors in the console:

Cannot read property 'toString' of null

Cannot read property 'length' of undefined


THE QUESTION(S):

How can I filter among mulitple fields? Can I do that using normal filter? Or I have to use a custom filter? But in this case, why is not working properly?

Thank you very much!

like image 815
FrancescoMussi Avatar asked Nov 24 '14 11:11

FrancescoMussi


2 Answers

You can use property filter like below

 <ui-select   ng-model="emplyee" theme="bootstrap">
 <ui-select-match placeholder="Select ...">{{$select.selected.firstName+" "+$select.selected.lastName}}</ui-select-match>
 <ui-select-choices repeat="emp in employees | propertyFilter: {firstName:$select.search, lastName:$select.search}">
 <span ng-bind-html="emp.firstName+' '+emp.lastName | highlight: $select.search"></span>
 </ui-select-choices>

You will have to modify the propertyFilter like below:

.filter('propertyFilter', function($log) {
 return function(items, props) {
    var out = [];
    if (angular.isArray(items)) {
    items.forEach(function(item) {
        var itemMatches = false;
        var keys = Object.keys(props);
        var optionValue = '';
        for (var i = 0; i < keys.length; i++) {
             optionValue = item[keys[i]] ? optionValue + item[keys[i]].toString().toLowerCase().replace(/ /g, '') : '';
        }
        for (var j = 0; j < keys.length; j++) {
            var text = props[keys[j]].toLowerCase().replace(/ /g, '');
            if (optionValue.indexOf(text) !== -1) {
               itemMatches = true;
               break;
            }
        }
        if (itemMatches) {
            out.push(item);
        }
        });
        } else {
            // Let the output be the input untouched
            out = items;
        }

        return out;
    };
})

Search can be done on the options value as a whole. For example if in options you have 'peter parker' then you can search with 'peter', 'parker','peter parker', 'peterparker' and even search with multiple spaces in between any character of peter parker.

like image 99
kunsingh Avatar answered Sep 19 '22 07:09

kunsingh


Maybe it's because the same value($select.search) is used for both filters email and name.

<ui-select-choices repeat="person2 in list_people | filter: {name: $select.search, email: $select.search, db_data_type_id: 5}">
...

This will also explains, why it only works with the first character.

Use separate values for each filter to fix this:

<ui-select-choices repeat="person2 in list_people | filter: {name: $select.search.name, email: $select.search.email, db_data_type_id: 5}">
...
like image 45
T4deu Avatar answered Sep 18 '22 07:09

T4deu