2012-04-06 22 views
28

Ich möchte eine bearbeitbare Liste von Elementen anzeigen, von denen jedes Element bearbeitet werden kann (gewissermaßen wie ein bearbeitbares Gitter, in gewisser Weise). Ich benutze KnockoutJS. Ich kann nicht nur ein einfaches Observable Array verwenden, da die Dokumentation besagt "Ein ObservableArray verfolgt, welche Objekte im Array sind, nicht den Zustand dieser Objekte". Also habe ich ein ObservableArray von Observable Objects erstellt (mit utils.KnockoutJS - Observable Array von Observable Objekten

). arrayMap) und verknüpfte sie mit der Ansicht. Das Problem ist jedoch, dass, wenn ich die Daten auf dem Bildschirm bearbeite, alle Dateneingabeänderungen, die der Benutzer auf dem Bildschirm vornimmt, nicht wirksam werden. Siehe http://jsfiddle.net/AndyThomas/E7xPM/

Was mache ich falsch?

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

}); 

Antwort

18

ko.utils.arrayMap Karte Ihre Viewmodel ist nicht Eigenschaften wie Observablen, und das ist, warum Sie sie dynamisch aktualisiert nicht sehen.

Wenn Sie Ihren CategoryId als beobachtbare definieren, werden Sie es sehen aktualisieren, wie erwartet:

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

diese aktualisierte jsfiddle Siehe: http://jsfiddle.net/tuando/E7xPM/5/

+0

perfekte thankssssss! – Andrew

14

auf Tuan Antwort auf Follow-up, musste ich füllen Meine Objekte basieren auf Daten, die von einer Servermethode von einem MVC-Controller von ASP.Net zurückgegeben wurden, wobei die Liste der Produkte im Modell der Ansicht enthalten ist und die Liste der Kategorien für die Dropdownliste im ViewBag enthalten ist. Ich habe den folgenden Code (siehe auch 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); 

}); 

Danke, Tuan!

+0

Schöne Antwort: Es gibt einige weitere Details hier http://losetechies.com/erichexter/2012/11/29/loading-knockout-view-model-from-asp-net-mvc/ –

1

I beschreibbaren berechneten Observablen bin mit, die in dem Aufruf initialisiert werden

ko.utils.arrayMap Kann zuviel des Guten in Ihrem Fall sein, aber es könnte jemand anders helfen. Siehe hierzu 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); 
    }); 
Verwandte Themen