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