我们的web应用程序中有一个表单,它在一个位置要求用户输入值列表。我们使用Razor和knockout.js编写了表单的这一部分,这样列表的每个值都有一个文本框,类似于this tutorial。我们如何将这些文本框数据绑定到我们的MVC模型?
下面是我们的表单:
@model OurProject.Models.Input.InputModel
@{
ViewBag.Title = "Input";
}
<h2>
Inputs</h2>
<div id="inputKOApp">
@using (Html.BeginForm())
{
<!-- snip - lots of part of our form that work correctly -->
<div class="row-fluid">
<div class="control-group">
<div class="span8 control-label">
@Html.LabelFor(model => model.POSTransactionCodes)
</div>
<div class="controls">
<!-- These are the textboxes we would like to bind to MVC -->
<ul class="pull-right" data-bind="foreach: POSTransactionCodes">
<li>
<input data-bind="value: code" />
<a href="#" data-bind="click: $root.removePOSTransactionCode">Delete</a></li>
</ul>
<button class="pull-right" data-bind="click: addPOSTransactionCode">
Add another POS Transaction Code</button>
@Html.ValidationMessageFor(model => model.POSTransactionCodes, null, new { @class = "help-inline" })
</div>
</div>
</div>
<!-- snip - more cshtml that is irrelevant to the problem -->
</div>
<input type="submit" value="Submit" />
}
</div>
<script type="text/javascript" src='~/Scripts/jquery-1.8.2.min.js'></script>
<script type="text/javascript" src='~/Scripts/knockout-2.1.0.js'></script>
<script type="text/javascript" src='~/Scripts/OP/OP.js'></script>
<script type="text/javascript" src='~/Scripts/OP/Input/OP.Input.Input.Form.js'></script>
<script type="text/javascript" src='~/Scripts/OP/Input/OP.Input.Input.Data.js'></script>
<script type="text/javascript">
var inputApp = $('#inputKOApp')[0];
OP.Input.Form.init(inputApp);
</script>下面是我们的knockout.js脚本OP.Input.Input.Form.js:
extend(OP, 'OP.Input.Form');
OP.Input.Form = function (jQuery) {
var TransactionCodeView = function () {
var self = this;
self.code = "";
};
//The ViewModel for the page
var ViewModel = function () {
var self = this;
//Fields
/* snip - lots of fields that work as expected */
self.POSTransactionCodes = ko.observableArray([]); //is a list of transaction codes
//Set up with initial data
/* I'm guessing that we won't need this function anymore since MVC will populate
* everything for us, but I'll leave it in until I'm far enough along to know
* I won't need to gut lots of stuff */
self.initialize = function () {
var c = function (data, status, response) {
/* snip - lots of fields that work as expected */
if (status === "success") {
if(data.POSTransactionCodes != null) ko.utils.arrayPushAll(self.POSTransactionCodes, data.POSTransactionCodes);
self.POSTransactionCodes.valueHasMutated();
} else {
}
};
OP.Input.Data.GetInput(c);
}
//When saving, submit data to server
self.save = function (model) {
var c = function (data, status, response) {
if (status === "success") {
} else {
}
};
OP.Input.Data.SaveInput(model, c);
}
//Modifying POSTransactionCodes array
self.removePOSTransactionCode = function (POScode) {
self.POSTransactionCodes.remove(POScode);
}
self.addPOSTransactionCode = function () {
self.POSTransactionCodes.push(new TransactionCodeView());
}
};
//Connect KO form to HTML
return {
init: function (elToBind) {
var model = new ViewModel();
ko.applyBindings(model, elToBind);
model.initialize();
}
};
} ($);这是我们的MVC模型:
namespace OurProject.Models.Input
{
public class InputModel : IModel
{
//Snip - lots of properties that aren't interesting for this problem
[Required]
[DisplayName("POS Transaction Codes")]
public List<double> POSTransactionCodes { get; set; }
public InputModel()
{ }
/* I ommitted a few other methods that
* aren't relevant to this problem. */
}
}发布于 2012-11-07 14:11:26
我不知道如何将数据发送回服务器,但您需要以允许模型绑定的方式命名您的输入:
如果要绑定到列表/集合,则输入的名称应如下所示:
<input type="text" name="CollectionPropertyName[index]" />您可以阅读有关Model Binding To A List in this article的文章
因此,您只需为输入生成适当的名称:
<input data-bind="value: code, attr: { name: 'POSTransactionCodes[' + $index() + ']' }" />您应该注意到,只有当您使用提交按钮并发送数据form-urlencoded时,上述解决方案才有效。如果您以json格式发送数据,则可能需要调整序列化逻辑以使模型绑定器满意:
在这种情况下,你的json应该是这样的:
{
//...
POSTransactionCodes: [ 1 , 3 ]
//..
}发布于 2014-04-10 11:23:37
多亏了nemesv的回答,让我明白了这一点。
但是我需要有“普通”的name和id属性才能进行jquery验证。因此,我想到了编写自己的数据绑定器的想法。
ko.bindingHandlers.nameId = {
update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
var value = valueAccessor(),
allBindings = allBindingsAccessor();
var valueUnwrapped = ko.utils.unwrapObservable(value);
var bindName = $(element).data('bind-name');
bindName = bindName.replace('{0}', valueUnwrapped);
$(element).attr({name : bindName, id : bindName});
}
};并在html中使用它。
<input
data-bind="value: qty, nameId: $index"
data-bind-name="inventory[{0}].qty" />jsfiddle
https://stackoverflow.com/questions/13261371
复制相似问题