在AngularJS中链接MVC

时间:2013-02-15 12:45:08

标签: angularjs angularjs-directive

我在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>

仍然坚持在更新标签值时如何重新评估输出。

1 个答案:

答案 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。因此,此示例仅适用于标记名称数组(我必须编辑一些初始数据以使其保持一致)。