|
■No74262 (WebSurfer さん) に返信
お返事が遅くなり、申し訳ありません。
やっと紹介して頂いた URL 先を確認し、実現したかった機能について
完成致しました。
まず環境は下記のとおりです。
Windows 7 Pro 64bit, VS Express 2013 for Web, .NET Framework4, ASP.NET MVC 4, インターネットアプリケーションテンプレート使用, 今回はデータベース未使用, EF5, IE11
●やりたいこと
1:nモデルのビューでの登録方法について
@親と子の入力フィールドは1画面で収めたい
A子のレコードは追加、削除をしたい
B親のレコード登録時に子のレコードも追加したい
●モデル
public class VMParent
{
public int ID { get; set; }
public string Name { get; set; }
public virtual List<VMChild> Children { get; set; }
}
public class VMChild
{
public int ID { get; set; }
public string Name { get; set; }
}
●Create ビュー
@model AspdotNetTest.Model.VMParent
@using (Html.BeginForm()) {
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<fieldset>
<legend>VMParent</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)
</div>
<p>
<input type="submit" name="cmd" value="Create" />
</p>
</fieldset>
}
@* 子の入力フィールドが表示され、部分更新される個所 *@
<div id="AjaxUpdate">
@Html.Partial("_Children", Model)
</div>
●_Children 部分ビュー
@model AspdotNetTest.Model.VMParent
@{
ViewBag.Title = "Create";
TempData["Parent"] = Model;
}
@using (Ajax.BeginForm("editChild", "PartialTest", new AjaxOptions {UpdateTargetId="AjaxUpdate" }))
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<fieldset>
<legend>VMParent</legend>
<div class="editor-label">
@Html.Label("名前")
</div>
<div class="editor-field">
@Html.Editor("AddName")
@Html.ValidationMessage("AddName")
<input type="submit" name="cmd" value="Add" />
</div>
@foreach (var child in Model.Children.Select((item, index) => new { item, index }))
{
@Html.Label(child.item.Name)
<input type="submit" name="cmd" value="Delete" onclick="setDeleteIndex(@child.index)" />
}
@Html.Hidden("DeleteIndex")
<script language="JavaScript">
function setDeleteIndex(id) {
$("input[id='DeleteIndex']").val(id);
}
</script>
</fieldset>
}
●コントローラ
public ActionResult Create(VMParent parent = null)
{
if (parent.Children == null)
{
// テストデータ挿入(通常はインスタンス生成のみ)
parent = new VMParent()
{
Name = "山田太郎",
Children = new List<VMChild>()
{
new VMChild() { ID = 1, Name="一郎" },
new VMChild() { ID = 2, Name="次郎" },
}
};
}
return View(parent);
}
[HttpPost]
public ActionResult Create(FormCollection collection, string Name)
{
try
{
// TempData から VMParent モデルを持ってくる
var parent = (AspdotNetTest.Model.VMParent)TempData["Parent"];
parent.Name = Name;
// DB にデータを記録する処理はここに入れる。
return RedirectToAction("Index");
}
catch
{
return View();
}
}
public ActionResult editChild(string cmd, string AddName, string DeleteIndex)
{
ModelState.Clear(); // これを入れないと事前に入っている文字が消えない
// TempData から VMParent モデルを持ってくる
var parent = (AspdotNetTest.Model.VMParent)TempData["Parent"];
if (cmd == "Add")
{
// 追加ボタンが押されたときは、AddName を追加
parent.Children.Add(new VMChild() { Name = AddName });
}
else if (cmd == "Delete")
{
// 削除ボタンが押されたときは、指定のインデックスを削除
parent.Children.RemoveAt(Convert.ToInt32(DeleteIndex));
}
return PartialView("_Children", parent);
}
以上のような形になりました。
現在 VMParent モデルのビューとコントローラのやり取りを、 TempData を使って
いるのですが、この処理の仕方で問題ないのでしょうか?
通常は BeginForm 内でモデルのフィールドを使って Submit し、
コントローラのメソッドでバインディングが行われる(?)と思うのですが、
うまく取得できなかったため、このような仕様になりました。
(その他にも、 AntiforgeryToken や ValidationSummary の動きもよくわかっていないのですが・・・)
「これで問題ない」や「普通はこうやるべき」というようなご助言がありましたら、
ご教示頂ければ幸いです。
よろしくお願い致します。
|