Javascript Angular ui-select 只过滤一个字段

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27103867/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 23:43:10  来源:igfitidea点击:

Angular ui-select filtering only one field

javascriptangularjsfilterangular-ui

提问by FrancescoMussi

THE SITUATION:

情况:

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

我有一个 angular 应用程序,使用angular ui-select从数据库中搜索和选择人员。

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:

尝试使用来自角度样本的PROPSFILTER :

 <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:

在这种情况下,它完全崩溃了,select2 中不再有数据,我在控制台中收到一些错误:

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!

非常感谢!

采纳答案by T4deu

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

也许是因为相同的值($select.search) 用于过滤器电子邮件和名称。

<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}">
...

回答by kunsingh

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:

您必须像下面这样修改 propertyFilter:

.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.

可以对整个选项值进行搜索。例如,如果在选项中你有 'peter parker' 那么你可以用 'peter', 'parker', 'peter parker', 'peterparker' 进行搜索,甚至可以在 peter parker 的任何字符之间搜索多个空格。

回答by dbmuller

I've seen a few floating around like the answer from kunsingh, which got me started to solve my similar problem. In my case it was searching multiple and in objects, but I also send logically deleted records to the client and optionally filter them in lists. For dropdowns I wanted that always removed without having to alter the API.

我已经看到一些像 kunsingh 的答案一样漂浮,这让我开始解决我的类似问题。就我而言,它正在搜索多个对象,但我也将逻辑删除的记录发送到客户端,并可选择在列表中过滤它们。对于下拉菜单,我希望它总是被删除而不必更改 API。

Here's my altered version, which includes searching on objects. Obviously this will only work if all your tables have an int column called Deleted (For me is part of the unique key and set to the identity value when deleted), and you pass it to the client.

这是我修改过的版本,其中包括搜索对象。显然,这只有在所有表都有一个名为 Deleted 的 int 列(对我来说是唯一键的一部分并在删除时设置为标识值)时才有效,并且您将它传递给客户端。

At a later point I plan to alter further to allow recursive searching of objects.

稍后我计划进一步更改以允许递归搜索对象。

App.filter('dropdownFilter', function () {
    return function (items, props: Object, keyvalue?) {
    var out = [];

        if (angular.isArray(items)) {
            items.forEach(function (item) {
                var itemMatches = false;
                var canbreak = false;

                // Filter out logically deleted records
                if (item.Deleted != 0)
                    itemMatches = false;
                else {
                    var keys = Object.keys(props);

                    for (var i = 0; i < keys.length; i++) {
                        var prop: string = keys[i];
                        var text = "";
                        // If an object, e.g. searching deep, such as Project: {ProjectName: $select.search}
                        // Then iterate through the object to find values.  
                        // NOTE: This one searches one deep from each object,
                        // e.g. Project.ProjectName
                        //      Project.User.LastName WILL NOT WORK.
                        if (angular.isObject(props[prop])) {
                            angular.forEach(props[prop], function (value, key) {
                                text = value.toLowerCase();
                                if (item[prop][key].toLowerCase().indexOf(text) !== -1) {
                                    itemMatches = true;
                                    canbreak = true;
                                }
                            });
                            if (canbreak)
                                break;
                        }
                        // If it's a simple array, then woo!
                        else {
                            text = props[prop].toLowerCase();
                            if (item[prop] != undefined && item[prop].toString().toLowerCase().indexOf(text) !== -1) {
                                itemMatches = true;
                                break;
                            }
                        }
                    }
                }

                if (itemMatches) {
                    out.push(item);
                }
            });
        }
        else {
            // Let the output be the input untouched
            out = items;
        }

    return out;
    }
});

and a sample of it in use (using select2 for angular). This is a dropdown of state/country with country as a sub-object of state.

以及使用中的示例(使用 select2 为角度)。这是州/国家的下拉列表,国家是州的子对象。

<ui-select ng-model="personneladdress.StateID" theme="select2" class="select2">
    <ui-select-match placeholder="{{language.State}}">{{$select.selected.StateName}}</ui-select-match>
    <ui-select-choices repeat="item.StateID as item in State | dropdownFilter: {StateName: $select.search, Country: {CountryName: $select.search}}">
        <span ng-bind-html="item.StateName | highlight: $select.search"></span><br />
        <small>
            <span ng-bind-html="''+item.Country.CountryName | highlight: $select.search"></span>
        </small>
    </ui-select-choices>
</ui-select>

回答by Pasha GR

I solved this problem by using this piece of code :

我通过使用这段代码解决了这个问题:

<ui-select-choices repeat="person2 in list_people | filter: $select.search" >

In ui-select-match I use two fields :

在 ui-select-match 我使用两个字段:

<ui-select-match placeholder="select One...">
   {{$item.field1}} - {{$item.field2}}
</ui-select-match>