问题
I have some trouble with filtering JSON data by tags with AngularJS. I tried this slightly modified filter by ExpertSystem (Apply dynamic filters using Tags) here:
groupifyApp.filter('filterByTags', function () {
return function (items, tags) {
var filtered = [];
if (tags.length == 0) {
filtered = items;
}
(items || []).forEach(function (item) {
var matches = tags.some(function (tag) {
return (item.data1.indexOf(tag.text) > -1) || (item.data2.indexOf(tag.text) > -1);
});
if (matches) {
filtered.push(item);
}
});
return filtered;
};
});
And in my HTML:
<tags-input ng-model="searchTags" type="text" placeholder="Search tags">
<auto-complete source="allTags()"></auto-complete>
</tags-input>
Model: {{searchTags}}
<br />
<table class="table table-hover">
<thead>
<th>Group name</th>
<th>Tags</th>
<th>Type</th>
<th>Looking for</th>
<th class="col-sm-1"> </th>
</thead>
<tr ng-repeat="match in allGroups | filterByTags:searchTags">
<td>{{match.name}}</td>
<td>
<ul>
<li ng-repeat="tag in match.tags">{{tag}}</li>
</ul>
</td>
<td>{{match.type}}</td>
<td>
<ul>
<li ng-repeat="deficit in match.deficits">{{deficit}}</li>
</ul>
</td>
<td>
<button class="btn btn-sm btn-default"><span class="glyphicon glyphicon-hand-left"></span></button>
</td>
</tr>
</table>
The JSON look like that:
[
{name: "Elite", type: "Learning", tags: ["RWTH", "Aachen"], competences: ["Complexity"], deficits: ["Java"], members: ["Niklas", "Marv"]},
{name: "Old Boys", type: "Assignments", tags: ["FH", "Aachen"], competences: ["Java"], deficits: ["AAT"], members: ["Joel", "Joel's Sister"]}
];
Unfortunately the table isn't filtered. It always prints out the whole table (even w/o my modification). I guess I have todefine which column shall be filtered, but I'm not really familiar with AngularJS or JavaScript at all. So any suggestions?
回答1:
You have to change your item types in filter function.
groupifyApp.filter('filterByTags', function () {
return function (items, tags) {
var filtered = [];
(items || []).forEach(function (item) {
var matches = tags.some(function (tag) {
return (item.name.indexOf(tag.text) > -1) ||
(item.type.indexOf(tag.text) > -1) ||
(item.tags.indexOf(tag.text) > -1) ||
((item.competences).indexOf(tag.text) > -1) ||
((item.members).indexOf(tag.text) > -1) ||
(item.deficits.indexOf(tag.text) > -1);
});
if (matches) {
filtered.push(item);
}
});
if (tags.length == 0) {
filtered = items;
}
return filtered;
};
});
Hope this helps. Btw If your object is integer, you have to change object type to string. To be specific:
{name: "Elite", age: 18, type: "Learning", tags: ["RWTH", "Aachen"], competences: ["Complexity"], deficits: ["Java"], members: ["Niklas", "Marv"]},
((item.age+"").indexOf(tag.text) > -1) ||
回答2:
I would just chain the promise you get back from wherever. I HTML you'll have the auto-complete directive within the tags input. 'filter.values' is the list of tags that have been filled in.
<tags-input ng-model="filter.values">
<auto-complete load-on-down-arrow="true"
debounce-delay="0"
min-length="1"
source="getTagsFromAPI ($query, filter.id)">
</auto-complete>
</tags-input>
I have a service which I called 'filterService' which has a function 'getAutoCompleteList', which returns all possible values from the API:
$scope.getTagsFromAPI = function($query, filterId) {
return filterService.getAutoCompleteList(filterId).then(function(result) {
return _.filter(result, function(q){
return _.contains(q.text, $query);
});
});
};
This function returns a promise, and I resolve the promise by adding '.then()' after is. I then use underscore to filter the result according to the '$query' passed in. You could also loop through the list yourself and compare, but I like to use underscore for this. Since the promises have been chained, I can then simply return the result.
来源:https://stackoverflow.com/questions/28220994/filter-ngtagsinput-in-angularjs