在ajax调用成功后将视图模型绑定到ui Knockout

时间:2012-12-30 16:31:32

标签: knockout.js knockout-mapping-plugin knockout-2.0

我在每行数据中都有一个selectall切换复选框和复选框。

现在从服务器返回的数据没有isSelected Observable。我为每一行添加了'isSelected'可观察对象。但是isSelected可观察量并没有绑定到每行的复选框。

这是viewmodel:

var folderViewModel = function () {
    var self = this;
    self.Folders = ['Inbox', 'Archive', 'Sent', 'Spam'];
    self.SelectedFolder = ko.observable();
    self.Mails = ko.observableArray([]);
    self.SelectedMail = ko.observable();
    self.SelectAll = ko.observable(false);

    self.navigate = function (folder) {
        self.SelectedFolder(folder);
        //$.get('/Api/MailBox', { folder: folder }, self.Mails);

        $.ajax({
            url: "/Api/Mailbox",
            data: { folder: folder },
            success: function (data) {
                ko.mapping.fromJS(data, {}, self.Mails);
                ko.utils.arrayForEach(self.Mails(), function (mail) {
                    mail.isSelected = ko.observable(true);
                    mail.isSelected.subscribe(function (myvalue) {
                        console.log(myvalue);
                    });
                });
                console.log(ko.toJSON(self.Mails()));
            },
            statusCode: {
                404: function () {
                    alert("No Mail");
                }
            }
        });

        //ko.mapping.fromJS(data, {}, self.Mails);
        //console.log(ko.toJSON(self.Mails));
    };

    self.SelectAll.subscribe(function (newValue) {
        ko.utils.arrayForEach(self.Mails(), function (mail) {
            console.log(mail.isSelected());
            mail.isSelected(newValue);

        });
        console.log(newValue);
    }, self);

    this.navigate("Inbox");
};
ko.applyBindings(new folderViewModel());

这是绑定。

<table class="table table-bordered table-striped table-condensed table-hover">
<thead>
    <tr>
        <th>
            <input type="checkbox" data-bind="checked: SelectAll"/>
            @*<input type="checkbox" />*@
        </th>
        <th>
            From
        </th>
        <th>
            To
        </th>
        <th>
            Subject
        </th>
        <th>
            Date
        </th>
    </tr>
</thead>
<tbody data-bind="foreach:Mails">
    <tr data-bind="click:$root.navigateToMail">
        <td style="width: 15px">
            <input type="checkbox" data-bind="checked: $root.isSelected">
            @*<input type="checkbox">*@
        </td>
        <td data-bind="text: From">
        </td>
        <td data-bind="text: To">
        </td>
        <td data-bind="text: Subject">
        </td>
        <td data-bind="text: MailDate">
        </td>
    </tr>
</tbody>

复选框<input type="checkbox" data-bind="checked: $root.isSelected">未绑定到mails.isSelected=ko.obsevable(true)中的ajax数据。可能是什么问题?

2 个答案:

答案 0 :(得分:4)

首先,kuddos使用learn.knockoutjs.com示例,令人惊叹的资源。

您的错误是KnockoutJS中常见的陷阱:您正在修改模型而不更新绑定到它的可观察对象。请参阅以下行 -

ko.mapping.fromJS(data, {}, self.Mails);
ko.utils.arrayForEach(self.Mails(), function (mail) { ... });

如果你看到,你首先要为邮件创建模型,然后添加一个额外的可观察数据。这个观察应该附加到哪个上下文?如果不更新每封邮件的值,则mail.isSelected永远不会添加到邮件对象中。

有两种方法可以解决这个问题。第一个,你在forEach数组中更新邮件模型:

ko.utils.arrayForEach(self.Mails(), function (mail, index) { 
    // Add up the isSelected observable
    self.Mails()[index] = mail; 
});

这对可观察数组有一个性能问题,您可以阅读here。基本上,您希望创建一个临时数组并更新整个可观察数组,而不是每次都调用Mails()

另一种方式很简单:交换如何创建邮件模型的顺序:

ko.utils.arrayForEach(self.Mails(), function (mail) { ... });
ko.mapping.fromJS(data, {}, self.Mails);

首先,你附加了一个你的observable数据对象,然后你告诉你的viewmodel“嘿!我们有一个新的模型来保存它具有来自data的这个属性加上我刚刚添加的一个可观察的isSelected,小心绑定它?“

话虽如此,HTML中的属性是checked: isSelected而不是checked: $root.isSelected,这就是为什么它有点像SelectAll(排序)一样工作的原因,因为isSelected被绑定了到您的ViewModel而不是您的邮件模型。您可以通过这个方便的声明来解决调试问题:

// In any row inside your data
<td data-bind="text: ko.toJSON($data)">DEBUG DATA</td>

应该是这样,你可以看到你的代码在这里工作以及它的所有解决方案:http://jsfiddle.net/jjperezaguinaga/VTuHA/。我添加了一些示例数据(使用JsFiddle的/echo/json/功能)并删除了一些内容,以及我用上一个代码调试的额外列。在最后一列中,您可以看到每次单击复选框时更新的值isSelected

答案 1 :(得分:0)

每个isSelected项目上都没有添加mail,而不是root视图模型中添加了<input type="checkbox" data-bind="checked: isSelected"> 吗?如果是这样,你的绑定应该是:

navigateToMail

注意:我也没有在root视图模型中看到{{1}}方法,这也会导致问题。