2012-04-06 114 views
28

我想顯示一個可編輯的項目列表,其中的每個項目都是可編輯的(有點像可編輯的網格,有點像)。我正在使用KnockoutJS。我不能只使用一個簡單的可觀察數組,因爲文檔聲明「一個可觀察數組跟蹤哪些對象在數組中,而不是這些對象的狀態」KnockoutJS - Observable Array of Observable objects

因此,我創建了observableArray的可觀察對象(使用utils。 arrayMap),並將它們綁定到視圖。但是,問題是,如果我在屏幕上編輯數據,則用戶在屏幕上進行的任何數據輸入更改不會生效。請參閱http://jsfiddle.net/AndyThomas/E7xPM/

我在做什麼錯?

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

}); 

回答

18

ko.utils.arrayMap不作爲觀測您的視圖模型的屬性映射,這就是爲什麼你沒有看到他們動態更新。

如果你定義類別編號爲可觀察,你會看到它更新預期:

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

看到這個更新的jsfiddle:http://jsfiddle.net/tuando/E7xPM/5/

+0

完美thanksssss! – Andrew 2017-05-31 16:11:12

14

要跟進疃的答案,我需要填充我的對象基於從ASP.Net MVC控制器的服務器方法返回的數據,其中產品列表包含在視圖的模型中,而下拉框的類別列表位於ViewBag中。我用下面的代碼(見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); 

}); 

謝謝,摶!

+0

不錯的答案:這裏有更多的細節http://lostechies.com/erichexter/2012/11/29/loading-knockout-view-models-from-asp-net-mvc/ – 2012-12-03 14:40:34

1

我使用的是在調用初始化ko.utils.arrayMap

可能是你的情況矯枉過正寫計算觀測,但它可能會幫助別人。看到這個 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); 
    });