角度过滤对象的多个字符串

时间:2017-01-05 23:36:59

标签: javascript html angularjs arrays json

我有一个JSON格式的数组(项目)。对象项目包含以下字段:

"name":"pname",
"id":"1",
"keywords":"aab bb cc"

我使用

在div标签中显示这些对象
<div ng-repeat="p in projects | filter : searchText">
   {{p.name}}, {{p.id}} etc.
</div>

我将过滤器连接到输入表单ng-model="searchText",并希望使用多个字符串进行搜索。例如搜索:“pname aa bb”应该导致显示上面的项目。

我知道我必须使用自定义过滤器并拆分searchText。但是,用于过滤字符串数组的方法似乎不适用于JSON对象。有什么区别?

尝试简单的字符串数组,例如['aab', 'bb', 'cc']不适用于对象数组:

.filter("myFilter", function(){
return function(input, searchText){
    var returnArray = [];
    var searchTextSplit = searchText.toLowerCase().split(' ');
    for(var x = 0; x < input.length; x++){
        var count = 0;
        for(var y = 0; y < searchTextSplit.length; y++){
            if(input[x].toLowerCase().indexOf(searchTextSplit[y]) !== -1){
                count++;
            }
        }
        if(count == searchTextSplit.length){
             returnArray.push(input[x]);   
        }
    }
    return returnArray;
}
});

如何使其适用于对象?

3 个答案:

答案 0 :(得分:2)

  

但是,用于过滤字符串数组的方法似乎不适用于JSON对象。有什么区别?

expression过滤器的filter参数为string时,Angular会尝试将给定的string仅一个匹配如果匹配的项目属于object类型,则为键值对。

供参考,来自Angular文档:

  

该字符串用于匹配数组的内容。将返回与此字符串匹配的数组中具有字符串属性的所有字符串或对象。这也适用于嵌套对象属性。

您希望的行为是将string多个键值对中的值相匹配。

也就是说,您可以利用expression参数可以传递谓词function来引入更智能的匹配行为。

请参阅我的以下 Plunker 以获取有效的解决方案。它可以进一步优化或调整以处理更多情况,即处理数组值。

关于我的解决方案需要注意的一点是,即使您的对象具有嵌套属性,它也支持匹配术语。

答案 1 :(得分:1)

plunker。您可以加入所有属性值,然后使用正则表达式匹配所有搜索项。我添加了边界条件,即它匹配每个关键字的开头。如果您不想进行边界匹配,可以修改它。

因此,如果您键入pname aa bb ss searchText,您将获得您的对象,因为它匹配所有条款。但是`pname aa zz'不会返回你的对象。

app.filter('myFilter', ['$filter', function($filter) {
    var buildMatchingString = function(object) {
        var matchingString = '';
        // Join all the property values into 1 string separated by a 'space'
        // so that we can do boundary matching
        angular.forEach(object, function(prop, key) {
            matchingString += ((prop || '') + ' ');
        });
        return matchingString;
    };

    return function(list, searchText) {
        if (!searchText) {
          // Return everything if there is no user input
            return list;
        }
        var result = [];
        // Split all the search terms
        var keywords = searchText.split(' ');

        return $filter('filter')(list, function(elem) {
            var matchingString = buildMatchingString(elem);
            // Check that the properties of the object matches the
            // beginning of ALL the search terms
            for(var i = 0; i < keywords.length; i++) {
                if (!matchingString.match(new RegExp('\\b' + keywords[i] + '.*', 'gi'))) {
                    return false;
                }           
            }
            return true;
        });
    };
}]);

答案 2 :(得分:0)

您可以在自定义过滤器内部使用角度的 $ filter 功能。

app.filter('myFilter', ['$filter', function($filter){
    return function(data, text){
        var textArr = text.split(' ');
        angular.forEach(textArr, function(test){
            if(test){
                data = $filter('filter')(data, test);
            }
        });
        return data;
    }
}]);

然后将 searchText 作为参数传递给自定义过滤器,例如

<li ng-repeat="obj in objects | myFilter:searchText">{{obj.name}}</li>