KnockoutJS:嵌套的observableArrays和嵌套的ForEach

时间:2015-11-17 19:29:22

标签: javascript knockout.js foreach

免责声明 - 我担心这个问题可能是重复的,因为功能似乎很基本,所以我知道我可能会得到一个dpe ding。但我找不到一个有效的解决方案

所以我有一个可观察的数组设置如下

self.meetingAttendees = ko.observableArray([
    {
        AttendeeTypeId: ko.observable(1),
        AttendeeNames: ko.observableArray([
            { Name: ko.observable("Nemo"), CurrentEdit: ko.observable(0) }
        ]),
        AttendeeSiteNumber: ko.observable(""),
        StudentNames: ko.observableArray([
            { Name: ko.observable("Flava Flave"), CurrentEdit: ko.observable(1) }
        ]),
        Email: ko.observable(""),
        Telephone: ko.observable("")
    }]);

和我的“问题”HTML是:

<tbody data-bind="foreach: $root.meetingAttendees">
    <tr>
        <td class="attendeeNameCol textAlignCenter">
            <div class="textAlignCenter" data-bind="foreach:{data: AttendeeNames, as: 'Attendee'}">
                 <input class="formInput" data-bind="textInput: Attendee.Name()"/>
                 <span class="glyphicon glyphicon-remove nameRemove" data-bind="click:$root.removeName.bind($data,$index(),'AttendeeNames',$parentContext.$index())"></span>
            </div>
            <span data-bind="visible:$root.meetingAttendees()[$index()].AttendeeTypeId() == 1,click:$root.addName.bind($data,$index(),'AttendeeNames',$index())" class="addAnotherText">(+) Add Another Parent</span>
         </td>
    </tr>
</tbody>

一切似乎工作得很好,并且使用虚拟数据,它可以正确绑定。但是,当我将一个元素推入AttendeeNames

self.meetingAttendees()[parentIndex].AttendeeNames().push( {Name: ko.observable(""),CurrentEdit: ko.observable(1)} );

我的观点未插入其他元素。我检查了数组,它确实显示已经添加了一个元素,所以我认为这是一个绑定问题。

我的问题是如何正确绑定以便嵌套的foreach语句正确更新并在嵌套的observableArrays中显示信息?

2 个答案:

答案 0 :(得分:0)

:(

答案太简单了。

self.meetingAttendees()[parentIndex].AttendeeNames().push(
    {Name: ko.observable(""),CurrentEdit: ko.observable(1)}
);

没有进入阵列。

我不应该使用AttendeeNames()。push()

需要是AttendeeNames.push()

我在绑定上犯了同样的错误。我正在做Attendee.Name()而不是Attendee.Name,我应该这样做。

如果有人想描述为什么会发生这种情况,我会接受他们的回答,因为我不知道为什么会有这个确切的逻辑。

答案 1 :(得分:0)

因此,AttendeeNames是一个可淘汰的可观察数组。如果你在它上面执行console.log,你会发现你得到一个函数而不是一个数组。这个变量实际上可以用两种方式。

如果将其称为AttendeeNames(),则您将获得没有任何淘汰功能的基础数组。因此,您可以根据需要修改此基础数组,并将其打印出来,看起来数据正在发生变化,但您的视图不会更新,因为淘汰赛无法了解这些更改。您可以使用AttendeeNames.valueHasMutated()手动通知可观察到的此更改。注意它是如何使用Knockout功能的 - ()之后没有AttendeeNames。有时,如果您认为自己可能会进行大量更改并且不希望更新视图,直到出于性能原因完成所有操作,这可能很有用。

当您致电AttendeeNames.push()时,您实际上正在使用淘汰赛功能,该功能会将项目添加到基础阵列会通知视图需要更新。

回顾:

以下代码段具有相同的功能:

AttendeeNames.push(item);

AttendeeNames().push(item);
AttendeeNames.valueHasMutated();

通过使用()访问knockout observable,您绕过了所有淘汰的东西并获得了封装的Javascript值。