書籍転載:ASP.NET MVC 5 実践プログラミング
テンプレートのカスタマイズ|テンプレートを決定する方法[Razor]
テンプレートヘルパーでは、特定のデータ型/メタ情報に応じた独自のテンプレートを用意して、独自の出力を生成することもできる。その方法を解説する。書籍転載の16本目(基礎編「4-4-2」「4-4-3」)。
書籍転載について
本コーナーは、秀和システム発行の書籍『ASP.NET MVC 5 実践プログラミング』の中から、特にBuild Insiderの読者に有用だと考えられる項目を編集部が選び、同社の許可を得て転載したものです。
『ASP.NET MVC 5 実践プログラミング』の詳細や購入は秀和システムのサイトや目次ページをご覧ください。
ご注意
本記事は、書籍の内容を改変することなく、そのまま転載したものです。このため用字用語の統一ルールなどはBuild Insiderのそれとは一致しません。あらかじめご了承ください。
4-4-2 テンプレートのカスタマイズ
テンプレートヘルパーでは、標準のテンプレートを利用するばかりではありません。特定のデータ型/メタ情報に応じて、独自のテンプレートを用意することで、独自の出力を生成することもできるのが、テンプレートヘルパーの本来の魅力です。
たとえば以下は、DateTime型のプロパティに対して、EditorForメソッドがポップアップカレンダー付きのテキストボックスを出力するための例です*25。ポップアップカレンダーの実装には、jQuery UI(8-2-4項=※転載対象外)のDatepickerウィジェットを利用します。
- *25 HTML5の<input type="date">要素でも同様のUIを実装できます。ただし、HTML5に対応していないブラウザーもまだまだ現役であることを考慮すると、jQuery UIを利用するのが無難です。
以下に、具体的な手順を追っていきます。
1EditorForメソッドのためのテンプレートを準備する
EditorForメソッドのテンプレートは、以下のパスに従って配置します*26。
- *26 本項ではEditorForを対象に手順を説明しますが、DisplayForメソッドでも、テンプレートの配置先が「~/Views/Shared/DisplayTemplates」「~/Views/コントローラー名/DisplayTemplates」になるだけで、以降の手順は同様です。
- ~/Views/Shared/EditorTemplates/Xxxxx.cshtml … アプリケーション全体で有効
- ~/Views/コントローラー名/EditorTemplates/Xxxxx.cshtml … 特定のコントローラーでのみ有効
Xxxxxの部分には型名、もしくはUIHint属性で指定するビュー名を指定します。EditorForメソッドは「UIHint属性→DataType属性→データ型」の優先順で、対応するテンプレートを検索します。
ここでは、「アプリケーション共通でDateTime型のプロパティに対応する」テンプレートを定義したいので、「~/Views/Shared/EditorTemplates/DateTime.cshtml」というテンプレートを用意します。
具体的なコードは、以下のとおりです。
@model System.DateTime?
@Html.TextBoxFor(model => model, new { @class = "form-control cal" })
|
@modelディレクティブで宣言されている型が「System.DateTime?」である点に注目してください*27。EditorForメソッドによる呼び出しでは、テンプレートに渡されるモデルも(エンティティそのものではなく)プロパティだからです。よって、テンプレート配下のTextBoxForメソッドでも「model => model.プロパティ」ではなく、「model => model」のように表します。
- *27 null許容型になっているのは、新規登録画面(Create.cshtml)ではnull値が渡されるからです。
なお、TextBoxForメソッドでclass属性を指定しているのは、あとからjQuery UIでdatepickerメソッドを呼び出す際のキーとするためです*28。これで$('.cal').datepicker()
のようにすることで、テキストボックスにカレンダー機能を付与できます。
- *28 もちろん、対応関係がとれていれば、class属性には別の名前を指定しても構いません。
【Note】EditorForメソッドのパラメーターを引用する
EditorForメソッドから任意のHTML属性を渡すこともできます。
@Html.EditorFor(model => model.Published,
new { htmlAttributes = new { @class = "form-control cal" } })
|
この場合、テンプレート側では、ビュー変数としてこれを受け取ります。
@Html.TextBoxFor(model => model, (object)ViewBag.htmlAttributes)
|
もしもテンプレート側で新たな属性を追加したいならば、以下のようにします。AnonymousObjectToHtmlAttributes
は、匿名型をIDictionary<string,object>型に変換するためのメソッドです。
@{
var attr = HtmlHelper.AnonymousObjectToHtmlAttributes((object)ViewBag.htmlAttributes);
attr.Add("tabindex", "5"); // tabindex 属性を追加
}
@Html.TextBoxFor(model => model, attr)
|
2jQuery UIライブラリをインポートする
jQuery UIを利用するには、あらかじめjQuery UIの関連リソースをプロジェクトに組み込んだ上で、レイアウトからインポートしなければなりません。具体的な方法については8-2-4項(※転載対象外)で詳説していますので、そちらを参照してください。ここでは、jQuery UIの本体に加えて、カレンダー呼び出しのコードもインポートしておきます。
$(function () {
//「class="cal"」である要素にカレンダー機能を付与
$('.cal').datepicker();
});
|
bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(
"~/Scripts/jquery-ui-{version}.js",
"~/Scripts/app.js"));
|
これで「~/bundles/jqueryui」というパスで、jQuery UI共々、app.jsがインポートされ、カレンダー機能が有効になりました。
3テンプレートの動作を確認する
以上で、自作テンプレートを有効にする手順は完了です。先ほどScaffolding機能で作成したアプリケーションを動作してみましょう。[公開日]欄にフォーカスを移動すると、冒頭の図4-7のように、ポップアップカレンダーが表示されることを確認してください。
4-4-3 テンプレートを決定する方法
先ほども触れたように、テンプレートヘルパーはあらかじめ決められた優先順位に従って、呼び出すべきテンプレートを決定します。以下に、優先順位が低い順にその方法をまとめます。
(1)標準のデータ型
前項で触れている方法です。PublishedプロパティはDateTime型なので、DateTime.cshtmlを選択します。
(2)付随的なデータ型(DataType属性)
たとえばPublishedプロパティに、以下のようなDataType属性を付与した場合、(DateTime.cshtmlではなく)Date.cshtmlを選択します*29。
- *29 動作を確認する際には、DateTime.cshtmlをリネームするなどしてください。
[DisplayName("公開日")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy年MM月dd日}")]
public DateTime Published { get; set; }
|
(3)利用するテンプレートを宣言(UIHint属性)
UIHint属性を利用することで、任意のテンプレートを紐づけることができます。たとえば、以下はPublishedプロパティにCalendar.cshtmlを関連付ける例です。通常は(2)までで賄えるのが理想ですが、特定のプロパティに対してのみ適用したいテンプレートを宣言する際には、この方法を利用します。
[DisplayName("公開日")]
[UIHint("Calendar")]
[DisplayFormat(DataFormatString = "{0:yyyy年MM月dd日}")]
public DateTime Published { get; set; }
|
(4)テンプレートヘルパーの引数
テンプレートヘルパーの第2引数で、明示的にテンプレートを指定することもできます。同一のプロパティには同じテンプレートを関連付けるのがまず基本ですので、まずはの(3)方法で賄えないかを検討してください。
以下は、Publishedプロパティに対して、CustomCal.cshtmlを関連付ける例です。
@Html.EditorFor(model => model.Published, "CustomCal", new { @class = "form-control" })
|
※以下では、本稿の前後を合わせて5回分(第14回~第18回)のみ表示しています。
連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。
14. HTMLエンコードを無効にする - Html.Rawメソッド[Razor]
デフォルトで実行されるHTML予約文字のエスケープ処理を無効にして生のままHTMLコードを出力するためのHtml.Rawメソッドについて解説。書籍転載の14本目(基礎編「4-3-4」)。
15. テンプレート関連のビューヘルパー|テンプレートの標準の挙動[Razor]
「テンプレートヘルパー」とも呼ばれるDisplayFor/EditorForメソッドについて紹介。また、テンプレートヘルパーの標準的な挙動を確認する。書籍転載の15本目(基礎編「4-4-1」)。
16. 【現在、表示中】≫ テンプレートのカスタマイズ|テンプレートを決定する方法[Razor]
テンプレートヘルパーでは、特定のデータ型/メタ情報に応じた独自のテンプレートを用意して、独自の出力を生成することもできる。その方法を解説する。書籍転載の16本目(基礎編「4-4-2」「4-4-3」)。
17. モデル単位にテンプレートを決定する - DisplayForModel/EditorForModelメソッド[Razor]
プロパティ単位ではなくモデル単位でHTMLコードを出力するDisplayForModel/EditorForModelメソッドについて解説。また、そのテンプレートを自作する方法を説明する。書籍転載の17本目(基礎編「4-4-4」)。
18. LINQとは?[C#]
LINQ to Entitiesの説明に入る前に、まずはC#の言語機能として組み込まれたクエリ機能「LINQ」について簡単に紹介する。書籍転載の18本目(基礎編「5-3-1」)。