簡體   English   中英

如何使用剔除將數據綁定到對象列表?

[英]How to data bind to a list of objects with knockout?

這是我的視圖模型。

服務器端:

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"/>

一切順利,我能夠在文本input編輯Name值,並將該值保留到隱藏的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上的HiddenFor從未起作用! 提交表單后, Items始終為null。

我認為這是合理的,因為在HTML中:

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

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

我正在考慮遍歷列表並從那里進行數據綁定。 但這也是困難的。 敲除foreachtbody標簽上,而C# foreach放在tr周圍( tbody內部)。

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


這是根據Fabio的建議我的解決方案:

  1. 在客戶端ko模型中,

添加計算值以將列表綁定到json字符串中。

vm.itemsJson = ko.computed(function() {
    return ko.toJSON(vm.items);
},this);
  1. 在html視圖中,

添加一個隱藏的輸入來保存json字符串並以我們的表單發布。

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

除了

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

添加另一個字符串屬性以保存發布的json。

public string ItemsJson { get; set; }

至此,我們可以看到ItemsJson值已成功發送到控制器操作。

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

由於它是類型化模型,因此我們將使用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字符串更好的方法。 否則,我將在本周末之后將法比奧的答案標記為我們的解決方案。

您可以使用計算的可觀察值綁定隱藏字段,如下所示:

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時,它將自動刷新。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM