Angular ui-select只过滤一个字段

时间:2014-11-24 11:34:42

标签: javascript angularjs filter angular-ui

情况:

我有一个使用angular ui-select的角度应用来搜索和选择数据库中的人。

除了一件事,它工作正常。 用户应该能够使用两个标准在人员之间进行过滤:名称和电子邮件。

使用普通角度滤波器,我只能过滤其中一个。 如果我尝试过滤这两个字段,它就不再起作用了。

一个字段的工作示例:

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


在过滤器中没有两个字段的工作示例:

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

奇怪的是,它实际上只适用于第一个角色。 当我键入第一个字符时,它会在两个字段,名称和电子邮件中突出显示它。 但是当我键入第二个字符时,它就不再起作用了 (我在控制台中没有出错)。


ATTEMP使用来自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>

在这种情况下,它完全破坏了,select2中没有数据,我在控制台中出现了一些错误:

Cannot read property 'toString' of null

Cannot read property 'length' of undefined


问题:

如何在多个字段之间进行过滤? 我可以使用普通过滤器吗? 或者我必须使用自定义过滤器? 但在这种情况下,为什么不能正常工作?

非常感谢!

4 个答案:

答案 0 :(得分:9)

您可以使用下面的属性过滤器

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

您必须修改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;
    };
})

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

答案 1 :(得分:6)

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

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

这也将解释为什么它只适用于第一个角色。

为每个过滤器使用单独的值来解决此问题:

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

答案 2 :(得分:1)

我已经看到一些像kunsingh的回答一样漂浮在周围,这让我开始解决我的类似问题。在我的情况下,它搜索多个和对象,但我也发送逻辑删除的记录到客户端,并可选择在列表中过滤它们。对于下拉列表,我希望始终将其删除,而无需更改API。

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

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

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;
    }
});

并使用它的一个样本(使用select2 for angular)。这是一个州/国家的下拉列表,国家/地区是国家的子对象。

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

答案 3 :(得分:0)

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

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

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

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