我刚刚开始使用基因敲除js,并且正在尝试构建动态的Treeview。为简化起见,我删除了与该问题无关的所有内容。树形视图将由嵌套的UL标签组成。

的HTML:

<div id="pnlDestinations">
    <ul data-bind="template: { name: 'GroupTemplate', foreach: Groups }"></ul>
</div>

<script type="text/html" id="GroupTemplate">
    <li>
        <a href="#" data-bind="text: GroupName, click: function() { RetrieveDestinations($data); }"></a>
        <ul data-bind="template: { name: 'DestinationTemplate', foreach: Destinations }"></ul>
    </li>
</script>

<script type="text/html" id="DestinationTemplate">
    <li>
        <a href="#" data-bind="text: DestinationName"></a>
    </li>
</script>


编码:

function ViewModel(groups) {
    Groups = ko.mapping.fromJS(groups);
    RetrieveDestinations = function (group) {
        $.getJSON('GetDestinations?id=' + group.GroupId(), function (data) {
            group.Destinations(ko.mapping.fromJS(data));
        });
    }
}

$(function () {
    $.getJSON("GetGroups", function (data) {
        ko.applyBindings(new ViewModel(data));
    });
});


因此,我将树视图绑定为两个级别(使用2个模板),但是我只在“ GetGroups”中获取一个级别(目的地存在,但为空数组)。

单击组时,将在RetrieveDestinations()方法中检索目标,并且应替换组中的空数组。但是,它们不会出现在我的树形视图中。

Treeview的绑定应该是正确的,因为如果将目的地包括在“ GetGroups”中,则所有内容都将正确呈现。

最佳答案

当给定数组时,ko.mapping.fromJS会将其转换为observableArray。

因此,当您执行group.Destinations(ko.mapping.fromJS(data))时,您要将Destinations observableArray的值设置为等于observableArray。基本上,这意味着它被包装了两次。

您可以做类似group.Destinations(ko.mapping.fromJS(data)())的操作

jsFiddle目前不允许保存,但是这是您的代码经过简化,可以使用映射插件来更新目的地(setTimeouts以模拟AJAX):

<div id="pnlDestinations">
    <ul data-bind="foreach: Groups">
        <li>
            <a href="#" data-bind="text: GroupName, click: $root.RetrieveDestinations"></a>
            <ul data-bind="foreach: Destinations">
                <li>
                    <a href="#" data-bind="text: DestinationName"></a>
                </li>
            </ul>
        </li>
    </ul>
</div>


ViewModel:

function ViewModel(groups) {
    this.Groups = ko.mapping.fromJS(groups);
    this.RetrieveDestinations = function (group) {
        setTimeout(function() {
            //fake data
            var name = group.GroupName(),
                data = [
                    { DestinationName: name + "-1" },
                    { DestinationName: name + "-2" },
                    { DestinationName: name + "-3" }
                ];
            ko.mapping.fromJS(data, {}, group.Destinations);
            group.Destinations.push({ DestinationName: "new" });
        }, 100);
    };
}

$(function () {
    setTimeout(function() {
        var data = [
            { GroupName: "Group1", Destinations: [] },
            { GroupName: "Group2", Destinations: [] },
            { GroupName: "Group3", Destinations: [] }
            ];
        ko.applyBindings(new ViewModel(data));
    }, 100);
});

10-08 06:06