Reputation: 809
For some reason i'm having trouble passing an object to observable array.
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());
}
my view:
<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>
The alerts show that the array is always empty, please explain what i'm doing wrong thanks.
Upvotes: 8
Views: 39148
Reputation: 55200
Just updating a little on nemesev answer. You really don't have to pass data
as an argument
var Event = function() {
var self = this;
self.name = ko.observable();
self.adress = ko.observable();
self.startTime = ko.observable();
self.endTime = ko.observable();
};
And call it like
self.events.push(new Event());
Upvotes: 1
Reputation: 139748
Your observable array usage e.g self.events.push(event);
is correct (because observable array implements push
), only your alerts are wrong.
The correct calls would be
alert(self.events().length)
alert(self.events()[0].name());
Because you need to call the observable array as a function like the regular ko.observable
to get its underlying value the array itself.
However you are currently adding to whole CalendarViewModel
to the array because the btnAddNewEvent
is outside of yourwith
binding so the current context will be your main view model.
One way to solve it: just add the self.event
to the array, so:
self.addEvent = function()
{
self.events.push(self.event);
alert(self.events().length)
alert(self.events()[0].name());
}
But this can cause problems later when you want to add another element because you will end up referencing the same element, so the right solution is copy the properties somewhere:
So I would create a constructor function for your event class:
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())
}
And push a new event in the addEvent
self.events.push(new Event(self.event));
Upvotes: 14