How does filter work in AngularJS?

强颜欢笑 提交于 2019-12-07 03:57:27

问题


I have a table generated with ng-repeat (from an objects' array).

I would like to filter it with a search text field.

Objects contained in my array has got deep properties.

I don't know why and how, but the filter is only working on email field, which is as deep as other properties.

I'm using this search form :

<input type="text" name="search" ng-model="searchText" />
...
<tr ng-repeat="x in obj | filter:searchText track by $index">
  ...
</tr>

plunker

EDIT :

This answer helps me to understand why it's not working. Someone knows how I can bypass the $ verification in filter ?

I'm using $ because I'm following the Google Contact API format.


回答1:


email works because nested property address doesn't contain any $ char.

Unfortunately, I don't think there is a way to bypass this behavior, however you can make your own filter and use it in ng-repeat.

This is simple example that should work for you:

JS

app.filter('customFilter', function() {
  return function(items, keyword) {
    if (!keyword || keyword.length === 0) return items;

    return items.filter(function(item){
      var phrase = keyword.$.toLowerCase();
      return item.gd$name.gd$fullName.$t.toLowerCase().includes(phrase) || 
        item.gd$name.gd$familyName.$t.toLowerCase().includes(phrase) || 
        item.gd$name.gd$givenName.$t.toLowerCase().includes(phrase) ||
        item.gd$email[0].address.toLowerCase().includes(phrase) ||
        item.gd$phoneNumber[0].$t.toLowerCase().includes(phrase) ||
        (!!item.gd$organization[0].gd$orgTitle && item.gd$organization[0].gd$orgTitle.$t.toLowerCase().includes(phrase)) ||
        (!!item.gd$organization[0].gd$orgName && item.gd$organization[0].gd$orgName.$t.toLowerCase().includes(phrase));
    });
  }
});

HTML

<tr ng-repeat="x in obj | customFilter:searchText">

Of course, you will have to add more checks for possible null values. I've just wanted to make it work on the data you've provided.

Hope, you'll find it useful.

Here's plunk




回答2:


You can check the source code of ngFilter here It is set to ignore keys starting with $ as it's a prefix used by AngularJS for public ($) and private ($$) properties.




回答3:


$ is a prefix used by Angular internal properties. For technical reasons, Angular prevents you to use it. Here is a workaround to deal with $ properties names without changing your JSON object:

You can iterate in ng-repeat over Object.keys($scope.object) instead $scope.object.

Demo on JSFiddle




回答4:


Since it is clear that we can change neither third party API nor AngularJS library code, we could go for modifying the object keys to not have $ in the beginning. But, since the data has so many of them at multiple level, let's do it recursively! :)

Here's how. I would remap each object in $scope.obj array to call a function:

$scope.obj = $scope.obj.map(function(cur) {
  return renameKey(cur)
})

Now, inside renameKey, it would check whether it's an Array or Object using helper functions and call itself recursively while replacing the keys prepending x for the strings starting with $

function renameKey(cur) {
  if(isArray(cur)) {
    cur.forEach(function(obj) {
      obj = renameKey(obj)
    })
  } else if (isObject(cur)) {
    for (let key in cur) {
      if(key.charAt(0) === '$') {
        cur['x'+key] = cur[key];
        delete cur[key];
      }
      cur[key] = renameKey(cur[key])
    }
  } 
  return cur
}

function isObject(obj) {
   return obj && (typeof obj === "object");
}

function isArray(obj) { 
  return isObject(obj) && (obj instanceof Array);
}

Looks little tedius but it does work! Now, all we need to do is have x$t instead of $t in the HTML, and boom!

working plunker




回答5:


I can't comment because my reputation is less than 50 but as far as i can tell it's any property that has a $ in it's name is not used in the filter.. I tried changing the property names and this fixed the issue. Realise you may or may not have control over this.




回答6:


Suppose your obj is as below:

$scope.obj=[{firstName:'Jeet',lastName:'kumar'},{firstName:'test1',lastName:'dev'},{firstName:'test2',lastName:'other'}];

Search input box

<input type="text" name="search" ng-model="searchText" />

Datatable filter by index 'firstName'

<tr ng-repeat="x in obj | filter:{firstName:searchText}">
 <td>{{x.firstName}}</td>
<td>{{x.lastName}}</td>
</tr>

Datatable filter over all index

<tr ng-repeat="x in obj | filter:searchText">
 <td>{{x.firstName}}</td>
<td>{{x.lastName}}</td>
</tr>

Desc:

filter:{name:searchText}
filter on the basis of 'firstName' index from your $socpe.obj array


来源:https://stackoverflow.com/questions/43735702/how-does-filter-work-in-angularjs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!