使用ko.utils.arrayfilter根据内部集合的值返回集合

时间:2013-10-31 15:14:33

标签: json knockout.js

我正在使用knockout并希望使用arrayFilter来返回属性"修改的对象数组"另一个数组内部的值为true。

即。 我的json对象看起来像

Family tree
Family{
  LastName=Smith
  Children{
    Name=bob,
    Modified=false},
   {
    Name=tom, Modified=true}
 }
Family{
  LastName=Jones
  Children{
    Name=bruno,
    Modified=false},
   {
    Name=mary, Modified=false}
 }

数组过滤器的结果将是(如下)因为孩子汤姆已经修改= true

FamilyTree
  Family{
  LastName=Smith
  Children{
    Name=bob,
    Modified=false},
   {
    Name=tom, Modified=true}
 }

这可能吗?

2 个答案:

答案 0 :(得分:4)

我认为@ pax162提供的解决方案可能会回答您的问题。但是,存在使用问题。建议的解决方案将执行嵌套迭代。如果您只希望处理数据一次(而不是驱动一些富客户端视图),这就是采取的方法。另一方面,如果要将此数据绑定到视图,则可以考虑采用另一种类似KO的方法。这就是我的想法:

var family = function(data){
    var self = {
        LastName :ko.observable(data.LastName),
        Children : ko.observableArray( data.Children || [])
    };

    family.hasModifiedChildren = ko.computed(function() {
        return ko.utils.arrayFirst(this.Children(), 
            function(child) {
                return child.Modified === true;
            }) !== null;
    }, family);

    return self;
}

不是使用JSON数据,而是创建可观察的JS对象:

var families = return ko.utils.arrayMap(familiesJson, family);
// or, if you need an observable:
families = ko.observableArray(ko.utils.arrayMap(familiesJson, family));

最后,获取具有修改过的子项的家庭列表,如下所示:

var familiesWithModifiedChildren = ko.computed(function() { 
    return ko.utils.arrayFilter(families, function(fam) {
        return fam.hasModifiedChildren();
    });
});

如果您要构建实时更新页面,则需要使用此样式的视图模型。这将允许Knockout利用其观察器优化,而不是每次评估函数时构建一个新数组。希望这有帮助!

答案 1 :(得分:1)

如果您只希望获得至少有一个经过修改的孩子的家庭,您可以这样做(http://jsfiddle.net/MAyNn/3/)。 json无效,稍微改了一下。

 var families = [
{
    LastName :"Smith",
    Children : [{
    Name:"bob",
    Modified:false},
   {
       Name:"tom", Modified :true}
 ]
},
{
    LastName :"Jones",
    Children : [{
    Name:"bruno",
    Modified:false},
   {
       Name:"mary", Modified :false}
 ]
}   
 ];

var filteredFamilies = ko.utils.arrayFilter(families, function(family){
    var hasModified = false;
    var first = ko.utils.arrayFirst(family.Children, function(child){
        return child.Modified;
    })
    if (first) {
        hasModified = true;
    }

    return hasModified;
})

console.log(families);
console.log(filteredFamilies);