0

這是我的視圖模型。如何將數據綁定到敲除對象的列表?

服務器端:

public class ShoppingListModel 
{ 
    public string Name { get; set; } 
    public List<ItemModel> Items{ get; set; } 

    public ShoppingListModel() 
    { 
     Items=new List<ItemModel>(); 
    } 
} 

在客戶端,我用knockout.mapping

ShoppingListModel = function(data) { 
    var vm = ko.mapping.fromJSON(data); 
    return vm; 
}; 

要綁定服務器端模式向客戶端模型:

@{ 
    var jsonSerializerSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }; 
    var data = new JavaScriptSerializer().Serialize(JsonConvert.SerializeObject(Model, jsonSerializerSettings)); 
} 

@section scripts { 
<script src="~/App/ShoppingListModel.js"></script> 

    <script>  
     var vm = ShoppingListModel(@Html.Raw(data)); 
     ko.applyBindings(vm); 
    </script> 
} 

上面的代碼:

  1. 使用JSON.NET到服務器側Model序列化爲般地裝載JSON。
  2. 構建客戶端視圖模型。
  3. ko.applyBinding()

現在我要帶的雙向綁定的優勢。

首先,我對Name測試:

@Html.HiddenFor(model => model.Name, new { @data_bind="value:name"}) 
<input type="text" data-bind="value:name"/> 

很順利,我可以在一個文本編輯inputName價值,堅持價值爲隱藏input。提交表單時,更新的值可能會達到POST操作。

現在的問題:如何在列表上實現綁定?

我的測試是從「項目」列表中刪除一個項目:

@Html.HiddenFor(model => model.Items, new { data_bind = "value: items" }) 

<tbody data-bind="foreach:items"> 
    <tr> 
     <td> 

      <span data-bind="text:name"></span> 
     </td> 
     <td><span data-bind="text:count"></span></td> 
     <td> 
      <button class="btn btn-xs" data-bind="click:$parent.remove"> 
       <i class="fa fa-trash"></i> 
      </button> 
     </td> 
    </tr> 
</tbody> 

一個console.log()告訴我,客戶端模型已經更新,但是這一次,在結合上HiddenFor從來沒有成功了!提交表格時,Items始終爲空。

我想這是合理的,因爲在HTML:

<input type="hidden" value="xxx" /> 

,我們期待一個輸入的值是一個簡單的值。

我在想從那裏通過列表和數據綁定循環。但這也很困難。淘汰賽foreachtbody標記,而C#foreach被放置在tr(在tbody內)。

那麼綁定列表的正確方法是什麼?


這是基於法比奧的建議我的解決方案:

  1. 在客戶端KO模型,

添加一個計算值的列表裝訂成JSON字符串。

vm.itemsJson = ko.computed(function() { 
    return ko.toJSON(vm.items); 
},this); 
  • 在HTML視圖,
  • 添加一個隱藏的輸入以保持JSON字符串和後與我們的形式。

    <input name="itemsjson" type="hidden" data-bind="value:itemsJson"/> 
    
  • 在服務器側視圖模型,
  • 除了

    public List<ItemModel> Items{ get; set; } 
    

    添加另一個字符串屬性保持張貼JSON。

    public string ItemsJson { get; set; } 
    

    在這一點上,我們都能夠看到成功發送到控制器動作ItemsJson值。

    1. 將json字符串解析到服務器端的List中。

    既然是打字模型,我們要用JSON.Net進行反序列化。

    var items=JArray.Parse(model.ItemsJson); 
    
    model.Items = items. 
        Select(i => new ItemModel {Name = (string) i["name"], Count = (int) i["count"]}) 
        .ToList(); 
    return View(model); 
    

    請務必使用JArray.Parse()List而不是JObject.Parse()

    它的工作原理。

    我們來看看是否有比手動解析json字符串更好的方法。否則,我會在本週末之後將法比奧的答案標記爲我們的解決方案。

    回答

    1

    你可以使用計算觀測到隱藏字段綁定,就像這樣:

    function YourViewModel() { 
        var self = this; 
        self.items = ko.observableArray(); //fill it with your stuff; 
        self.valueForHiddenField = ko.computed(function() { 
         return ko.toJSON(self.items); 
        }, this); //use this observable as value of your hidden field 
    } 
    

    欲瞭解更多信息http://knockoutjs.com/documentation/json-data.html

    編輯1

    你不需要到JSON轉換中的控制器。相反,發送一個JSON到你的服務器,使用隱藏字段列表發送集合。就像這樣:

    <form> 
        <!-- ko foreach: items --> 
         <input type="hidden" data-bind="value: property1, attr: { name: 'Items[' + $index() + '].Property1' }"> 
         <input type="hidden" data-bind="value: property2, attr: { name: 'Items[' + $index() + '].Property2' }"> 
        <!-- /ko --> 
    
    </form> 
    

    然後你就可以發送了後,也不需要擔心的收集,當你改變了項目observableArray它會自動刷新。

    +0

    不錯的建議。所以當隱藏輸入中的json值被POST到服務器時,那個Json值會自動被解析成一個List,我猜?讓我嘗試並確認它。 – Blaise

    +0

    不幸的是沒有。隱藏輸入中的json是一個字符串,不會自動解析到服務器端模型中。需要某種方式在服務器端進行模型綁定。 – Blaise

    +0

    我已經使它與手動json解析一起工作。在問題的底部發布整個事情。想知道是否有更優雅的方式。十分感謝你」。 – Blaise