フォームを表示するRazorとKnockout.jsを使用したビューがあります。フォームの一部はユーザーに値のリストを入力するように要求し、私たちはko.observablearray
それらを追跡するためにを使用しています。このリストは、値ごとに1つずつ、一連のテキストボックスとして表され、各ボックスの横に[削除]ボタンがあり、すべての下に1つの[追加]ボタンがあります。これは、 http://learn.knockoutjs.com/#/?tutorial=collectionsのデモプロジェクトと同様に機能します。
私たちのフォームは、2つの方法で予期せず動作しています。
- 削除ボタンがクリックされると、
ko.observablearray
クリックされたものに対応する値だけでなく、からすべての値が削除されます。 - フォーム全体の[送信]ボタンをクリックする
ko.observablearray
と、サーバーにフォームを送信する代わりに、新しい要素が追加されます。
なぜこの動作が見られるのですか?(これらが2つの別個の問題であることは知っていますが、根本的な問題が同じであるかどうかはわかりません。そのため、1つの質問に投稿します。)
これが私たちのRazorビューです:
@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>
ノックアウトコードの主要部分である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
});
}
};