Partial View を使用してクライアント側で部分 HTML を非同期で読み込む

ページ更新日 :
ページ作成日 :

環境

Visual Studio
  • Visual Studio 2019
ASP.NET Core
  • 3.1

動的な HTML 要素の追加について

動的に HTML 要素を追加する場合、一般的には Javascript などで要素を追加していくことになりますが、 Web サーバー側とは独立して処理を行うため、属性値など二重で管理しなければならないことがあります。

ASP.NET Core では部分ビュー(Partial View)を使用することにより、 サーバー側で定義した部分 HTML (.cshtml) にサーバー処理を加えた状態で HTML を取得することができます。 クライアント側ではこの HTML を取得して指定箇所に要素を追加します。

サンプル内容

部分ビューとして <ul><li> の一覧を定義しています。

Server Partial の箇所は部分ビューを index.cshtml に定義したものを表示しています。 そのため、サーバーからビューを受け取った時点で展開しています。

Client Load Ajax Partial の箇所は、クライアントで HTML を取得し画面表示が行った直後に Javascript でサーバーから部分ビューを取得して表示します。

Button Ajax Partial の箇所は、ボタンを押したタイミングで Javascript でサーバーから部分ビューを取得して表示します。処理内容は Load と同じです。 一応読み込めなかった場合のエラー処理も記述しています。

コントローラー (HomeController.cs)

Load 時に読み込む部分ビューとボタン押下時に読み込む部分ビュー用のアクションを定義します。

部分ビューを返すには PartialView メソッドを呼び出して return します。 PartialView にもモデルをバインドできるので、ここでは List<string> をバインドさせています。 実際にどの型をバインドさせるかはビュー側で定義でき、これは index.cshtml などの Razor 構文とまったく同じです。

ビュー名の指定の仕方は他のビュー関数と同じです。

public class HomeController : Controller
{
  // :
  // :

  public IActionResult PartialLoad()
  {
    var list = new List<string>() { "Load1", "Load2", "Load3" };

    // PartialView を呼ぶこと
    return PartialView("Partial", list);
  }

  public IActionResult PartialButton()
  {
    var list = new List<string>() { "Button1", "Button2", "Button3" };

    // PartialView を呼ぶこと
    return PartialView("Partial", list);
  }
}

部分ビュー (Views/Home/Partial.cshtml)

Partial.cshtml に部分ビューを定義します。内容はバインドされた文字列の一覧を li タグで並べているだけです。 作り方は通常のビューとまったく同じなので特に注意することはありません。 Razor 構文なので C# のコードを埋め込むことも可能です。

部分ビューのファイル名やフォルダの階層はビューの配置法則に従っていればどこに置いていても構いません。

@model List<string>

<ul>
  @foreach (var item in Model)
  {
    <li>@item</li>
  }
</ul>

ビュー (HTML) (Views/Home/index.cshtml)

HTML 側の定義ですが、基本的には表示部分が大半なので説明すべき箇所は少ないです。

Server Partial の部分については partial タグを指定することによって、 指定した部分ビューを展開することができます。 name にビュー名を指定し、model にバインドパラメータを指定します。コントローラー側の PartialView メソッドと同様です。 ちなみにこれはサーバー側での展開処理になるので、クライアントでは HTML を受け取った時点ですでに展開済みとなっています。

Client Load Ajax PartialButton Ajax Partial では非同期で取得した部分ビューを div タグに展開するように配置しています。 ボタン側では正常に取得できるボタンとわざと存在しないアクションを指定するボタンを配置しています。

<h3>Server Partial</h3>
<p>
  リクエスト後のレスポンス HTML 時点で部分ビューが展開されている。
</p>
<partial name="Partial" model="@(new List<string>() { "Server1", "Server2", "Server3" })" />

<h3>Client Load Ajax Partial</h3>
<p>
  画面表示後に自動的にビューが読み込まれる。<br />
  Web ブラウザのデバッガのブレークポイントでスクリプトの処理を止めれば
  表示のタイミングでは読み込まれていないことは確認できる。
</p>
<div id="load_area">読み込み中…。</div>

<h3>Button Ajax Partial</h3>
<p>ボタンを押すとビューが読み込まれる</p>
<button type="button" id="button1" class="btn btn-primary">Partial View 読み込み (正常)</button>
<button type="button" id="button2" class="btn btn-danger">Partial View 読み込み (エラー)</button>
<div id="message"></div>
<div id="button_area"></div>

ビュー (Javascript) (Views/Home/index.cshtml)

Javascript 側では初期表示後の処理とボタン押下時の処理を記述しています。

jQuery オブジェクトに対して load 関数を呼び出し、 第1引数に対象のアクション(URL)を指定することによって非同期で部分ビューを取得することができます。 取得した内容が HTML であれば、jQuery オブジェクト内部の HTML として埋め込むことができます。

第2引数にはコールバック関数を指定することができ、取得したステータスなどを参照することができます。 取得した結果が正常かエラーかによって処理を分岐させることが可能です。

この load 関数は get 関数や ajax 関数に置き換えることも可能ですが、処理内容は若干増えます。

$(document).ready(function () {

  // 画面表示後のタイミングで読み込む
  $("#load_area").load("/Home/PartialLoad");

  // ボタンを押したときに読み込む
  $("#button1").click(function () {
    // 存在するアクションを指定
    loadPartialView('/Home/PartialButton');
  });
  $("#button2").click(function () {
    // 存在しないアクションを指定
    loadPartialView('/Home/PartialButton_xxxxxxxx');
  });
});

// 指定したパスの partial view を読み込む
function loadPartialView(loadPath) {
  $("#button_area").text('読み込み中…。');
  $("#button_area").load(loadPath, function (response, status, xhr) {
  // status === 'error' ならエラーと判断
  if (status === 'error') {
    $('#message').text('エラー (status : ' + xhr.status + ', statusText : ' + xhr.statusText + ')');
  } else {
    $('#message').text('正常 (status : ' + xhr.status + ', statusText : ' + xhr.statusText + ')');
  }
});