Add object to observable array using knockout

For some reason, I am unable to pass the object to the 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 opinion:

  <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 warnings show that the array is always empty, explain what I'm doing wrong.

+6
source share
3 answers

Your observable use of the array, for example self.events.push(event); is correct (since the observable array implements push ), only your warnings are wrong.

The right challenges will be

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

Since you need to call the observable array as a function, like a normal ko.observable , to get the main value of the array itself.

However, you are currently adding the CalendarViewModel to the array to the whole because btnAddNewEvent is outside of your with binding, so the current context will be your main view model.

One way to solve it: just add self.event to the array, therefore:

 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 end up referring to the same element, so the correct solution will 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 click on the new event in addEvent

 self.events.push(new Event(self.event)); 
+10
source

Try

 self.events().length 

and

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

instead.

+2
source

Just a little updated on nemesev's answer. You really don't need 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 name it like

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

Source: https://habr.com/ru/post/943787/


All Articles