5

データベースから動的フォームを作成する必要があります。その場でフォームフィールドを定義するために、次のエンティティがあります。

    public class FormField {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Type { get; set; }    // Possible values are: 'Radio','Combo','Text'. A dropdown will be created for a Combo type of element, a radio set for Radio type of element and a text input for Text type of element.
        public string Options { get; set; } // Only relevant in case of Radio/Combo type
        public string Default { get; set; } // Default value in case of Type 'Text' and selected value in case of Type 'Radio/Combo'
        public string Blankout { get; set; }// An expression to define when this field should be hidden 
    }

    /* A sample JSON array (from the DB) to build the form would be:
       [
        { Name:"Gender", Type:"radio", Options:["Male","Female","Unknown"], Default:"Male", Blankout:"Never" },
        { Name:"Age", Type:"text", Options:"None", Default:15, Blankout:"Never" },
        { Name:"Neighbourhood", Type:"Combo", Options:["Eastern","Western","Northern","Southern","Central"], Default:"Central", Blankout:"if (Age < 40 or Voted='Obama')" },
        { Name:"Voted", Type:"Combo", Options:["Obama","Romney","Harry Potter"], Default:"Harry Potter", Blankout:"if ((Gender='Female' and Age < 15) or Neighbourhood='Eastern'" }
       ]
    */

DBの「FormField」レコードから動的フォームを作成できますが、問題は、任意のフォームフィールドの値の変更を追跡する必要があり、値の変更が発生したときに、すべてのフォームデータをサーバーに送信する必要があることです(非同期)サーバーで「空白」式を評価するため。KnockoutJSを使用せずにこの変更追跡を行うと、応答がなくなり、非常に複雑になります。KnockoutJSのチュートリアルをいくつか実行しましたが、この特定の問題に対してViewModelを整理する方法を理解できませんでした。

どんな助けでもいただければ幸いです。

アップデート1

次のコードを使用して、このフォームデータをコントローラーに投稿しようとしました。

    $.ajax({
            type: "POST",
            url: "/MyController/GetBlankoutElements",
            contentType: 'application/json',
            dataType: 'json',
            data: JSON.stringify(ko.toJSON(self)),
            success: function(result) {
                alert(result);
                //self.HiddenElements(result.split(','));
            }
    });

私のコントローラーでは、次のコードを試しました:

    [HttpPost]
    public ActionResult GetBlankoutElements(List<MyFieldViewModel> Fields)
    {
        return Json(Fields); // List, Fields is null here
    }

彼女はMyFieldViewModelクラスがどのように見えるかです:

    public class MyFieldViewModel 
    {
        public string Title { get; set; }
        public string Name { get; set; }
        public string Type { get; set; }
        public string Default { get; set; }
        public string[] Options { get; set; }
    }

JSON経由でオブジェクトの配列をASP.NetMVC3に投稿するで説明されているヒントを試しました

以下は、 alert(ko.toJSON(self))を実行したときに出力されるJsonデータです。

    {"Fields":
        [{"Title":"CCType","Name":"CCType","Type":"Radio","Default":"Enterprise","Options":["Enterprise","Express","CVP","PCCE"]},{"Title":"Industry","Name":"Industry","Type":"Combo","Default":"Banks","Options":["Banks","ServiceProvider","Outsourcer","Airlines","Utilities","Government","Retail"]},{"Title":"Customer Lab","Name":"CustomerLab","Type":"Combo","Default":"0","Options":["0","1"]},{"Title":"No of Agents","Name":"Agents","Type":"Text","Default":"if(c.CCType==\"CVP\") then 10 else 25","Options":[]},{"Title":"ExpLicType","Name":"ExpLicType","Type":"Radio","Default":"if(c.CCType==\"Express\") then \"Enhanced\" else \"None\"","Options":["None","Premium","Standard","Enhanced"]},{"Title":"Multimedia","Name":"Multimedia","Type":"Combo","Default":"WIM","Options":["None","EIM","WIM","EIM&WIM","BSMediaRouting","MCAL"]}],
     "HiddenElements":[]
    }

必要なのは、フィールド名とユーザーが選択した値だけです。このjsonデータをMyFieldViewModelクラスにマップしても混乱しますが、選択した値を取得するにはどうすればよいですか?

アップデート2 (JSONデータマッピングが機能しました)

私が変わったとき

    data: JSON.stringify(ko.toJSON(self))

データ付き:ko.toJSON(self)

次のスクリーンショットでわかるように、マッピングは私のコントローラーで完全に機能しました。 postjsonデータからマップされたリストオブジェクトのスクリーンショットをデバッグします

現在、問題は残っています。フォームを投稿する目的は、フォームに対するユーザーの入力、つまりすべてのフォームフィールド要素に対する値でサーバーを更新することでした。 フォームフィールドの現在選択/入力された値を投稿するにはどうすればよいですか? たとえば、上のスクリーンショットでは、デフォルトは表示されますが、現在選択されている値は表示されません。

4

1 に答える 1

8

dirty flag変更を追跡するには、次の記事から使用できます: http ://www.knockmeout.net/2011/05/creating-smart-dirty-flag-in-knockoutjs.html 。

次のビューモデルを作成します。

function FormField(data) {
    var self = this;

    self.Name = ko.observable(data.Name);
    self.Type = ko.observable(data.Type);
    self.Options = ko.observableArray(data.Type != 'text' ? data.Options : []);
    self.Default = ko.observable(data.Default);
}

function ViewModel(data) {
    var self = this;

    self.Fields = ko.observableArray(ko.utils.arrayMap(data, function(item) {
        return new FormField(item);
    }));

    self.dirtyFlag = new ko.dirtyFlag(this);

    self.isDirty = ko.computed(function (){
        if (self.dirtyFlag.isDirty())
        {
            alert("Value changed!");
            // Do async update.
        }
    });
}

HTMLマークアップ:

<div data-bind="foreach: Fields">
    <b data-bind="text: Name"></b>
    <!--ko if: Type() == "combo"-->
        <select data-bind="options: Options, value: Default"></select>                 <!--/ko-->
    <!--ko if: Type() == "radio"-->
        <div data-bind="foreach: Options">
            <input type="radio" value="cherry" data-bind="value: $data, checked: $parent.Default" />
            <span data-bind="text: $data"></span>
        </div>
    <!--/ko-->    
    <!--ko if: Type() == "text"-->
        <input type="text" data-bind="value: Default"></input>                 
    <!--/ko-->   
    <br/>    
</div>

ここに作業中のフィドルがあります:http://jsfiddle.net/vyshniakov/CWTTR/

編集:

私が正しく理解した場合の質問に対する回答は次のとおりです。

すべてのフィールドをサーバーに投稿するには、ko.toJSON(self)関数を使用できます。ajax呼び出しは次のようになります。

    $.ajax({
        type: "POST",
        url: "controller/action",
        contentType: 'application/json',
        data: JSON.stringify(ko.toJSON(self)),
        success: function(result) {
            self.HiddenElements(result);
        }
    });

更新されたフィドルを見て、サーバーからの応答に応じて一部のフィールドを非表示にする方法を確認してください:http: //jsfiddle.net/vyshniakov/CWTTR/1/

于 2012-10-30T12:54:49.743 に答える