我在AngularJS中有一个基本的应用程序。该模型包含许多项目以及这些项目的关联标记。我想要实现的是能够过滤显示的项目,以便只显示那些带有一个或多个活动标签的项目,但是我没有太多的运气来弄清楚如何从视图中操作模型。
JS可在http://jsfiddle.net/Qxbka/2获得。这包含我迄今为止设法达到的状态,但我有两个问题。首先,该指令尝试在控制器中调用方法toggleTag()
:
template: "<button class='btn' ng-repeat='datum in data' ng-click='toggleTag(datum.id)'>{{datum.name}}</button>"
但是没有调用该方法。其次,我不确定如何更改输出部分的ng-repeat
,以便它只显示带有一个或多个活动标记的项目。
关于我做错了什么以及如何让这个工作的任何指示都将非常感激。
更新 我更新了指令中的方法以直接传递数据项,即
template: "<button class='btn' ng-repeat='datum in data' ng-click='toggle(data, datum.id)'>{{datum.name}}</button>"
并在指令中创建了toggle()
方法。通过这样做,我可以操纵data
并且它反映在状态HTML中,但是我会感谢任何反馈,如果这是正确的方法来做到这一点(对我来说这感觉不太合适)。 / p>
仍然坚持在更新标签值时如何重新评估输出。
答案 0 :(得分:1)
您可以在ng-repeat
上使用过滤器(docs):
<li ng-repeat="item in items | filter:tagfilter">...</li>
过滤器表达式的参数可以是很多东西,包括范围上的函数,它将为数组中的每个元素调用一次。如果它返回true,则元素将显示,如果返回false,则不显示。
您可以这样做的一种方法是在示波器上设置selectedTags
数组,通过观察tags
数组填充该数组:
$scope.$watch('tags', function() {
$scope.selectedTags = $scope.tags.reduce(function(selected, tag) {
if (tag._active) selected.push(tag.name);
return selected;
}, []);
}, true);
最后的额外true
使得角度通过平等与参考(我们想要的)进行比较,因为我们需要它来观察每个标签上的_active
属性。
接下来,您可以设置过滤功能:
$scope.tagfilter = function(item) {
// If no tags are selected, show all the items.
if ($scope.selectedTags.length === 0) return true;
return intersects($scope.selectedTags, item.tags);
}
使用快速而脏的辅助函数intersects
返回两个数组的交集:
function intersects(a, b) {
var i = 0, len = a.length, inboth = [];
for (i; i < len; i++) {
if (b.indexOf(a[i]) !== -1) inboth.push(a[i]);
}
return inboth.length > 0;
}
我forked your fiddle here表明了这一点。
关于这种方式的一个小问题是项目有一组标记“名称”而不是ID。因此,此示例仅适用于标记名称数组(我必须编辑一些初始数据以使其保持一致)。