「ASP.NET MVC と jQuery で新規登録ダイアログと編集ダイアログ」でダイアログ上での新規登録とデータの編集を行ったわけですが、その際にサーバー側でのデータ検証でエラーを把握した場合に、単純にデータ入力画面(この場合はダイアログ表示)に戻せないと書きました。実際そのとおりなのですが、サーバー側のデータを使わないと検証できないものがあるのも事実です(ページング表示でクライアント側にすべてのデータが渡されていない場合のデータの重複確認など)。
そこで、サーバー側でデータ検証エラーを把握した際に、データ入力のダイアログを再表示させる方法を考えてみました。データ検証でエラーが発生した場合、エラーメッセージと入力データをビューへ渡し、クライアント側では受け取った HTML ドキュメントからエラー発生を把握して、入力されていたデータをフォームにセットしてからダイアログを表示させれば、うまくできそうです。
動かしてみた結果は、次のとおりです。制約事項として、「メールアドレスの重複はダメ」としました。
まずは、モデル(TestModel.cs)の CreateContact メソッドにメールアドレスの存在チェックを組み込みます。同一メールアドレスが既に登録されていた場合には ValidationException を投げるようにします。
static public void CreateContat(DataModel dataModel)
{
if (_dataModel.Where(c => c.Email == dataModel.Email).Count() != 0)
throw new ValidationException("同一のメールアドレスが既に登録されているので追加できませんでした。");
dataModel.Id = _dataModel.Max(n => n.Id) + 1;
_dataModel.Add(dataModel);
}
次はコントローラー(HomeController.cs) の CreateContact(DataModel model) アクションに、ValidationException が発生したときにビューへエラーメッセージと入力データを渡すコードを組み込みます。
[HttpPost]
public ActionResult CreateContact(DataModel model)
{
try
{
TestModel.CreateContat(model);
}
catch (ValidationException e)
{
TempData["createErr"] = e.Message;
TempData["model"] = model;
}
return RedirectToAction("ListContacts");
}
最後にビュー(ListContacts.cshtml)です。フォームの入力エリアへのデータセット、<div id=”createDialog” style=”display:none;”>の次の行にエラーメッセージの表示領域の確保、そして、エラーメッセージと入力データが渡されたときに、渡された入力データのセットとダイアログ表示を行う JavaScript のセットを行うコードを組み込みます。
@model IEnumerable<TestJqueryUi004.Models.DataModel>
@{
ViewBag.Title = "連絡先一欄";
}
@section scripts {
<script type="text/javascript">
<!--
function showCreateDialog() {
$("#createDialog").dialog({
title: "新規作成",
width: 550,
height: 400,
modal: true,
buttons: {
"作成": function () {
$("#createDialog form").submit();
if ($("#createDialog form").valid()) {
$(this).dialog("close");
}
},
"キャンセル": function () {
$(this).dialog("close");
}
},
close: function () {
$(this).dialog("destroy");
}
});
}
function showEditDialog(id, name, email, phone) {
setForm("#editDialog", id, name, email, phone);
$("#editDialog").dialog({
title: "連絡先編集",
width: 550,
height: 400,
modal: true,
buttons: {
"更新": function () {
$("#editDialog form").submit();
if ($("#editDialog form").valid()) {
$(this).dialog("close");
}
},
"キャンセル": function () {
$(this).dialog("close");
}
},
close: function () {
$(this).dialog("destroy");
}
});
}
function setForm(selector, id, name, email, phone) {
$(selector + " form")
.find("input[id=Id]").val(id)
.end()
.find("input[id=Name]").val(name)
.end()
.find("input[id=Email]").val(email)
.end()
.find("input[id=Phone]").val(phone);
}
//-->
</script>
}
<h2>@ViewBag.Title</h2>
<div style="color: Red">@Html.Encode(TempData["editErr"])</div>
<p>
<a href="#" onclick="showCreateDialog()">連絡先の作成</a>
</p>
<table>
<tr>
<th>
名前
</th>
<th>
メールアドレス
</th>
<th>
電話番号
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Email)
</td>
<td>
@Html.DisplayFor(modelItem => item.Phone)
</td>
<td>
<a href="#" onclick="showEditDialog('@item.Id', '@item.Name', '@item.Email', '@item.Phone')">編集</a> |
@Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
</tr>
}
</table>
<div id="createDialog" style="display:none;">
<div style="color: Red">@Html.Encode(TempData["createErr"])</div>
@Html.Action("CreateContact")
</div>
<div id="editDialog" style="display:none;">
@Html.Action("EditContact")
</div>
<div style="display:none">
@if (TempData["createErr"] != null)
{
<script type="text/javascript">
$(
function () {
showDialogWithErr("#createDialog");
}
);
</script>
}
@if (TempData["model"] != null)
{
var errData = (TestJqueryUi004.Models.DataModel)TempData["model"];
<script type="text/javascript">
function showDialogWithErr(selector) {
var errData = $("#errData");
setForm(selector, 0, errData.find("div[class=name]").text(),
errData.find("div[class=email]").text(), errData.find("div[class=phone]").text());
if (selector == "#createDialog")
showCreateDialog();
else
showEditDialog();
}
</script>
<div id="errData">
<div class="name">@Html.Encode(errData.Name)</div>
<div class="email">@Html.Encode(errData.Email)</div>
<div class="phone">@Html.Encode(errData.Phone)</div>
</div>
}
</div>
showDialogWithErr(“#createDialog”); の呼び出しは jQuery の ready イベントで行うようにしています(省略表記で記述)。
とりあえず、こんな感じで動いています。なお、あくまで感触を掴むために書いたものなので、エラー・ハンドリングを省いています。もし参考にされる方がいらしたら、ちゃんとエラー処理をしてください 😉
何か気がついたこととかあったら、指摘していただけると嬉しいです 🙂
「入力ダイアログで入力された値のサーバーでの検証エラーの表示」への2件のフィードバック