2013-05-15 6 views
7

私が持っている問題を明確に述べるのは難しいです。検証が失敗した後にループで作成されたフォームフィールドに値を保持する方法を理解しようとしています。私はループと検証で作成された要素の束を持っているより複雑な現実のフォームを持っています。私はそれを以下の簡単な例に減らしました。

検証に失敗した場合は、ループ内に作成された「コメント」という名前のテキストエリアを使用して、以下の事前送信イメージに示されている値を保持します。

フォーム提出をデバッグすると、各フィールドの値は、ModelにあるCommentという名前のIList変数に正常に接続されます。これは私がループし、インデックスに基づいてそれらを見つけることができるようにしたいものです。

送信後、ループによって生成された各テキストエリアは、モデル内のIList変数コメントのコンマ区切りの表示を示します。ビュー内とモデル内のフィールドは、名前を共有しているため、接続しているようです。彼らは途中で適切に接続しますが、途中では接続しません。ビュー全体ではなく、コメント[i]に関連付けられた値のみを表示して、フォーム提出の間に値が一定になるようにしたいと思います。


最初のロード以下スクリーンショットとサンプルコード:
First load of form without changes

事前提出フォームの変更点:最初の提出後に見られるように
Form with changes to the first input before submitting

フォーム:
Form as seen after the first submission

秒提出後に見られるようなフォーム:
enter image description here

モデルのコード
MVC Razor ViewのHTML.Textareaの値

using System.Collections.Generic; 
namespace UI.Models.Forms 
{ 
    public class TempListModel : ContentModel 
    { 
     public TempListModel() 
     { 
      Comment = new List<string>(); 
     } 
     public IList<string> Comment { get; set; } //Comments for each URL in the list 
    } 
} 


コードの表示

@model UI.Models.Forms.TempListModel 
@using (Html.BeginForm("temptest", "Test", new { id = 1 }, FormMethod.Post, new { id = "listForm", name = "listForm" })) 
{ 
    <ul> 
     @for (int i = 0; i < Model.Comment.Count(); i++) 
     { 
      <li> 
       <div class="llformlabel"> 
        Notes: 
        <div>@Model.Comment[i]</div> 
        @Html.TextArea("Comment", Model.Comment[i], 4, 63, new { @id = "Comment_" + i, @title = "Comment" })</div> 
      </li> 
     } 
    </ul> 
    <input type="submit" value="Save Changes" /> 
} 


コントローラコード

using System.Collections.Generic; 
using System.Web.Mvc; 
using UI.Models.Forms; 
namespace UI.Controllers 
{ 
    public class TestController : Controller 
    { 
     [AcceptVerbs(HttpVerbs.Post)] 
     public ActionResult TempTest(TempListModel model) 
     { 
      //This function executes after the user submits the form. 
      //If server side validation fails then the user should be shown the form as it was when they submitted. 
      //model.Comment = GetComments(); //In my real world example this comes from a database. 
      if (true) //!ModelState.IsValid) //In my real world code this is a validation step that may fail 
      { 
       return View(model); 
      } 
     } 
     [AcceptVerbs(HttpVerbs.Get)] 
     public ActionResult TempTest(int? id) 
     { 
      //In the real world example there is a lot going on in this function. 
      //It is used to load data from databases and set up the model to be displayed. 
      var model = new TempListModel(); 
      model.Comment = GetComments(); 
      return View("TempTest", "TempLayout", model); 
     } 
     private static IList<string> GetComments() 
     { 
      //Simple sample function used for demo purposes. 
      IList<string> comments = new List<string>(); 
      comments.Add("Comment 1"); 
      comments.Add("Comment 2"); 
      comments.Add("Comment 3"); 
      return comments; 
     } 
    } 
} 

答えて

8

あなたが検証に失敗した場合は、単にモデルを返します。

[AcceptVerbs(HttpVerbs.Post)] 
    public ActionResult TempTest(TempListModel model) 
    { 
     if (ModelState.IsValid) 
     { 
      return RedirectToAction("TempTest"); 
     } 
     return View(model); 
    } 

編集

@for (int i = 0; i < Model.Comment.Count(); i++) 
{ 
    <li> 
     @Html.TextAreaFor(m => m.Comment[i], 4, 63, new { @title = "Comment" }) 
    </li> 
} 

代わりに、あなたのビューでこれを試してみて、ヘルパーはあなたのための要素に名前を付けましょう。あなたはnameという属性(Comment[i]など)になります。

+0

RedirectToActionの代わりにビューを使用するようにコードサンプルを変更したので、GetComments関数が値を上書きしていないことがより明確になりました。私は現在のコードサンプルが示唆しているように表示していると思いますが、それと同じ問題があります。 – RacerNerd

+0

@RacerNerd編集を参照してください。 – Jasen

+0

ありがとうございます。これはトリックでした。それは、モデルの変数に接続するhtmlフィールドを必要とするたびに、 "For"でhtmlジェネレータを使用する方が適切ですか?私が作業しているコードは、変数の接続はほとんどがここで見ているようにすべての場合にうまくいかないような名前の一致によって実現されているようです。 – RacerNerd

2

ASP。NET MVCのデフォルトModelBinderは、モデル内にモデルを構築するためにTempListModelプロパティに一致するHTML名を要求内で検索します。しかし、あなたは、各HTML要素のコメントIDを上書きされています

@Html.TextArea("Comment", Model.Comment[i], 4, 63, new { @id = "Comment_" + i, @title = "Comment" }) 

このカスタムIDを配置する必要がある場合は、あなたが新しいModelBinderを作成する必要があります。

@Html.TextAreaFor(m => m.Comment[i], 4, 63, new { @title = "Comment" }) 

あなたは、その助けをホープス

: あなたは、このような簡単なものを維持することができます!

+1

こんにちはファルス。これを見ていただきありがとうございます。 Jasenはあなたにそれを打ちのめしましたが、私の理解を助けるために追加された説明に感謝します。 – RacerNerd

関連する問題