2012-04-06 23 views
28

Vorrei visualizzare un elenco modificabile di elementi, ognuno dei quali è modificabile (un po 'come una griglia modificabile, in un modo). Sto usando KnockoutJS. Non posso usare solo una Observable Array semplice perché, come afferma la documentazione "Un osservableArray tiene traccia di quali oggetti sono nell'array, non lo stato di quegli oggetti"KnockoutJS - Array osservabile di oggetti osservabili

Quindi, ho creato un array osservabile di oggetti osservabili (usando utilità. arrayMap) e li ha associati alla vista. Tuttavia, il problema è che se modifico i dati sullo schermo, qualsiasi modifica dei dati che l'utente apporta sullo schermo non sembra avere effetto. Vedi

Cosa sto facendo male?

<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/2.0.0/knockout-min.js" type="text/javascript"></script> 

<table> 
    <tbody data-bind="template: { name:'productListJavascriptTemplate', foreach: products}"> 
    </tbody> 
</table> 


<script type="text/html" id="productListJavascriptTemplate"> 
<tr> 
    <td>Name: <input data-bind="value: Name"/></td> 
    <td>Name: <span data-bind="text: Name"/></td> 
    <td><select data-bind="options: this.viewModel.categories, 
     optionsText: 'Name', optionsValue: 'Id', value: CategoryId, 
     optionsCaption: 'Please select...'"></select></td> 
    <td>CategoryId: <input data-bind="value: CategoryId"/></td> 

</tr> 

</script>​ 

var categoryList= [ 
{ 
    Name: "Electronics", 
    Id: "1"}, 
{ 
    Name: "Groceries", 
    Id: "2"} 
]; 

var initialData= [ 
{ 
    Name: "Television", 
    CategoryId: "1"}, 
{ 
    Name: "Melon", 
    CategoryId: "2"} 
]; 

var viewModel = { 
    products: ko.observableArray(
     ko.utils.arrayMap(initialData, function(product) { 
           return ko.observable(product); 
     })), 
    categories: ko.observableArray(categoryList)  
}; 


$(function() { 
    ko.applyBindings(viewModel); 

}); 

risposta

18

ko.utils.arrayMap non mappa le proprietà del ViewModel come osservabili, e per questo non si vede li aggiornati dinamicamente.

Se si definisce la vostra CategoryId come osservabile, lo vedrete aggiornare come previsto:

var initialData = [ 
    { 
     Name: "Television", 
     CategoryId: ko.observable("1") 
    }, 
    { 
     Name: "Melon", 
     CategoryId: ko.observable("2") 
    } 
]; 

Vai a questa jsfiddle aggiornamento: http://jsfiddle.net/tuando/E7xPM/5/

+0

perfetto thanksssss! – Andrew

14

dare seguito alla risposta di Tuan, avevo bisogno per popolare i miei oggetti basati su dati restituiti da un metodo server da un controller ASP.Net MVC, in cui l'elenco di prodotti è contenuto nel modello della vista e l'elenco di categorie per la casella a discesa è nel ViewBag. Ho usato il seguente codice (vedi anche http://www.knockmeout.net/2011/04/utility-functions-in-knockoutjs.html):

var initialData = @Html.Raw(new JavaScriptSerializer().Serialize(Model)); 
var categoryList = @Html.Raw(new JavaScriptSerializer().Serialize(ViewBag.CategoryList)); 

var ObservableProduct = function(name, description, categoryId) {   
    this.Name = ko.observable(name);   
    this.Description = ko.observable(description); 
    this.CategoryId = ko.observable(categoryId); 
}; 

var viewModel = { 
    products: ko.observableArray(ko.utils.arrayMap(initialData, function(product) { 
      return new ObservableProduct(product.Name, product.Description, product.CategoryId); 
     })), 
    categories: ko.observableArray(categoryList)  
}; 

$(function() { 
    ko.applyBindings(viewModel); 

}); 

Grazie, Tuan!

+0

Bella risposta: c'è qualche dettaglio in più qui http://lostechies.com/erichexter/2012/11/29/loading-knockout-view-models-from-asp-net-mvc/ –

1

Sto usando osservabili calcolate scrivibili che vengono inizializzate nella chiamata a ko.utils.arrayMap

Può essere un eccessivo nel tuo caso, ma potrebbe aiutare qualcun altro. Vedere questo jsFiddle sample

// Writeable computed observables 
    function Customer(id, firstName, lastName, preferred) { 
    var self = this; 
    self.id = id; 
    self.firstName = firstName; 
    self.lastName = lastName; 
    // Non-Writeable computed observable 
    self.fullName = ko.computed(function() { 
     var fn = self.firstName; 
     var ln = self.lastName; 
     return ln ? fn + ' ' + ln : fn; 
    }, self); 
    self.preferred = ko.observable(preferred); 
    // Writeable computed observable 
    self.isPreferred = ko.computed({ 
     read: function() { 
      var preferredStr = self.preferred() || ''; 
      var isPreferredComputed = preferredStr.toUpperCase(); 
      return (isPreferredComputed === 'Y') ? true : false; 
     }, 
     write: function(value) { 
      self.preferred((!value) ? '' : (value ? 'Y' : ''));    
     }, 
     owner: self   
    });  
} 
    var mappedData = ko.utils.arrayMap(dataFromServer, function(customer) { 
     return new Customer(customer.id, customer.firstName, customer.lastName, customer.preferred); 
    }); 
Problemi correlati