使用Knockout将对象添加到可观察数组中

8
由于某些原因,我在将对象传递给可观察数组时遇到了问题。
function CalendarViewModel() {
var self = this;

self.event = {
    name : ko.observable(""),
    adress : ko.observable(""),
    startTime : ko.observable(""),
    endTime : ko.observable("")
}

self.events = ko.observableArray([

])

self.addEvent = function (event) {

    self.events.push(event);

    alert(self.events.length)
    alert(self.events[0].name());
 }

我的看法:

 <fieldset class="add-event-fieldset">
            <div data-bind="with: event">
                <legend>Add Event</legend>
                <div style="text-align: center;">
                    <label class="title-label">What </label>
                </div>
                <div>
                    <label>Name: </label>
                    <input type="text" name="whatTxtBox" data-bind="value: name" />
                </div>
                <div>
                    <label>Where: </label>
                    <input type="text" name="whereTxtBox" data-bind="value: adress" />
                </div>
                <div style="text-align: center;">
                    <label class="title-label">When </label>
                </div>
                <div>
                    <label>start: </label>
                    <input type="text" id="startHourTxtBox" data-bind="value: startTime" />
                </div>
                <div>
                    <label>end: </label>
                    <input type="text" id="endHourTxtBox" data-bind="value: endTime" />
                </div>
            </div>

            <input type="hidden" name="" id="hiddenDay" />

            <button id="btnAddNewEvent" data-bind="click: $root.addEvent">+</button>
        </fieldset>

警告显示数组一直为空,请解释我做错了什么,谢谢。
3个回答

13

您的可观察数组用法,例如self.events.push(event);是正确的(因为observable array实现了push),只有您的警报信息是错误的。

正确的调用如下:

alert(self.events().length)
alert(self.events()[0].name());

因为你需要像普通的 ko.observable 一样将可观察数组作为函数调用以获取其基础值即数组本身。

但是,由于 btnAddNewEvent 在你的with 绑定之外,所以你当前正在将整个 CalendarViewModel 添加到数组中,因为当前上下文将是你的主视图模型。

解决方法之一:只需将self.event添加到数组中,如下:

self.addEvent = function() 
{ 
    self.events.push(self.event); 
    alert(self.events().length)
    alert(self.events()[0].name());
}

但是这样做可能会在以后添加另一个元素时产生问题,因为您最终会引用相同的元素,因此正确的解决方案是将属性复制到某个地方:

所以我会为您的事件类创建一个构造函数:

var Event = function(data) {
    var self = this;
    self.name = ko.observable(data.name()),
    self.adress = ko.observable(data.adress()),
    self.startTime = ko.observable(data.startTime()),
    self.endTime = ko.observable(data.endTime())
}

在addEvent中触发一个新事件

self.events.push(new Event(self.event));

现在它正在工作,但是当我使用alert(self.events()[0].name())时似乎会出现此错误:Uncaught TypeError: Object #<CalendarViewModel> has no method 'name'。当我输入alert(self.events()[0].event.name())时就可以了,但这难道不意味着我将整个视图模型存储在数组中而不仅仅是视图模型的事件属性吗?我想要数组只保存事件对象,而不是视图模型本身。 - Alan Budzinski
是的,您目前正在将整个日历视图模型添加到数组中,因为 btnAddNewEventwith 绑定之外,所以当前上下文将是您的主视图模型。解决此问题的一种方法是只添加 self.event,因此 self.addEvent = function () { self.events.push(self.event); alert(self.events().length) alert(self.events()[0].name()); - nemesv

3

尝试

self.events().length

并且

self.events()[0].name() 

替代方式。


1

我只是稍微更新一下nemesev的回答。实际上你不需要将data作为参数传递。

var Event = function() {
    var self = this;
    self.name = ko.observable();
    self.adress = ko.observable();
    self.startTime = ko.observable();
    self.endTime = ko.observable();
};

并像这样调用

self.events.push(new Event());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接