在我的模型中,我的数据类似于:
$scope.list = [{id:0,tags:['tag1','tag2']},{id:2,tags:['tag2']}};
我想用复选框显示标签列表(包含'tag1'和'tag2'的唯一值)。希望如下:
<div ng-repeat="tag in list.tags">
<label class="checkbox">
<input type="checkbox" ng-model="filter.tag" />
{{tag}}
</label>
</div>
我知道如何根据已检查的内容过滤主列表,如果我对列表进行硬编码,而不是如何自动生成唯一标记列表。
答案 0 :(得分:26)
您正在寻求执行三项操作:
$scope.list
您可以使用纯JavaScript执行此操作,但为了简化操作,我建议使用Underscore,这是一个库,可让您访问许多用于操作和检查数组,对象等的函数。
让我们从这段代码开始:
$scope.list = [
{id: 0, tags: ['tag1', 'tag2']},
{id: 1, tags: ['tag2']},
{id: 2, tags: ['tag1', 'tag3', 'tag4']},
{id: 3, tags: ['tag3', 'tag4']}
];
现在,让我们执行第一个操作:从tags
中的每个对象的$scope.list
属性中获取数组。 Underscore提供了pluck
方法,这正是我们所需要的。
采摘
_.pluck(list, propertyName)
可能是map最常见的用例的便捷版本:提取属性值列表。
使用pluck,我们可以得到以下结果:
var tags = _.pluck($scope.list, 'tags');
// gives us [['tag1', 'tag2'], ['tag2'], ['tag1', 'tag3', 'tag4'], ['tag3', 'tag4']]
现在,我们想要展平该数组。
展平
_.flatten(array, [shallow])
展平嵌套数组(嵌套可以是任何深度)。如果你传递浅,那么数组只会被压平一个级别。
tags = _.flatten(tags);
// gives us ['tag1', 'tag2', 'tag2', 'tag1', 'tag3', 'tag4', 'tag3', 'tag4']
最后,您只需要每个标记的一个实例。
uniq
_.uniq(array, [isSorted], [iterator])
别名:unique
使用===生成数组的无副本版本,以测试对象相等性。如果您事先知道数组已排序,则为isSorted传递true将运行更快的算法。如果要根据转换计算唯一项,请传递迭代器函数。
tags = _.unique(tags)
// gives us ['tag1', 'tag2', 'tag3', 'tag4']
我们可以将这些与Underscore的有用chain
方法结合在一起,将这些组合在一起。让我们在返回唯一标记的范围上创建一个函数:
$scope.uniqueTags = function() {
return _.chain($scope.list)
.pluck('tags')
.flatten()
.unique()
.value();
};
由于这是一个函数,因此无论我们是否在$scope.list
之后添加或删除项目,它都将始终返回唯一标记。
现在,您可以使用ng-repeat
上的uniqueTags
来显示每个代码:
<div ng-repeat="tag in uniqueTags()">
<label class="checkbox">
<input type="checkbox" ng-model="filter.tag" />
{{tag}}
</label>
</div>
这是一个有效的jsFiddle演示了这种技术:http://jsfiddle.net/BinaryMuse/cqTKG/
答案 1 :(得分:3)
使用自定义过滤器获取唯一的标记集/数组,适用于ng-repeat:
.filter('uniqueTags', function() {
return function(list) {
var tags = {};
angular.forEach(list, function(obj, key) {
angular.forEach(obj.tags, function(value) {
tags[value] = 1;
})
});
var uniqueTags = []
for (var key in tags) {
uniqueTags.push(key);
}
return uniqueTags;
}
});
我首先将标签放入一个对象中,这会自动赋予我们唯一性。然后我将它转换为数组。
使用如下:
<div ng-repeat="tag in list | uniqueTags">
以下情况可能与我认为您可能不希望/希望它做的事情有关:
<input type="checkbox" ng-model="filter.tag">
这不会在控制器范围(即使用ng-repeat的范围)上创建$ scope属性filter.tag1
和filter.tag2
。 ng-repeat的每次迭代都会创建自己的子范围,因此上面的ng-model将在每个ng-repeat子范围上创建范围属性filter.tag
,如我的小提琴所示。