MVC、jQuery、JSON、ページング、mapRouteに関するハウツーシリーズ

ソースコードをダウンロード
はじめに
データベースシステムに大量のデータが存在するため、クライアント側の作業が非常に重要になりました。クラシックASP.NETのcode-behindアプローチでは、ASP.NETコンポーネントを使用してcode-behindファイルにほとんどの作業をコーディングすることが自然な方法です。さらに、ASP.NETコンポーネントのレンダリングとviewstateメカニズムは、現在クラシックASP.NETの弱点と考えられています。
そのため、新しいパラダイムが登場しました。この新しいパラダイムによると、開発者はパフォーマンスを低下させるviewstateなしで、より少ないレンダリングで純粋なHTMLとJavaScriptを扱うことができます。
MVCは古いデザインまたはアーキテクチャパターンとして知られていますが、上記で述べたクラシックASP.NETのボトルネックの後、特に人気を博しました。jQueryとJSONが効果的に使用されるMVCでは、高性能アプリケーションを開発できます。
前提知識
この記事は、MVC、jQuery、JSONに関するいくつかの入門レベルの記事を読んだ後に役立つ可能性があります。以下のリンクは初心者に役立つかもしれません:
コードの使用
この記事では「ハウツーシリーズ」を目標としています。そのため、すべてのスクリプトは添付のソースコードから提供されています。実際、各「ハウツー」は別々の記事になり得ます。いずれにせよ、すべての可能な回答が1つの例にまとめられています。この記事では理論的な情報よりも実践的なアプローチがあります。例えば、簡単にするためにデータベースの代わりにいくつかの静的リストが使用されています。
以下の質問に回答します:
- MVCで良いパフォーマンスでCRUDを実行する方法は?
- JavaScriptのconfirmまたはalertの代わりにjQueryダイアログを使用する方法は?
- MVCリストでページングを実行する方法は?
- jQueryを使用してMVCで「もっと見る」リンクを作成する方法は?
- リンクで属性(attribute)を使用する方法は?
- jQueryでAJAX呼び出しを実行する方法は?
- MVCでFormコレクションを使用する方法は?
- 一度に複数のレコードを削除する方法は?
- MVCでpartial actionを使用する方法は?
- MVCアプリケーションでJSON形式を使用する方法は?
- マスター詳細コンボボックスを入力する方法は?
- jQuery datepickerを使用する方法は?
- jQueryダイアログを使用してMVCで画像をアップロードする方法は?
- クライアント側でテーブル行を作成する方法は?
- Global.asaxでmapRouteをカスタマイズする方法は?
- テーブルのすべての行をcheckALLおよびuncheckALLにする方法は?
- 「データ読み込み中」を作成する方法は?
- jQueryでマスター詳細グリッドを作成する方法は?
1) MVCで良いパフォーマンスでCRUDを実行する方法は?
大まかに考えると、すべてのビジネスソリューションにはCreate-Read-Update-Delete(作成-読み取り-更新-削除)機能があります。可能であれば、「insert」と「update」の両方に同じ「保存フォーム」を使用することは、開発者にとってコスト効率が良い場合があります。同じフォームを使用することは、actionに送信されるパラメータを管理することで可能です。
フォームにグリッドのようなリスト(実際にはHTMLテーブル)と別の「new」ボタンがあると仮定します。テーブルの各行には、その行に関連する「edit」と「delete」ボタンがあります。
「New」をクリックした後、新しいページ(ここではviewと呼ばれます)にリダイレクトすることは効率的な方法ではありません。なぜなら、リダイレクトされたページでデータが保存された後、ユーザーはデータベースに追加されたデータを見るために「リストを表示」をクリックする必要があるからです。これは、リストビューへのリダイレクトと可変選択コストでデータベースからデータを選択することを意味します!
上記で述べた「newをクリックして再度リスト」のシナリオの代わりに、より良い方法を適用できます。
Create(作成):
- リストビューで「New」をクリックした後、「jQuery保存ダイアログ」が表示されます。
- createビューがjQueryダイアログにレンダリングされます。
- createフォームに入力し、「Save」を押します。
- Saveボタンが押されると、データはAJAX postを介して関連するcontrollerに送信できます。
- Ajaxフォームには
onSuccessJavaScript関数があります。 - 「
onSuccess」JavaScriptメソッドで、追加された新しい行(「onSuccess」にパラメータとして来るJSON)は、リスト全体を更新せずにリストの先頭に追加(prepend)されます。
Read(読み取り):
これはリスト操作です。可能であれば、リストフォームには必要なデータのみを表示する必要があります。以下の技術を使用できます:
- コンボボックスまたは数字によるページング、
- 「もっと見る」の実装、
- フィルタリング付きリスト。
Update(更新):
- リストビューで、リストの任意の行の「Edit」をクリックした後、選択した行のデータで同じ「jQuery保存ダイアログ」を表示できます。
- すべてのステップは「Create」と同じなので、「
onSuccess」メソッドのみが「update」操作に応じて変更されます。 - この場合、データベース更新後、編集された行のデータのみがビューで更新されます。このようにして、最後に編集されたレコードを見るためにリスト全体を更新する必要はありません。
Delete(削除):
- 見栄えの良いjQueryダイアログで確認した後、データベース削除後、選択された行のみがリストから削除されます。再び、リスト全体を更新する必要はありません。
insertとeditの両方に同じダイアログが使用されます。

PersonList.cshtmlビューのリンクは以下のとおりです:
HTML
@Html.ActionLink("New", "Save",
new { personNo = 0 }, new { @class = "newLink" })
...
@Html.ActionLink("Edit", "Save", new { personNo = item.PersonNo }, new { @class = "editLink" })
- New: 表示されるテキスト。
- Save: Controller内のaction。
- personNo: 「Save」actionに送信されるパラメータ。0の場合、ダイアログは空で開き、0より大きい場合はそのidのデータがダイアログに表示されます。
- newLink: 以下のjQueryで使用される仮想className。
JavaScript
<div id="saveDialog" title="Person Information"></div>
<script type="text/javascript">
var linkObj;
//.....
$(document).ready(function () {
//...
$('#saveDialog').dialog({
autoOpen: false,
width: 400,
resizable: false,
modal: true,
buttons: {
"Save": function () {
$("#update-message").html('');
$("#savePersonForm").submit();
},
"Cancel": function () {
$(this).dialog("close");
}
}
});
//....
setLinks();
});
// ....
function setLinks()
{
$(".editLink, .newLink, uploadPicLink").unbind('click');
$(".editLink, .newLink").click
(
function ()
{
linkObj = $(this);
var dialogDiv = $('#saveDialog');
var viewUrl = linkObj.attr('href');
$.get(viewUrl, function (data)
{
dialogDiv.html(data);
//validation
var $form = $("#savePersonForm");
$form.unbind();
$form.data("validator", null);
$.validator.unobtrusive.parse(document);
$form.validate($form.data("unobtrusiveValidation").options);
dialogDiv.dialog('open');
});
return false;
}
);
//...
} //end setLinks
</script>
PersonControllerのSave actionは以下のとおりです:C#
// ...
[HttpGet]
public ActionResult Save(int personNo)
{
Person person= new Person();
person.BirthDate = DateTime.Today;
person.PersonNo = 0;
if (personNo > 0)
{
person = Repository.GetPersonList().Where(c => c.PersonNo == personNo).FirstOrDefault();
}
return PartialView(person);
}
// ...
[HttpPost]
public JsonResult Save(Person p)
{
//...
}
// ...
2) JavaScriptのconfirmまたはalertの代わりにjQueryダイアログを使用する方法は?
カスタマイズされたメッセージボックスはWindowsアプリケーションで可能です。Webではサードパーティのコンポーネントライブラリを使用する場合に可能です。以下のようなJavaScriptボックスの代わりにjQueryダイアログを使用することも可能です:

PersonListビューのDeleteリンクは以下のとおりです:HTML
@Html.ActionLink("Delete", "DeletePerson", new { personNo =
item.PersonNo }, new { @class = "deleteLink", @pkNo = item.PersonNo })
HTMLとjQueryコードは以下のとおりです:
JavaScript
<div id="confirmDialog" title="Warning"></div>
<script type="text/javascript">
//...
$(".deleteLink").live("click", function (e) {
e.preventDefault();
// ..
$("#confirmDialog").html('<br/><br/>sure?');
$("#confirmDialog").dialog({
resizable: false,
height: 200,
width: 300,
modal: true,
buttons: {
"Yes": function () {
// ..
}, // end of yes button
"No": function () {
$(this).dialog("close");
}
} //end buttons
}); //end modal
}); //end delete
//...
</script>
3) MVCリストでページングを実行する方法は?
ページングは、データのリストとデータ転送コストを最小化するための良いアプローチの1つです。データを表示するための多くの方法を適用できます。この「ハウツー」では、ページングにコンボボックスが使用されています。ただし、必要に応じてページの下部に番号付けも可能です。これはアプリケーションと開発者に依存します。コンボボックスによるページングは以下のように開発できます。

まず、ページングのメタデータの場所を以下のように準備します:
HTML
@model AddressBook_mvc3_jQuery.Models.Paginginfo
...
<div id="paginginfo">
<hr />
<select id="PageSelect"></select>
<span class="pagingPersonNo" style="visibility:hidden">@Model.id</span>
<span class="pagingTotalCount" style="visibility:hidden">@Model.TotalCount</span>
<span class="pagingPageSize" style="visibility:hidden">@Model.PageSize</span>
<span class="pagingSummary">aaa</span>
<hr/>
</div>
<div id="content"></div>
...
ページが最初に読み込まれると、「
paginginfo」idのdivが入力され、以下のスクリプトを使用してレコードの最初のページが表示されます。JavaScript
<script type="text/javascript">
//...
function initializePaging()
{
var PersonNo = $("#paginginfo .pagingPersonNo").text();
var TotalCount = $("#paginginfo .pagingTotalCount").text();
var PageSize = $("#paginginfo .pagingPageSize").text();
var PageSelect = $("#PageSelect");
if (TotalCount==0)
{
PageSelect.html("");
$("#paginginfo").hide();
}
else
{
PageSelect.html("");
var num = Math.ceil(TotalCount/PageSize);
for (var i = 1; i <= num; i++)
{
if (i==1)
PageSelect.append($("<option selected></option>").val(i).text(i));
else
PageSelect.append($("<option></option>").val(i).text(i));
}
}
fillData(PersonNo, 1);
}
//..
function fillData(parPersonNo, parPageNo)
{
if (parPageNo)
{
$.ajax({
type: "POST",
url: "@Url.Action("GetAddressList", "Address")",
data: { personNo: parPersonNo, pageNo: parPageNo },
cache: false,
dataType: "json",
success: function (data)
{
if (data.Html)
{
$("#content").html(data.Html);
buttonizeALL();
setLinkAbilites();
setPagingSummary(parPageNo);
}
else
{
alert('opps!');
}
},
error: function(exp)
{
alert('Error address : ' + exp.responseText);
}
}); //end ajax call
} // if (parPageNo)
}//fillData
//...
</script>
Controller内のactionコードは以下のとおりです。ご覧のとおり、結果リストは
RenderPartialViewメソッドを使用して部分的にレンダリングされ、JSONオブジェクトに配置されます。C#
public class AddressController : Controller
{
//..
public JsonResult GetAddressList(int personNo, int pageNo)
{
int pageSize = 5; //it could be parameter
int skipCnt = ((pageNo - 1) * pageSize);
List<Address> list = (from x in Repository.GetAddressList() where x.PersonNo ==
personNo orderby x.AddressNo descending select x).Skip(skipCnt).Take(pageSize).ToList();
JsonResult jr = Json(new
{
Html = this.RenderPartialView("AddressList", list),
Message = "OK"
}, JsonRequestBehavior.AllowGet);
return jr;
}
//..
}
「
PageSelect」idのコンボのselecteditemが変更されると、以下のjQueryスクリプトが動作します。JavaScript
//..
$("#PageSelect").change(function ()
{
var $this = $(this);
var parPageNo = $this.val();
var parPersonNo = $("#paginginfo .pagingPersonNo").text();
fillData(parPersonNo,parPageNo);
});//PageSelect
//..
4) jQueryを使用してMVCで「もっと見る」リンクを作成する方法は?
この技術は多くの人気のあるWebサイトで使用されています。大きなリストに適用する必要があります。「もっと見る」は以下のように実現できます:

リストビューには「more」のリンクがあります。
HTML
//
<table id="NoteTable"></table>
<br />
<a href="#" style="display:none" id="more">more</a>
<div id="saveDialog" title="Notes Information"></div>
<div id="confirmDialog" title="Warning"></div>
//
「more」がクリックされると、以下のjQueryスクリプトが動作します。
JavaScript
//..
//load more results
$(function ()
{
$("#more").click(function (e)
{
e.preventDefault();
var lastNoteNo = $("#NoteTable tr:last .noteNo").text();
if (lastNoteNo)
{
var PersonNo = $("#paginginfo .pagingPersonNo").text();
fillData(PersonNo, lastNoteNo);
}
//--- scroll to bottom of page ---
var $target = $('html,body');
$target.animate({scrollTop: $target.height()}, "slow");
//--- /scroll to bottom of page ---
return false;
});
});
//..
function fillData(parPersonNo, parLastNoteNo)
{
if (parPersonNo)
{
$.ajax({
type: "POST",
url: "@Url.Action("GetNoteList", "Note")",
data: { personNo: parPersonNo, lastNoteNo: parLastNoteNo} ,
cache: false,
dataType: "json",
success: function (data)
{
if (data.Html)
{
$("#NoteTable").append(data.Html);
buttonizeALL();
setLinkAbilites();
if (data.HasMore)
$("#more").show();
else
$("#more").hide();
}
else
{
alert('opps!');
}
},
error: function(exp)
{
alert('Error address : ' + exp.responseText);
}
}); //end ajax call
} // if
}//func
// ..
Controller内の以下のactionはJSON結果を返します。
C#
public class NoteController : Controller
{
//...
public JsonResult GetNoteList(int personNo, int lastNoteNo)
{
int pageSize = 5; //it could be parameter
bool hasMore = false;
List<Note> list = null;
if (lastNoteNo == 0)
{
list = (from x in Repository.GetNoteList() where x.PersonNo == personNo
orderby x.NoteNo descending select x).Take(pageSize).ToList();
hasMore = (from x in Repository.GetNoteList() where x.PersonNo ==
personNo select x.NoteNo).Take(pageSize + 1).Count() - pageSize > 0;
}
else
{
list = (from x in Repository.GetNoteList() where x.NoteNo < lastNoteNo &&
x.PersonNo == personNo orderby x.NoteNo descending select x).Take(pageSize).ToList();
hasMore = (from x in Repository.GetNoteList() where x.NoteNo < lastNoteNo &&
x.PersonNo == personNo select x.NoteNo).Take(pageSize + 1).Count() - pageSize > 0;
}
JsonResult jr = Json(new
{
Html = this.RenderPartialView("_NoteList", list),
Message = "OK",
HasMore = hasMore
}, JsonRequestBehavior.AllowGet);
return jr;
}
// ...
}
5) リンクで属性(attribute)を使用する方法は?
これは特に編集、削除、詳細表示などのボタンに使用するのに良い機能です。
リストが作成されるとき、関連するキーがリンクに属性として追加されます。リンクのクリックイベントでそのキーが使用され、操作が簡単に行われます。
例えば、リストの各行に削除リンクがあると仮定します。行の削除リンクがクリックされると、controller内の「delete action」のパラメータとしてキーを使用することが可能です。
HTML
@Html.ActionLink("Delete", "DeletePerson", new { personNo = item.PersonNo },
new { @class = "deleteLink", @pkNo = item.PersonNo })
クライアントでソースを確認すると、以下の行が表示されます。
HTML
<a role="button" class="deleteLink ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"
href="/Person/DeletePerson/1" pkno="1"><span class="ui-button-text">Delete</span></a>
jQueryスクリプトでは、属性は以下のように使用されます。例えば、pknoは1で使用されます。
JavaScript
$(".deleteLink").live("click", function (e)
{
e.preventDefault();
var pkNo = $(this).attr("pkNo");
//..
});
6) jQueryでAJAX呼び出しを実行する方法は?
AJAX呼び出しは、アプリケーションをより高速にするための非常に良い機能です。データベースに大量のデータがある一部のアプリケーションでは、開発者は2つのデータラインで少量のデータを転送することに注意を払う必要があります。最初のラインはデータベースとアプリケーション間、2番目はアプリケーションとクライアントブラウザ間です。このような要件にはAJAX呼び出しが非常に便利です。
JavaScript
//..
$.ajax({
type: "POST",
url: "/Person/DeletePerson",
data: { personNo: pkNo },
cache: false,
dataType: "json",
success: function ()
{
//..
},
error: function (jqXHR, exception)
{
alert('Uncaught Error.\n' + jqXHR.responseText);
}
}); //end ajax call
//..
URLは以下のようにも使用できます。
JavaScript
//..
url: "@Url.Action("DeletePerson", "Person")",
// ..
7) MVCでFormコレクションを使用する方法は?
フォームがポストされると、すべてのフォーム要素がcontroller内の関連するactionにコレクションとして送信されます。controllerでは、各キーと値のペアを使用できます。以下のような保存フォームがあると仮定します:
HTML
@model AddressBook_mvc3_jQuery.Models.Address
@{ViewBag.Title = "Address"; }
@using (Ajax.BeginForm("Save", "Address", new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
OnSuccess = "saveSuccess"
}, new { @id = "saveForm" }))
{
@Html.ValidationSummary(true)
<input style="visibility:hidden" type="text" name="TBPersonNo"
id="idTBPersonNo" value="@Model.PersonNo"/>
<input style="visibility:hidden" type="text" name="TBAddressNo"
id="idTBAddressNo" value="@Model.AddressNo"/>
<br />
<fieldset>
<table>
<tr>
<td>Address Type</td>
<td>
<select name="CBAddressType" id="idCBAddressType" style="width:120px">
</select>
</td>
</tr>
<tr>
<td>Country</td>
<td>
<select name="CBcountry" id="idCBcountry" style="width:120px">
</select>
</td>
</tr>
<tr>
<td>City</td>
<td>
<select name="CBcity" id="idCBcity" style="width:120px">
</select>
</td>
</tr>
<tr>
<td>AddressText</td>
<td>
<textarea rows="4" cols="25" name="TBAddressText"
id="idTBAddressText">@Model.AddressText</textarea>
</td>
</tr>
</table>
</fieldset>
}
ビューのデータは、以下に示すようにモデルオブジェクトまたはFormCollectionとしてcontroller内のactionに送信できます:
C#
//..
[HttpPost]
public JsonResult Save(FormCollection fc)
{
object obj = null;
Address addrTmp = new Address();
addrTmp.AddressNo = Convert.ToInt32(fc["TBAddressNo"].ToString());
addrTmp.AddressTypeNo = Convert.ToInt32(fc["CBAddressType"].ToString());
addrTmp.AddressText = fc["TBAddressText"].ToString();
addrTmp.CityNo = Convert.ToInt32(fc["CBcity"].ToString()); ;
addrTmp.PersonNo = Convert.ToInt32(fc["TBPersonNo"].ToString());
if (ModelState.IsValid)
{
if (addrTmp.AddressNo == 0)
{
//find last person
//if it is database system no need to this line. Probably the AddressNo would be autoincrement
addrTmp.AddressNo = Data.Repository.GetAddressList().OrderBy(x => x.AddressNo).Last().AddressNo + 1;
Data.Repository.GetAddressList().Add(addrTmp);
obj = new { Success = true,
Message = "Added successfully",
Object = addrTmp,
operationType = "INSERT",
Html = this.RenderPartialView("_addressLine", addrTmp )
};
}
else
{
Address addr = Repository.GetAddressList().Where(c => c.AddressNo == addrTmp.AddressNo).FirstOrDefault();
addr.AddressTypeNo = addrTmp.AddressTypeNo;
addr.AddressText = addrTmp.AddressText;
addr.CityNo = addrTmp.CityNo;
addr.PersonNo = addrTmp.PersonNo;
obj = new { Success = true,
Message = "Updated successfully",
Object = addr,
operationType = "UPDATE",
Html = this.RenderPartialView("_addressLine", addr )
};
}
}
else
{
obj = new { Success = false, Message = "Please check form" };
}
return Json(obj, JsonRequestBehavior.DenyGet);
}
//..
8) 一度に複数のレコードを削除する方法は?
一部のページでは、一度に多くのレコードを削除すると作業が楽になることがあります。複数のレコードを削除することは、選択したすべてのレコードのキーを収集することで可能です。すべてのキーがcontrollerに送信された後、以下のように削除を行うことができます。

まず「deleteALL」idの「Delete Selected」ボタンがクリックされます。Yesを押した後、以下のjQueryスクリプトを使用できます。もちろん、代替スクリプトも開発できます。
JavaScript
//..
$("#deleteALL").live("click", function (e)
{
e.preventDefault();
var len = $("#NoteTable tr").length;
$("#confirmDialog").html('<br/><br/>deleting all selecteds.. sure?');
$("#confirmDialog").dialog({
resizable: false,
height: 200,
width: 300,
modal: true,
buttons:
{
"Yes": function ()
{
$(this).dialog("close");
var strSelecteds = '';
var rows = $("#NoteTable tr");
for(var i=0; i< rows.length; i++)
{
var row = $(rows).eq(i);
var span = row.find('span#cboxSpan');
var cb = row.find('span#cboxSpan').find('input.cboxDELclass');
var checked=(cb.is(':checked'));
var pkno = cb.attr("pkno");
if (checked)
{
strSelecteds = strSelecteds + pkno + ',';
}
}//
if (strSelecteds.length>0)
{
strSelecteds = strSelecteds.substring(0,strSelecteds.length-1);
}
if (strSelecteds.length>0)
{
$.ajax({
type: "POST",
url: "/Note/DeleteALL",
data: { noteNOs: strSelecteds },
cache: false,
dataType: "json",
success: function (data)
{
var strSelectedsArr = strSelecteds.split(',');
for (var i = 0; i < strSelectedsArr.length; i++)
{
var rowNo = '#row-' + strSelectedsArr[i];
$(rowNo).remove();
//alert(strSelectedsArr[i]);
}//for
$('#saveDialog').dialog('close');
$('#Message').html(data.Message);
$('#Message').delay(300).slideDown(300).delay(1000).slideUp(300);
},
error: function(jqXHR, exception)
{
alert('Uncaught Error.\n' + jqXHR.responseText);
}
}); //end ajax call
}
else
alert('No row selected');
}, // end of yes button
"No": function ()
{
$(this).dialog("close");
}
} //end buttons
}); //end modal
}); //end deleteALL
//...
上記のように、複数レコードの削除は「Note」controller内の「DeleteALL」actionへのajax呼び出しで行われます。
9) MVCでPartial Actionを使用する方法は?
一部の状況では、多くのフォームで使用する必要があるコンポーネントが必要です。例えば、以下に示すようないくつかの別々のフォームで「人物情報ボックス」が必要な場合があります。

_personinfoビューは以下のようになります。
HTML
@model AddressBook_mvc3_jQuery.Models.Person
@{ ViewBag.Title = "_personinfo"; }
<fieldset>
<legend>Person info</legend>
<table>
<tr><td><b><span> @Model.FirstName @Model.LastName </span></b>(@String.Format("{0:dd.MM.yyyy}",
Model.BirthDate))</td><td>(@Model.CategoryName)</td></tr>
</table>
</fieldset>
任意のビューでpartial actionを使用するには、以下のコード行を使用できます。
HTML
//..
<h2>Address List</h2>
<div>
@Html.Action("_personinfo", "Common")
</div>
//..
10) MVCアプリケーションでJSON形式を使用する方法は?
JSON形式は、controller内のactionにパラメータを送信するときと、actionから結果を取得するときに使用できます。以下に示すように、Note controller内のDeleteNote actionにはnoteNoパラメータがあります。ここで、pkNoは値で呼び出されるパラメータです。
JavaScript
$(".deleteLink").live("click", function (e)
{
e.preventDefault();
var pkNo = $(this).attr("pkNo");
//..
$.ajax({
type: "POST",
url: "/Note/DeleteNote",
data: { noteNo: pkNo },
cache: false,
dataType: "json",
success: function ()
{
$(rowNo).remove();
},
error: function(jqXHR, exception)
{
alert('Uncaught Error.\n' + jqXHR.responseText);
}
}); //end ajax call
//..
}); //end delete
controller内のactionからJSON結果を取得することが可能です。以下のスクリプトは結果をjsonオブジェクトとして返します。
C#
//..
[HttpPost]
public JsonResult DeleteNote(int noteNo)
{
string message = string.Empty;
try
{
Note n = Data.Repository.GetNoteList().Where(c => c.NoteNo == noteNo).FirstOrDefault();
if (n != null)
{
Data.Repository.GetNoteList().Remove(n);
message = "Deleted";
}
else
{
message = "Note not found!";
}
}
catch (Exception ex)
{
message = ex.Message;
}
return Json(new { Message = message }, JsonRequestBehavior.AllowGet);
}
//..
11) マスター詳細コンボボックスを入力する方法は?
一部のフォームでは、1つのコンボボックスを変更したときに別のコンボボックスを入力する必要があります。例えば、国-都市のペアでは、国がマスターで都市が詳細と考えることができます。

「保存フォーム」のビューのhtmlは以下のとおりです。
HTML
@model AddressBook_mvc3_jQuery.Models.Address
@{ViewBag.Title = "Address"; }
@using (Ajax.BeginForm("Save", "Address", new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
OnSuccess = "saveSuccess"
}, new { @id = "saveForm" }))
{
@Html.ValidationSummary(true)
<input style="visibility:hidden" type="text" name="TBPersonNo"
id="idTBPersonNo" value="@Model.PersonNo"/>
<input style="visibility:hidden" type="text" name="TBAddressNo"
id="idTBAddressNo" value="@Model.AddressNo"/>
<br />
<fieldset>
<table>
<tr>
<td>Address Type</td>
<td>
<select name="CBAddressType" id="idCBAddressType" style="width:120px">
</select>
</td>
</tr>
<tr>
<td>Country</td>
<td>
<select name="CBcountry" id="idCBcountry" style="width:120px">
</select>
</td>
</tr>
<tr>
<td>City</td>
<td>
<select name="CBcity" id="idCBcity" style="width:120px">
</select>
</td>
</tr>
<tr>
<td>AddressText</td>
<td>
<textarea rows="4" cols="25" name="TBAddressText"
id="idTBAddressText">@Model.AddressText</textarea>
</td>
</tr>
</table>
</fieldset>
}
最初の読み込みでは、Address controller内の「GetCountryList」actionを使用してidCBCountryコンボボックスが入力されます。その後、国コンボボックスが変更されると、以下のように都市コンボボックスが入力されます。
JavaScript
<script type="text/javascript">
$(document).ready(function () {
//...
//-----------------------------------------------------
$.ajax({
type: "POST",
url: "@Url.Action("GetCountryList", "Address")",
data: {},
cache: false,
dataType: "json",
success: function (data)
{
var idCBcountry = $("#idCBcountry");
idCBcountry.html("");
if (@Model.AddressNo>0)
{
for (var i = 0; i < data.List.length; i++)
{
var item = data.List[i];
if (item.CountryNo == @Model.CountryNo)
{
idCBcountry.append($("<option selected></option>").val(item.CountryNo).text(item.CountryName));
fillCity(item.CountryNo);
}
else
{
idCBcountry.append($("<option />").val(item.CountryNo).text(item.CountryName));
}
} //for
}
else
{
for (var i = 0; i < data.List.length; i++)
{
var item = data.List[i];
if (i==0)
{
idCBcountry.append($("<option selected></option>").val(item.CountryNo).text(item.CountryName));
fillCity(item.CountryNo);
}
else
{
idCBcountry.append($("<option />").val(item.CountryNo).text(item.CountryName));
}
} //for
}//else
},
error: function(exp)
{
alert('ErrorCountry : ' + exp.responseText);
}
});
//-----------------------------------------------------
$("#idCBcountry").change(function () {
var $this = $(this);
var CountryNo = $this.val();
if (CountryNo)
{
fillCity(CountryNo);
}//if
});
//-----------------------------------------------------
});//end of function
function fillCity(parCountryNo)
{
$.ajax({
type: "POST",
url: "@Url.Action("GetCityList", "Address")",
data: {CountryNo: parCountryNo},
cache: false,
dataType: "json",
success: function (data)
{
var idCBcity = $("#idCBcity");
idCBcity.html("");
for (var i = 0; i < data.List.length; i++)
{
var item = data.List[i];
if (item.CityNo == @Model.CityNo)
{
idCBcity.append($("<option selected></option>").val(item.CityNo).text(item.CityName));
}
else
{
idCBcity.append($("<option />").val(item.CityNo).text(item.CityName));
}
}
},
error: function(exp)
{
alert('ErrorCity : ' + exp.responseText);
}
});
}//fillCity
</script>
actionコードは以下のとおりです。リストはjsonオブジェクトに埋め込まれます。その後、上記のjQueryスクリプトで、リスト要素はインデックスで使用されます。
C#
public class AddressController : Controller
{
//..
public JsonResult GetCountryList()
{
object obj = null;
List<Country> list = Repository.GetCountryList();
obj = new { Success = true, Message = "OK", List = list };
return Json(obj, JsonRequestBehavior.AllowGet);
}
public JsonResult GetCityList(int CountryNo)
{
object obj = null;
List<City> list = Repository.GetCityList().Where(c => c.CountryNo == CountryNo).ToList(); ;
obj = new { Success = true, Message = "OK", List = list };
return Json(obj, JsonRequestBehavior.AllowGet);
}
//..
}
この技術は、ビューフォーム内の任意のhtml要素に使用できます。
12) jQuery datepickerを使用する方法は?
日付型はほぼすべてのビジネスアプリケーションで使用されます。文化の違いにより、この型を使用することは開発者にとって問題を意味することがあります。しかし、jQuery datepickerは日付型の使用を容易にします。

リストで目的の形式で日付を表示するには、以下の行を使用できます。
HTML
<span class="BirthDate"> @String.Format("{0:dd.MM.yyyy}", item.BirthDate) </span>
保存フォームでは以下のhtmlスクリプトが使用されます。
HTML
...
<div class="editor-label">
@Html.LabelFor(model => model.BirthDate)
</div>
<div class="editor-field">
@Html.TextBoxFor(model => model.BirthDate,
new { @class = "BirthDateSave",
@id = "TBBirthDate",
@Value = Model.BirthDate.ToString("dd.MM.yyyy")
})
</div>
...
jQuery Datepickerは、同じページ内で以下のスクリプトで@Html.TextboxForと連携できます。
JavaScript
<script language="javascript" type="text/javascript">
$(document).ready(function () {
$(".BirthDateSave").datepicker({
changeMonth: true,
changeYear: true,
dateFormat: 'dd.mm.yy',
showOn: 'both'
});
});
</script>
適切な.cshtmlの先頭に以下の行を含める必要があります。
HTML
..
<link href="@Url.Content("~/Content/themes/base/jquery.ui.all.css")" rel="stylesheet" type="text/css" />
<script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery-ui-1.8.11.min.js")" type="text/javascript"></script>
..
13) jQueryダイアログを使用してMVCで画像をアップロードする方法は?
画像は別のビューで簡単にアップロードできます。しかし、画像をアップロードするためだけに別のビューにリダイレクトし、その後リストビューにリダイレクトすることはコスト面で非効率的な場合があります。代わりに、リストビューで、各行のアップロードリンクをクリックしてjQueryダイアログを開き、画像を参照してアップロードできます。

「Upload Pic」がクリックされると、以下のスクリプトが動作します。
JavaScript
//..
$(".uploadPicLink").click
(
function ()
{
linkObj = $(this);
var dialogDiv = $('#savePicDialog');
var viewUrl = linkObj.attr('href');
$.get(viewUrl, function (data) {
dialogDiv.html(data);
//validation
var $form = $("#savePersonPicForm");
$form.unbind();
$form.data("validator", null);
$.validator.unobtrusive.parse(document);
$form.validate($form.data("unobtrusiveValidation").options);
dialogDiv.dialog('open');
});
return false;
}
);
//..
jQueryダイアログに読み込まれるSavePersonPicフォームは以下のとおりです。jQueryダイアログでファイルをアップロードするためにiframeが使用されます。
HTML
@model AddressBook_mvc3_jQuery.Models.Person
@{ViewBag.Title = "Save image";}
@using (Html.BeginForm("SavePersonPic", "Person", FormMethod.Post,
new
{
enctype = "multipart/form-data",
id = "savePersonPicForm",
name = "savePersonPicForm",
target = "UploadTarget"
}))
{
@Html.ValidationSummary(true)
<div id="update-message" class="error invisible"></div>
<fieldset>
<legend>Person Picture</legend>
<div class="editor-label">
<label for="file">Upload Image:</label>
</div>
<div class="editor-field">
<input type="file" name="file" id="file"/>
</div>
</fieldset>
}
<iframe id="UploadTarget"
name="UploadTarget" onload="UploadImage_Complete();"
style="position: absolute; left: -999em; top: -999em;">
</iframe>
controller内のファイルアップロードactionは以下のとおりです:
C#
public class PersonController : Controller
{
//..
//-------------- image -----
[HttpGet]
public ActionResult SavePersonPic(int personNo)
{
Person person = new Person();
if (personNo > 0)
{
person = Repository.GetPersonList().Where(c => c.PersonNo == personNo).FirstOrDefault();
}
return PartialView(person);
}
[HttpPost]
public JsonResult SavePersonPic(HttpPostedFileBase file, int personNo)
{
string message = string.Empty;
bool success = false;
string imgPath = "";
string fileName = "";
try
{
string path = System.IO.Path.Combine(Server.MapPath("~/Content/images"),
System.IO.Path.GetFileName(file.FileName));
file.SaveAs(path);
Person p = Data.Repository.GetPersonList().Where(r => r.PersonNo == personNo).FirstOrDefault();
p.imgFileName = file.FileName;
ViewBag.Message = "File uploaded successfully";
message = ViewBag.Message;
fileName = file.FileName;
imgPath = Url.Content(String.Format("~/Content/images/{0}", fileName));
success = true;
}
catch (Exception ex)
{
message = ex.Message;
success = true;
imgPath = "";
fileName = "";
}
return Json(
new { Success = success,
Message = message,
PersonNo=personNo,
ImagePath = imgPath,
FileName = fileName
},
JsonRequestBehavior.AllowGet
);
}
//------------- /image --------
// ..
}
iframeのJavaScript「onload」関数は以下のとおりです。アップロードされた画像は、行を更新せずにリストの関連行に表示されます。
JavaScript
//..
function UploadImage_Complete()
{
//Check first load of the iFrame
if (isFirstLoad == true)
{
isFirstLoad = false;
return;
}
try
{
//Reset the image form
document.getElementById("savePersonPicForm").reset();
var jsonTxt = ($('#UploadTarget').contents()).text();
var jsonObj = JSON.parse(jsonTxt);
var rowid = '#row-' + jsonObj.PersonNo;
var row = $('#personTable ' + rowid);
var imgid = "#img-" + jsonObj.PersonNo;
var img = row.find(imgid);
$(img).attr("src", jsonObj.ImagePath);
$('#Message').html(jsonObj.Message);
$('#Message').delay(300).slideDown(300).delay(1000).slideUp(300)
$('#savePicDialog').dialog('close');
}
catch (err)
{
alert(err.get_Message());
}
}
//..
14) クライアント側でテーブル行を作成する方法は?
データベースに追加されたレコードは、クライアント側のリストに表示する必要があります。これは多くの方法で行うことができます。レコードが追加された後、リストはデータベースから完全に更新できますが、これは重い操作になります。しかし、javascriptまたはjqueryを使用すると、ビュー内のすべての要素を更新せずにビューに新しい行を追加できます。ここでは2つの方法について説明します。
まず、以下のように行と行のセルがjavascriptで1つずつ作成されます。以下のスクリプトに示すように、このフォームのsubmit後、saveSuccess JavaScript関数がこのようなシナリオに使用されます。
HTML
..
@model AddressBook_mvc3_jQuery.Models.Person
@{ ViewBag.Title = "Save Person"; }
..
@using (Ajax.BeginForm("Save", "Person", new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
OnSuccess = "saveSuccess"
}, new { @id = "savePersonForm" }))
{
@Html.ValidationSummary(true)
..
}
..
saveSuccess javascriptメソッドは以下のとおりです。actionは操作タイプを含むjson結果を返します。操作に応じて、つまりINSERTまたはUPDATEに応じて、ビュー内のテーブルが変更されます。データベースに新しいレコードが追加されると、テーブルに新しい行が追加(prepend)されます。データベース内の既存のレコードが更新されると、テーブル内の関連行のみが変更されます。
JavaScript
function saveSuccess(data)
{
if (data.Success == true)
{
if (data.operationType == 'UPDATE')
{
//we update the table's row info
var parent = linkObj.closest("tr");
$(parent).animate({ opacity: 0.3 }, 200, function ()
{;});
parent.find(".FirstName").html(data.Object.FirstName);
parent.find(".LastName").html(data.Object.LastName);
parent.find(".CategoryName").html(data.Object.CategoryName);
var date = new Date(parseInt(data.Object.BirthDate.substr(6)));
var dateStr = FormatDate(date);
parent.find(".BirthDate").html(dateStr);
$(parent).animate({ opacity: 1.0 }, 200, function () {
;
});
}
else
{ //INSERT
//we add the new row to table
//we do not refresh all records on screen
try
{
var personTable = document.getElementById("personTable");
var row = personTable.insertRow(1); //row 0 is header
row.setAttribute("id", 'row-' + data.Object.PersonNo.toString());
var buttonsLinks =
'<a role="button" class="editLink ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only ui-state-hover ui-state-focus" href="/Person/Save/' + data.Object.PersonNo.toString() + '"><span class="ui-button-text">Edit</span></a> ' +
'<a role="button" class="adressLink ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" href="/Address/Index/' + data.Object.PersonNo.toString() + '"><span class="ui-button-text">Addresses</span></a> ' +
'<a role="button" class="noteLink ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" href="/Note/Index/' + data.Object.PersonNo.toString() + '"><span class="ui-button-text">Notes</span></a> ' +
'<a role="button" class="deleteLink ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" href="/Person/Delete/' + data.Object.PersonNo.toString() + '" pkno="' + data.Object.PersonNo.toString() + '"><span class="ui-button-text">Delete</span></a>';
var cellButtons = row.insertCell(0);
cellButtons.innerHTML = buttonsLinks;
var cellPersonNo = row.insertCell(1);
cellPersonNo.innerHTML = "<span class=\"PersonNo\">" + data.Object.PersonNo + "</span>";
var cellCategoryName = row.insertCell(2);
cellCategoryName.innerHTML = "<span class=\"CategoryName\">" + data.Object.CategoryName + "</span>";
var cellFN = row.insertCell(3);
cellFN.innerHTML = "<span class=\"FirstName\">" + data.Object.FirstName + "</span>";
var cellLN= row.insertCell(4);
cellLN.innerHTML = "<span class=\"LastName\">" + data.Object.LastName + "</span>";
var cellBirthDate = row.insertCell(5);
var date = new Date(parseInt(data.Object.BirthDate.substr(6)));
var dateStr = FormatDate(date);
cellBirthDate.innerHTML = "<span class=\"BirthDate\">" + dateStr + "</span>";
var cellimgFileName = row.insertCell(6);
cellimgFileName.innerHTML =
"<img id=\"img-" + data.Object.PersonNo.toString() + "\" alt=\"" + data.Object.ImgFileName + "\" src=\"/content/images/" + "noimg.jpg" + "\" height=\"35px\" width=\"50px\"><br><a class=\"uploadPicLink\" href=\"/Person/SavePersonPic/" + data.Object.PersonNo.toString() + "\" pkno=\"" + data.Object.PersonNo.toString() + "\" style=\"font-size:9px;\">Upload Pic</a>";
setLinks();
}
catch (err) {
alert(err.Message);
}
}
$('#saveDialog').dialog('close');
$('#Message').html(data.Message);
$('#Message').delay(300).slideDown(300).delay(1000).slideUp(300);
}
else {
$("#update-message").html(data.ErrorMessage);
$("#update-message").show();
}
}
上記で述べた最初の方法は古いアプローチのように見えるかもしれません。そのため、以下の2番目の方法がより適用しやすいかもしれません。この方法では、レンダリングされたhtmlを使用してテーブルに行を追加または更新します。以下のようなテーブルがあると仮定します。
HTML
@model IEnumerable<AddressBook_mvc3_jQuery.Models.Address>
<table id="AddressTable">
<tr>
<th></th>
<th>
#
</th>
<th>
AddressType
</th>
<th>
City/Country
</th>
<th>
Address Text
</th>
</tr>
@foreach (var item in Model)
{
<tr id="row-@item.AddressNo">
<td>
@Html.ActionLink("Edit", "Save",
new { addressNo = item.AddressNo, personNo = item.PersonNo }, new { @class = "editLink" })
@Html.ActionLink("Delete", "DeleteAddress",
new { addressNo = item.AddressNo }, new { @class = "deleteLink", @pkNo = item.AddressNo })
</td>
<td>
<span class="AddressNo">@item.AddressNo</span>
</td>
<td>
<span class="AddressTypeName">@item.AddressTypeName</span>
</td>
<td>
<span class="CityName">@item.CityName/@item.CountryName</span>
</td>
<td>
<span class="AddressText">@item.AddressText</span>
</td>
</tr>
}
</table>
「new」がクリックされると、以下のスクリプトがjQueryダイアログに読み込まれます。
HTML
@model AddressBook_mvc3_jQuery.Models.Address
@{ViewBag.Title = "Address"; }
@using (Ajax.BeginForm("Save", "Address", new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
OnSuccess = "saveSuccess"
}, new { @id = "saveForm" }))
{
@Html.ValidationSummary(true)
<input style="visibility:hidden" type="text"
name="TBPersonNo" id="idTBPersonNo" value="@Model.PersonNo"/>
<input style="visibility:hidden" type="text"
name="TBAddressNo" id="idTBAddressNo" value="@Model.AddressNo"/>
<br />
<fieldset>
<table>
<tr>
<td>Address Type</td>
<td>
<select name="CBAddressType" id="idCBAddressType" style="width:120px">
</select>
</td>
</tr>
<tr>
<td>Country</td>
<td>
<select name="CBcountry" id="idCBcountry" style="width:120px">
</select>
</td>
</tr>
<tr>
<td>City</td>
<td>
<select name="CBcity" id="idCBcity" style="width:120px">
</select>
</td>
</tr>
<tr>
<td>AddressText</td>
<td>
<textarea rows="4" cols="25" name="TBAddressText"
id="idTBAddressText">@Model.AddressText</textarea>
</td>
</tr>
</table>
</fieldset>
}
フォームが送信されると、controller内の以下のactionが動作します。
C#
public class AddressController : Controller
{
//..
[HttpPost]
public JsonResult Save(FormCollection fc)
{
object obj = null;
Address addrTmp = new Address();
addrTmp.AddressNo = Convert.ToInt32(fc["TBAddressNo"].ToString());
addrTmp.AddressTypeNo = Convert.ToInt32(fc["CBAddressType"].ToString());
addrTmp.AddressText = fc["TBAddressText"].ToString();
addrTmp.CityNo = Convert.ToInt32(fc["CBcity"].ToString()); ;
addrTmp.PersonNo = Convert.ToInt32(fc["TBPersonNo"].ToString());
if (ModelState.IsValid)
{
if (addrTmp.AddressNo == 0)
{
//find last person
//if it is database system no need to this line. Probably the AddressNo would be autoincrement
addrTmp.AddressNo = Data.Repository.GetAddressList().OrderBy(x => x.AddressNo).Last().AddressNo + 1;
Data.Repository.GetAddressList().Add(addrTmp);
obj = new { Success = true,
Message = "Added successfully",
Object = addrTmp,
operationType = "INSERT",
Html = this.RenderPartialView("_addressLine", addrTmp )
};
}
else
{
Address addr = Repository.GetAddressList().Where(c => c.AddressNo == addrTmp.AddressNo).FirstOrDefault();
addr.AddressTypeNo = addrTmp.AddressTypeNo;
addr.AddressText = addrTmp.AddressText;
addr.CityNo = addrTmp.CityNo;
addr.PersonNo = addrTmp.PersonNo;
obj = new { Success = true,
Message = "Updated successfully",
Object = addr,
operationType = "UPDATE",
Html = this.RenderPartialView("_addressLine", addr )
};
}
}
else
{
obj = new { Success = false, Message = "Please check form" };
}
return Json(obj, JsonRequestBehavior.DenyGet);
}
// ..
}
要求されたhtmlスクリプトを取得するためにRenderPartialViewメソッドが使用されます。
C#
//..
public static string RenderPartialView(this Controller controller, string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
viewName = controller.ControllerContext.RouteData.GetRequiredString("action");
controller.ViewData.Model = model;
using (var sw = new StringWriter())
{
ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
var viewContext = new ViewContext(controller.ControllerContext,
viewResult.View, controller.ViewData, controller.TempData, sw);
viewResult.View.Render(viewContext, sw);
return sw.GetStringBuilder().ToString();
}
}
//..
saveAddressフォームのajax postのsaveSuccess関数は以下のとおりです:
JavaScript
<script type="text/javascript">
//...
function saveSuccess(data)
{
if (data.Success == true)
{
$("#paginginfo").show();
if (data.operationType == 'UPDATE')
{
var row = linkObj.closest("tr");
// the following line can also be used to get related row
//$('#AddressTable #row-' + data.Object.AddressNo);
row.replaceWith(data.Html);
//..
}
else
{ //INSERT
try
{
$("#AddressTable tr:first").after(data.Html);
//..
}
catch (err)
{
alert(err.Message);
}
}
//..
}
else
{
//..
}
}
//..
</script>
上記で説明した2つの技術のいずれかを使用できます。
15) Global.asaxでmapRouteをカスタマイズする方法は?
クラシックasp.netアプリケーションでは、urlRewrite操作はいくつかのサードパーティのアセンブリで簡単に実現されていました。MVCアプリケーションでは、Global.asaxを使用してmapRouteをカスタマイズすることが可能です。
以下のmapRouteはGlobal.asaxのデフォルトです:
C#
public class MvcApplication : System.Web.HttpApplication
{
//..
public static void RegisterRoutes(RouteCollection routes)
{
// all new customized maproute rules can be put here
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
// ..
}
以下のスクリプトによると、
**/Save/{addressNo}/{personNo}**がリンクとして使用されます。HTML
@Html.ActionLink("Edit", "Save",
new { addressNo = item.AddressNo, personNo = item.PersonNo }, new { @class = "editLink" })
上記のリンクのスクリーンショットは以下のとおりです。

そのため、Global.asaxに以下のようなカスタマイズされたmapRouteルールを追加することが可能です。
C#
//..
routes.MapRoute(
"AddressSave",
"Address/Save/{addressNo}/{personNo}",
new { controller = "Address", action = "Save",
addressNo = UrlParameter.Optional, personNo = UrlParameter.Optional }
);
//..
上記で説明した2つの技術のいずれかを使用できます。
16) テーブルのすべての行をcheckALLおよびuncheckALLにする方法は?
多くのアプリケーションでは、テーブル内のすべてのチェックを一度にマークまたはマーク解除したい場合があります。

このような関数には以下のスクリプトを使用できます。
HTML
..
<br />
| <a href="#" class="checkALLRecords" id="checkALL">Check ALL</a> | <a href="#" class="unCheckALLRecords" id="unCheckALL">Uncheck ALL</a> |
<br />
..
<table id="NoteTable"></table>
..
JavaScript
//..
//check ALL records
$("#checkALL").live("click", function (e)
{
e.preventDefault();
CheckALL(true);
});
//uncheck ALL records
$("#unCheckALL").live("click", function (e)
{
e.preventDefault();
CheckALL(false);
});
//..
function CheckALL(state)
{
var rows = $("#NoteTable tr");
for(var i=0; i< rows.length; i++)
{
var row = $(rows).eq(i);
var span = row.find('span#cboxSpan');
var cb = row.find('span#cboxSpan').find('input.cboxDELclass');
if (state==true)
cb.attr('checked',true);
else
cb.attr('checked',false);
}
}
//..
17) 「データ読み込み中」を作成する方法は?
複数のデータ行を読み込む際、「データ読み込み中」メッセージをユーザーに表示する必要があります。

以下のdivは必要なメッセージに応じてカスタマイズできます。
HTML
..
<div id="loadMessage"></div>
..
div領域をカスタマイズするために以下のjavascript関数を使用できます。
JavaScript
..
function showLoader(root, txt) {
$("#loadMessage").html("");
$("#loadMessage").show();
var loader = '<img src="' + root + '/ajax-loader.gif" align="absmiddle">&nbsp;<span><br/>' + txt + '...</span>';
$("#loadMessage").fadeIn(100).html(loader);
}
function hideLoader() {
$("#loadMessage").hide();
}
..
18) jQueryでマスター詳細グリッドを作成する方法は?
マスター行がクリックされると、詳細行は以下に示すようにマスターグリッドの下に表示されます。

グリッドとして以下のテーブルが使用されます。
HTML
..
<table id="CountryTable" class="hovertable2"></table>
<br />
<br />
<table id="CityTable" class="hovertable"></table>
..
マスター詳細アプローチをシミュレートするために以下のjavascript関数が使用されます。
JavaScript
..
function setTableRowClick()
{
$("#CountryTable tr td.clickable").unbind('click');
$('#CountryTable tr td.clickable').click(function ()
{
var row = $(this).parent();
setRow(row);
});
//-------------
}//func
function setRow(row)
{
var rowid = row.attr('id'); //current
var higlightedCountryTableRowid = $("#pageinfo .higlightedCountryTableRowid").text();
$("#pageinfo .higlightedCountryTableRowid").html(rowid.toString());
if ((rowid==0) || (rowid!=higlightedCountryTableRowid))
{
//------
row.siblings().removeClass('diffColor');
row.addClass("diffColor");
//-------
fillCityData(rowid);
}
}
..
function fillCountryData()
{
$.ajax({
type: "POST",
url: "@Url.Action("GetCountryList", "Country")",
data: {},
cache: false,
dataType: "json",
success: function (data)
{
if (data.Html)
{
$("#CountryTable").html(data.Html);
buttonizeALL();
setLinkAbilitesCountry();
setLinkAbilitesCity();
setTableRowClick();
}
else
{
alert('opps-- country list error!');
}
},
error: function(exp)
{
alert('Error address : ' + exp.responseText);
}
}); //end ajax call
}//func
function fillCityData(parCountryNo)
{
$.ajax({
type: "POST",
url: "@Url.Action("GetCityList", "Country")",
data: { countryNo: parCountryNo},
cache: false,
dataType: "json",
success: function (data)
{
if (data.Html)
{
$("#CityTable").html(data.Html);
buttonizeALL();
setLinkAbilitesCity();
setTableRowClick();
}
else
{
alert('opps-- city list error!');
}
},
error: function(exp)
{
alert('Error address : ' + exp.responseText);
}
}); //end ajax call
}//func
..
結論
この記事がお役に立てば幸いです。