2013-04-27 7 views
6

Per qualche motivo ho problemi a passare un oggetto a un array osservabile.aggiungi un oggetto a un array osservabile utilizzando il knockout

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()); 
} 

mio punto di vista:

<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> 

Gli avvisi indicano che la matrice è sempre vuota, spiegare quello che sto facendo, grazie sbagliate.

risposta

10

L'utilizzo del campo osservabile ad esempio self.events.push(event); è corretto (perché observable array implementa push), solo gli avvisi sono errati.

Le chiamate corretta sarebbe

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

Perché è necessario chiamare la matrice osservabile come una funzione come la normale ko.observable per ottenere il valore sottostante l'array stesso.

Tuttavia, si sta attualmente aggiungendo all'intero CalendarViewModel all'array perché lo btnAddNewEvent è al di fuori del collegamento with in modo che il contesto corrente sia il modello di visualizzazione principale.

Un modo per risolverlo: basta aggiungere il self.event alla matrice, in modo da:

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

Ma questo può causare problemi più tardi, quando si desidera aggiungere un altro elemento, perché si finirà per riferimento lo stesso elemento, quindi la soluzione giusta è copiare le proprietà da qualche parte:

quindi vorrei creare una funzione di costruzione per la classe evento:

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()) 
} 

e spingere un nuovo evento nel addEvent

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

ora sta funzionando ma sembra che quando uso di allerta (self.events() [0] .nome()); Ottengo questo errore: Uncaught TypeError: Object # non ha il metodo 'nome', quando digito in alert (self.events() [0] .event.name()) allora è ok ma non significa che memorizzo l'intero modello di visualizzazione nel mio array e non solo la proprietà event del modello di vista. Voglio che la matrice tenga jsut agli oggetti degli eventi, non alla vista stessa. –

+0

Sì, stai attualmente aggiungendo l'intero calendario viewmodel all'array perché 'btnAddNewEvent' è al di fuori del vincolo' with', quindi il contesto corrente sarà il tuo modello di vista principale. Un modo per risolverlo e aggiungere il 'self.event' quindi' self.addEvent = function() {self.events.push (self.event); alert (self.events(). length) alert (self.events() [0] .name()); ' – nemesv

+0

sweet, funziona come previsto –

2

Prova

self.events().length 

e

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

invece.

0

Basta aggiornare un po 'sulla risposta nemesev. Davvero non c'è bisogno di passare data come argomento

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

e chiamarlo come

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