今回はASP.NET MVCで、Ajaxを使って処理中を示すクルクル回るGif画像(ローディングスピナー)を表示する方法を解説します。
MVCに用意されているAjax.BeginFormを使うと簡単に実装できるので、AjaxやjQueryに不慣れでも問題なく実装できます。
※ASP.NET Core MVCでスピナーを表示する方法については以下の記事を参照してください。
環境
- Windows10
- Visual Studio Community 2019
- .NET Framework 4.8
準備1:スピナー画像の用意
スピナー画像は次のサイトから簡単に作成できます。パターンや色を自由に選ぶことが可能です。
お好みの画像を生成してダウンロードしましょう。ファイル名はデフォルトのままで構いません。
準備2:NuGetパッケージの追加
Ajax.BeginFormを使うためにはNuGetパッケージの追加が必要です。
「ツール」→「NuGetパッケージマネージャ」→「ソリューションのNuGetパッケージの管理」をクリックし、次の画像の通り「Microsoft.jQuery.Unobtrusive.Ajax」を追加します。
パッケージのインストールが完了すると、Scriptフォルダ内に2つのファイルが追加されます。
今回の全体的なフォルダ構成は次の通りです。
準備1でダウンロードした画像は「Content」フォルダ内の「Image」フォルダに配置しました。
コードと解説
まずコントローラーです。
using System.Collections.Generic;
using System.Web.Mvc;
using System.Threading;
using WebApplication.Models;
namespace WebApplication.Controllers
{
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index(string search)
{
// 「検索」ボタンクリック時の処理
if (search != null)
{
// 画面に表示するユーザーリストの生成
var userList = new List<UserModel>
{
new UserModel { Id = 1, Name = "Mike", Age = 18 },
new UserModel { Id = 2, Name = "Jane", Age = 25 },
new UserModel { Id = 3, Name = "Bob", Age = 20 }
};
// 3秒停止
Thread.Sleep(3000);
// 部分ビューを返す
return PartialView("_IndexPartial", userList);
}
return View();
}
}
}
ビューで「検索」ボタンがクリックされたらユーザーリストを生成して、部分ビューを返します。
本来であればデータベースから取得したデータをリストに格納するかと思いますが、今回は説明用に簡略化しています。
また、ローディング表示をわかりやすくするため3秒間停止する処理を追加しています。
ユーザーリストの元となるモデルはこんな感じです。
namespace WebApplication.Models
{
public class UserModel
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
}
そして、今回の要となるビューです。
<h2>ユーザー名検索</h2>
@* Ajax.BeginFormの使用 *@
@using (Ajax.BeginForm("Index", "Home", new AjaxOptions
{
LoadingElementId = "loading",
HttpMethod = "Get",
UpdateTargetId = "target",
OnBegin = "onBegin",
OnComplete = "onComplete"
}))
{
<button class="btn btn-primary" value="search" name="search" type="submit" >
検索
</button>
@* ローディング画像の表示(初期状態は非表示) *@
<img src="@Url.Content("~/Content/Image/ajax-loader.gif")" id="loading" style="display:none;" />
}
@* 部分ビュー表示箇所 *@
<div id="target"></div>
@* Ajax.BeginFormを使うためのjqueryファイルの呼び出し *@
<script src="~/Scripts/jquery-3.4.1.min.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
@* ローディング画像の表示切り替え用スクリプト *@
<script>
function onBegin() {
$('#search').prop('disabled', true);
};
function onComplete() {
$('#search').prop('disabled', false);
};
$(document).ready(function () { });
</script>
まずAjax.BeginFormを使って、「検索」ボタンクリックをするとAjax通信を開始し、同時にローディング画像を表示するようにします。
使用しているAjaxOptionsの意味はこんな感じです。
- LoadingElementId:ロード中に表示したい画像のIDを指定
- HttpMethod:通常のBeginFormと同じくGetまたはPostを指定
- UpdateTargetId:部分ビューを表示する箇所のIDを指定
- OnBegin:Ajax通信開始時の関数名を指定
- OnComplete:Ajax通信完了時の関数名を指定
他のオプションについては公式ドキュメントを参照してください。
なお、Ajax.BeginFormを使うためにはjqueryファイルの呼び出しの記述を忘れないようにしましょう。
また今回はスクリプトを直接cshtml内に記述していますが、別にscriptファイルを作成してバンドルしたものを呼び出す方が適切かと思われます。
最後に部分ビューです。部分ビューとして認識させるためにファイル名は_(アンダースコア)で始まる名前にしましょう。
@model IEnumerable<WebApplication.Models.UserModel>
<hr />
@if (Model == null) { }
<p>全 @Model.Count() 件</p>
<table class="table table-bordered">
<thead>
<tr>
<th>
<div class="text-center">ID</div>
</th>
<th>
<div class="text-center">ユーザー名</div>
</th>
<th>
<div class="text-center">年齢</div>
</th>
</tr>
</thead>
@if (Model.Count() > 0)
{
<tbody>
@foreach (var item in Model)
{
<tr>
<td>@Html.DisplayFor(m => item.Id)</td>
<td>@Html.DisplayFor(m => item.Name)</td>
<td>@Html.DisplayFor(m => item.Age)</td>
</tr>
}
</tbody>
}
else
{
<tbody>
<tr>
<td colspan="3" align="center">データがありません</td>
</tr>
</tbody>
}
</table>
部分ビューでは特別なことはしていません。コントローラーから渡されたリストの中身をシンプルに表示しています。
実行結果
検索ボタンをクリックするとクルクルが表示されます。
3秒後に部分ビューが呼び出され、リストの中身が表示されました。
ちなみにリストが空だったときはこのような結果になります。