2012-10-30 26 views
5

データベースから動的フォームを構築する必要があります。私はその場でフォームのフィールドを定義するエンティティを次ていますknockoutjsを使った動的フォーム構築

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に「フォームフィールド」の記録からダイナミックなフォームを作成することができますが、問題は、私はすべてのフォームフィールドの値の変化を追跡する必要があります値の変更が発生した場合、サーバー上の「Blankout」式を評価するために、すべてのフォームデータをサーバーに(非同期に)送信する必要があります。私がKnockoutJSなしでこの変更を追跡すると、その応答がなく、非常に非常に複雑になります。 私はKnockoutJSのいくつかのチュートリアルを終えましたが、この特定の問題に対してViewModelを構成する方法を理解できませんでした。

ご協力いただければ幸いです。

アップデート1

私は、次のコードを使用してコントローラにこのフォームデータをポストすることを試みた:

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

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

$.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(',')); 
      } 
    }); 

を彼女はMyFieldViewModelクラスの外観です:

私は私が必要なもの 警告(ko.toJSON(自己))

{"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データがちょうどです後Post an Array of Objects via JSON to ASP.Net MVC3

で説明したヒントを試してみました

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; } 
    } 

フィールド名とその選択された値をユーザーが、私は私のMyFieldViewModelクラスにマッピングされているこのjsonデータを取得した場合でも私は混乱して、選択された値を得るだろうか? ko.toJSON(自己)

マッピングは私のコントローラ上で完全に働いた:私は データと

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

を変更した場合

アップデート2

(JSONデータのマッピングは、働いていました)次のスクリーンショットのように表示されます。 Debug screenshot of Mapped list object from post json data

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

答えて

8

変更を追跡するには、dirty flaghttp://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呼び出しは、以下のようになります。http://jsfiddle.net/vyshniakov/CWTTR/1/:サーバーからの応答に応じて、いくつかのフィールドを隠す方法を確認するには、更新フィドルで

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

ルック。

+0

このような素早い対応のために@Artemに感謝します。これは動的フォーム部分の構築に応答します。また、実行時にフィールドの一部を非表示にする必要があります.AJAXリクエストのデータ属性に要素名を静的に入力できない場合、サーバーに「すべてのフォームデータ」をポストします。次に、serverがJSONリストを返します。これらの要素の名前は、非表示にする必要があります。フォーム上のそのような要素はすべて消えてしまいます(以前は隠されていた他の要素を消しています)。あなたが私の問題を理解したことを願っていますあなたの努力を本当に感謝します。 –

+0

@Akeel - あなたが近くにいるように聞こえます。あなたは 'Blankout'を観測可能にし、それぞれに対して' visible'または 'if'のどちらかのバインディングを使うか、非隠しフィールド(配列を返します)を表す計算を作成し、それを使って' foreach'を作成します。ダーティー・フラグが発生したとき、そして応答が返ってくるときにAJAXリクエストを行うことができます。それぞれのフィールドで 'Blankout'オブザーバブルを更新します。あなたのシナリオを正しく理解していますか? –

+0

@Akeel最新の記事を参照してください。 –

関連する問題