淘汰树 - 获取树中的所有选定项目

时间:2014-05-20 19:29:43

标签: arrays knockout.js

Here's the fiddle

我有一个客户端的树结构,我绑定到一个无序列表,每个客户端可能有也可能没有SubClient。我已添加了在列表中选择项目的功能,但现在我无法弄清楚如何遍历树并获取所有选定项目的数组。

特别是,这只野兽是我遇到问题的地方:

cp.GetSelectedClientsArray = function (clients) {
    var selected = [];
    ko.utils.arrayForEach(clients, function (item) {
        if (item.IsSelected()) {
            selected.push(item.ClientName());
        }
        ko.utils.arrayForEach(item.SubClient(), function (subItem) {
            if (subItem.IsSelected()) {
                selected.push(subItem.ClientName());
            }
            cp.GetSelectedClientsArray(subItem);
        });
    });
    console.log(selected);
    return selected;
};

在我切换IsSelected()observable后,我想遍历列表并获得一个只包含所选项的数组。

我写过并重写了这几次,并且可以真正使用一些帮助。我甚至不确定如何编写一个可以工作的递归函数,因为每次我从内部调用函数时,它会清除我的“选定”数组并将其设置为全局变量保留所有已选中的项目数组。

感谢任何帮助

4 个答案:

答案 0 :(得分:2)

这是递归版

cp.GetSelectedClientsArray = function (clients) {
    var result = [];
    function GetSelected(clients){
        for (var i in clients){
            if(clients[i].IsSelected()){
                result.push(clients[i].ClientName());
            }
            GetSelected(clients[i].SubClient());
        }
    }
    GetSelected(clients);
    console.log(result);
    return result;
};

请参阅jsfiddle

答案 1 :(得分:1)

为什么只需在View-Model上创建SelectedClients字段,并在切换时删除/添加字段,就可以递归地遍历客户列表?

例如:

_self.SelectedClients = ko.observableArray([]);

_self.ToggleSelectedUser = function (data, event) {
    var toggle = !data.IsSelected();
    data.IsSelected(toggle);

    if (toggle)
        _self.SelectedClients.push(data.ClientName());
    else
        _self.SelectedClients.remove(data.ClientName());
};

请参阅Fiddle

<强>更新

根据你的评论,当你需要递归地在树上行走时,你可以尝试这样的事情:

function AggregateSelectedClients(clients, results)
{
    results = results || [];
    if (!clients || !clients.length) return results;

    ko.unwrap(clients).forEach(function(v, i)
                    {
                    var selected = ko.unwrap(v.IsSelected);
                    var subClients = ko.unwrap(v.SubClient);

                    if (selected)
                        results.push(ko.unwrap(v.ClientName));

                    if (subClients && subClients.length)
                        AggregateSelectedClients(subClients, results);
                    });

    return results;
}

答案 2 :(得分:1)

如果我理解你正在尝试做什么,为什么不尝试这样的事情呢?

 _self.SelectedClient = ko.observableArray();
 _self.ToggleSelectedUser = function (data, event) {
        var toggle = !data.IsSelected();
        data.IsSelected(toggle);

        if(toggle === true) 
        { 
             _self.SelectedClient.push(data.ClientName()); 
        } 
        else 
        {
           _self.SelectedClient.remove(data.ClientName());
        }

答案 3 :(得分:0)

必须将选定的孩子添加到父选择中。

ko.utils.arrayForEach(item.SubClient(), function (subItem) {
   if (subItem.IsSelected()) {
      selected.push(subItem.ClientName());
   }       
   //cp.GetSelectedClientsArray(subItem);
   selected.push.apply(selected, cp.GetSelectedClientsArray(subItem));
});

<强> See fiddle

我希望它有所帮助。