3

フォームを表示するRazorとKnockout.jsを使用したビューがあります。フォームの一部はユーザーに値のリストを入力するように要求し、私たちはko.observablearrayそれらを追跡するためにを使用しています。このリストは、値ごとに1つずつ、一連​​のテキストボックスとして表され、各ボックスの横に[削除]ボタンがあり、すべての下に1つの[追加]ボタンがあります。これは、 http://learn.knockoutjs.com/#/?tutorial=collectionsのデモプロジェクトと同様に機能します。

私たちのフォームは、2つの方法で予期せず動作しています。

  1. 削除ボタンがクリックされると、ko.observablearrayクリックされたものに対応する値だけでなく、からすべての値が削除されます。
  2. フォーム全体の[送信]ボタンをクリックする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
        });
    }
};
4

2 に答える 2

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を見てください。明らかな理由で送信機能をテストしていません;-)

于 2012-10-30T11:07:53.660 に答える
0

これが、フォームで送信機能が機能しなかった理由です。

ビューには、次の Razor がありました。

<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" />
于 2012-11-20T21:30:21.113 に答える