【问题标题】:Angular ui-select filtering only one fieldAngular ui-select 仅过滤一个字段
【发布时间】:2015-01-22 02:35:30
【问题描述】:

情况:

我有一个 Angular 应用程序,它使用 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>

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


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


问题:

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

非常感谢!

【问题讨论】:

  • @hanu 只是想知道,您是否为 propsFilter 实现了自定义 javascript 函数?它不会单独工作 (see line 83)。我还没有尝试使用它,但似乎很多人不知道他们必须包含 javascript 代码。
  • 是的,它必须包含在指令中。谢谢指出。

标签: javascript angularjs filter angular-ui


【解决方案1】:

您可以使用如下属性过滤器

 <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 的任何字符之间使用多个空格进行搜索。

【讨论】:

    【解决方案2】:

    可能是因为相同的值 ($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}">
    ...
    

    【讨论】:

    • 抱歉,这应该如何工作? $select.search 是具有单个文本值的属性。
    • filter: {name: $select.search, email: $select.search}.. 对我来说很好..
    【解决方案3】:

    我看到过一些类似 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 表示角度)。这是一个国家/国家的下拉列表,国家作为国家的子对象。

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

    【讨论】:

    • 你做了递归的吗?
    • 我还没做,对不起!我已设法将所有列表子对象缩小到较小的大小。
    【解决方案4】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-10
      • 2015-06-18
      • 1970-01-01
      • 2014-09-12
      • 1970-01-01
      • 2011-03-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多