我们有一个使用Razor和Knockout.js显示表单的视图。表单的一部分要求用户输入值列表,我们使用ko.observablearray
来跟踪它们。此列表表示为一组文本框,每个值一个,每个框旁边有一个“删除”按钮,所有这些框下面都有一个“添加”按钮。它的工作方式与http://learn.knockoutjs.com/#/?tutorial=collections的演示项目类似。
我们的形式出乎意料地以两种方式表现:
ko.observablearray
中的所有值,而不仅仅是与所单击的内容对应的值。 ko.observablearray
添加一个新元素,而不是将表单提交给我们的服务器。为什么我们会看到这种行为? (我知道这些是两个独立的问题,但我不确定它们是否是由相同的潜在问题引起的,这就是我在一个问题中发布它们的原因。)
这是我们的剃刀观点:
@model OurProject.Models.Input.InputModel
@{
ViewBag.Title = "Input";
}
<h2>Inputs</h2>
<div id="inputForm">
<!-- snip - lots of input elements to fill in that are bound to KO -->
<div>
@Html.LabelFor(model => model.POSTransactionCodes)
</div>
<div>
<span class="help-block">Separate values by commas.</span>
</div>
<div>
<ul data-bind="foreach: POSTransactionCodes">
<li><input data-bind="value: $data" /> <a href="#" data-bind="click: $root.removePOSTransactionCode">Delete</a></li>
</ul>
<button data-bind="click: addPOSTransactionCode">Add another POS Transaction Code</button>
@Html.ValidationMessageFor(model => model.POSTransactionCodes, null, new { @class = "help-inline" })
</div>
<!-- snip - more input elements -->
<button data-bind="click: save">Submit</button>
</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 elementToBindTo = $("#inputForm")[0];
OP.Input.Input.Form.init(elementToBindTo);
</script>
这是我们的主要Knockout代码,OP.Input.Input.Form.js:
extend(OP, 'OP.Input.Input.Form');
OP.Input.Input.Form = function (jQuery) {
//The ViewModel for the page
var ViewModel = function () {
var self = this;
//Fields
/* snip - lots of ko.observables() */
self.POSTransactionCodes = ko.observableArray([]); //is a list of transaction codes
/* snip - lots of ko.observables() */
//Set up with initial data
self.initialize = function () {
var c = function (data, status, response) {
if (status === "success") {
/* snip - lots of ko.observables() */
ko.utils.arrayPushAll(self.POSTransactionCodes, data.POSTransactionCodes);
self.POSTransactionCodes.valueHasMutated();
/* snip - lots of ko.observables() */
} else {
}
};
OP.Input.Input.Data.GetInput(c);
}
//When saving, submit data to server
self.save = function (model) {
var c = function (data, status, response) {
if (status === "success") {
//After succesfully submitting input data, go to /Input/Submitted
//in order to let MVC determine where to send the user next
window.location.href = "~/Input/Submitted";
} else {
}
};
OP.Input.Input.Data.SaveInput(model, c);
}
//Modifying POSTransactionCodes array
self.removePOSTransactionCode = function (POScode) {
self.POSTransactionCodes.remove(POScode)
}
self.addPOSTransactionCode = function () {
self.POSTransactionCodes.push("");
}
};
//Connect KO form to HTML
return {
init: function (elToBind) {
var model = new ViewModel();
ko.applyBindings(model, elToBind);
model.initialize();
}
};
} ($);
这是OP.Input.Input.Data.js:
extend(OP, 'OP.Input.Input.Data');
OP.Input.Input.Data = {
GetInput: function (callback) {
$.get("/API/Input/InputAPI/GetInputModel", callback);
},
SaveInput: function (input, callback) {
$.ajax({
url: "/API/Input/InputAPI/SaveInput",
type: "post",
data: input,
complete: callback
});
}
};
答案 0 :(得分:2)
您需要将新的ViewModel推送到可观察的数组中。其中包含可观察的属性。
为此,我创建了一个名为TransactionCodeView
的新视图模型var TransactionCodeView = function() {
var self = this;
self.code = ko.observable("");
};
然后当用户点击“添加另一个POS交易代码”时:
self.addPOSTransactionCode = function () {
self.POSTransactionCodes.push(new TransactionCodeView());
}
唯一改变的是HTML绑定:
<li><input data-bind="value: code" /> <a href="#" data-bind="click: $root.removePOSTransactionCode">Delete</a></li>
因为code
是新视图模型中的可观察属性,我们将input
值绑定到该值。
看看这个jsfiddle。我没有测试提交功能,原因很明显; - )
答案 1 :(得分:0)
这就是提交功能无法在我的表单上运行的原因:
在视图中,我有这把剃刀:
<div>
<ul data-bind="foreach: POSTransactionCodes">
<li><input data-bind="value: $data" /> <a href="#" data-bind="click: $root.removePOSTransactionCode">Delete</a></li>
</ul>
<button data-bind="click: addPOSTransactionCode">Add another POS Transaction Code</button>
@Html.ValidationMessageFor(model => model.POSTransactionCodes, null, new { @class = "help-inline" })
</div>
使用我的“添加”按钮的button
元素导致它响应用户按Enter而不是表单末尾的提交按钮。当我将按钮更改为input
元素时,它开始按预期工作。
<input type="button" value="Add another POS Transaction Code"
data-bind="click: addPOSTransactionCode" />