7

Sto utilizzando Knockout per implementare uno strumento di selezione dell'elenco dei corsi. Sto usando l'approccio di seguito per popolare i dati (MVC3/Razor), in modo che quando il viewmodel è inizialmente popolato, non ho problemi a lavorare con ogni array KO (cioè CourseList, ScheduleList). Tuttavia, quando il carico iniziale dal server restituisce zero righe, il che significa che la proprietà viewmodel 'ScheduleList' è vuota, quindi non è possibile chiamare alcun metodo come .push() o .removeAll(). Presumibilmente ciò significa che l'array osservabile non è mai stato creato poiché non c'era nulla da riempire. Quando il modello viene riempito, la proprietà ScheduleList viene popolata con un elenco. Qual è il modo migliore per istanziarlo quando l'azione MVC lo restituisce come vuoto? C'è un jsFiddle che sembra affrontarlo, ma quando provo a usare l'opzione 'create', rende vuoto il mio intero modello. Non sono sicuro di quale sia la sintassi dell'opzione 'create'. Il jsFiddle è qui: http://jsfiddle.net/rniemeyer/WQGVC/Come inizializzare un viewmodel Knockout quando il caricamento viewmodel iniziale è vuoto

// Get the data from the server 
var DataFromServer = @Html.Raw(Json.Encode(Model));  

// Data property in viewmodel 
var data = { 
    "CourseList": DataFromServer.CourseList , 
    "ScheduleList": DataFromServer.ScheduleList 
    }; 

$(function() { 
    // Populate Data property 
    viewModel.Data = ko.mapping.fromJS(data); 

    // ko.applyBindings(viewModel, mappingOptions);    
    ko.applyBindings(viewModel); 
}); 

Quando il caricamento della pagina iniziale non popola ScheduleList, quindi il codice seguente genera un errore. Se il carico iniziale della pagina conteneva dati, allora si potrebbe chiamare .removeAll() e .push() ecc

var oneA= 'abc'; 

// push not working     
this.Data.ScheduleList.push(oneA); 

risposta

9

Impostare i parametri di mappatura per renderlo così via creazione, si dà una certa struttura. Quindi farà gli aggiornamenti per te.

Quello che è più probabile che accada è che il tuo DataFromServer in realtà non contiene alcuna proprietà ScheduleList. Quindi, quando viene mappato, non viene mai creata una proprietà corrispondente. Il mappatore mapperà solo le proprietà esistenti in osservabili.

È necessario impostare le opzioni create per il modello di visualizzazione per aggiungere matrici vuote quando l'array non è impostato. In questo modo, il tuo modello di visualizzazione finirà con gli array osservabili corrispondenti sul posto.

Assicurandosi che CourseList o ScheduleList sia un array, il modello di visualizzazione mappato li mapperà come oggetti observableArray in modo che il codice funzioni come previsto.

var DataFromServer = { 
    'CourseList': [1,2,3] 
    //, 'ScheduleList': [] 
}; 

var dataMappingOptions = { 
    'create': function (options) { 
     var data = options.data; 
     data.CourseList = data.CourseList || []; 
     data.ScheduleList = data.ScheduleList || []; 
     return ko.mapping.fromJS(data); 
    } 
}; 

viewModel.Data = ko.mapping.fromJS(DataFromServer, dataMappingOptions); 
+0

Grazie! Questo è esattamente ciò che sta accadendo e questo risolve il problema. Interessante che la maggior parte dei jsFiddles che ho visto agissero sulla proprietà (array stesso), quindi non avevo provato a creare questo callback. Anche l'altro approccio suggerito da Ray funziona. –

1
var data = { 
    CourseList: DataFromServer.CourseList || ko.observableArray([]) , 
    ScheduleList: DataFromServer.ScheduleList || ko.observableArray([]) 
    };