我們在我們的Web應用程序中有一個表單,它在一個地方要求用戶輸入一個值列表。我們使用Razor和knockout.js編寫了這部分表單,以便爲列表中的每個值都有一個文本框,類似於this tutorial。我們如何將這些文本框與我們的MVC模型進行數據綁定?數據綁定MVC-4到Knockout.js foreach
這裏是我們的形式:
@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. */
}
}