1. 序章
このチュートリアルでは、 PlayFrameworkでScalaを使用してテンプレートを使用する方法を学習します。 テンプレートファイルを定義し、コントローラーからパラメーターを渡し、テンプレートで依存性注入を使用する方法を学習します。
2. テンプレートの定義
Play Frameworkテンプレートは、テンプレート変数をパラメーターとして受け取り、HTMLコードを返す関数のように機能します。 BaeldungPlayFrameworkチュートリアルのいくつかへのリンクを含むページを作成するとします。
まず、index.scala.htmlファイルをviews.Baeldungパッケージに作成します。
@(articles: List[(String, String)])
<h1>Baeldung Play tutorials</h1>
<ul>
@for(article <- articles) {
<li><a href="@article._2">@article._1</a></li>
}
</ul>
テンプレートファイルの最初の行にはパラメータが含まれています。このテンプレートでは、入力としてタプルのリストが必要です。
ファイルの残りの部分は、テンプレート操作を含むHTMLコードです。 テンプレートエンジンは、@文字で始まるすべてのものを提供します。 この例では、 @for 演算子を使用して記事のリストを反復処理し、 @ article._1 変数を使用して記事のタイトルにアクセスし、@article._2を使用します。 記事のURLにアクセスします。
3. コントローラでテンプレートを使用する
それでは、テンプレートを使用して応答を生成するコントローラーを定義しましょう:
class ViewTemplateController @Inject()(cc: ControllerComponents)
extends AbstractController(cc) {
def index = Action { implicit request =>
val articles = List(
("Introduction to Play Framework", "https://www.baeldung.com/scala/play-framework-intro"),
("Building REST API in Scala with Play Framework", "https://www.baeldung.com/scala/play-rest-api")
)
Ok(views.html.Baeldung.index(articles))
}
}
テンプレートファイルを定義すると、Play Frameworkによってクラスが自動的に作成され、HTML出力を返す関数として使用できることがわかります。
4. テンプレートでのカスタムクラスの使用
この記事では、テンプレートに2つのパラメーターを含む簡単な例を示します。 したがって、タプルを間違えずに使用するのは簡単です。 しかし、15個のパラメーターが必要な場合はどうなるでしょうか。 幸い、テンプレートを定義するときに、組み込みの型だけを使用する必要はありません。
クラスを定義すると、テンプレートとコントローラーの両方で使用できます:
case class Article(title: String, url: String)
def withClass = Action { implicit request =>
val articles = List(
Article("Introduction to Play Framework", "https://www.baeldung.com/scala/play-framework-intro"),
Article("Building REST API in Scala with Play Framework", "https://www.baeldung.com/scala/play-rest-api")
)
Ok(views.html.Baeldung.with_class(articles))
}
これで、テンプレートはArticleのリストをパラメーターとして受け入れることができます。
@(articles: List[Article])
<h1>Baeldung Play tutorials</h1>
<ul>
@for(article <- articles) {
<li><a href="@article.url">@article.title</a></li>
}
</ul>
5. テンプレートへの依存性注入
パラメータに加えて、テンプレートにオブジェクトを挿入することもできます。 これは、テンプレート内でヘルパー関数を使用する場合に役立ちます。 次の例では、短いメニューでページを定義し、依存性注入を使用して価格フォーマットをテンプレートに渡します。 コントローラから始めましょう:
case class Product(productName: String, price: Double, isAvailable: Boolean)
class MenuController @Inject()(template: views.html.Baeldung.menu, cc: ControllerComponents)
extends AbstractController(cc) {
def availableProducts = Action { implicit request =>
val products = List(
Product("coffee", 8.99, true),
Product("cake", 12.00, true),
Product("pancake", 3.00, false)
)
Ok(template(products))
}
}
上記のコードでは、テンプレートのインスタンスをコントローラーオブジェクトに挿入していることに注意してください。 これは、テンプレートに依存関係も挿入しているために必要です:
@this(priceFormatter: PriceFormatter)
@(products: List[Product])
<ul>
@for(product <- products) {
<li>@product.productName @priceFormatter(product.price)</li>
}
</ul>
テンプレートの最初の行は、テンプレートコンストラクターです。 テンプレートにコンストラクターを定義し、依存性注入を使用してテンプレートをコントローラーに渡すと、PlayFrameworkは依存性を自動的に注入します。
6. 条件付きロジック
前の例には、製品が利用可能かどうかを示すboolean変数があります。 メニューで利用できない商品の外観を変更したい場合はどうなりますか?
Play Frameworkテンプレートでは、条件演算子を使用して、使用できない製品を別の方法でレンダリングできます。
@if(product.isAvailable) {
<li>@product.productName @priceFormatter(product.price)</li>
} else {
<li><strike>@product.productName @priceFormatter(product.price)</strike></li>
}
7. テンプレートでの関数の定義
テンプレートに多くのループと条件ステートメントを追加すると、そのコードはすぐに判読できなくなり、保守が困難になります。テンプレートファイルで関数を定義することで、この問題を解決できます。
このような関数はパラメーターを受け入れ、テンプレートの一部を返します。 したがって、このアプローチを使用して、前の2つの例を書き直すことができます。
@display(product: Product) = {
@if(product.isAvailable) {
<li>@product.productName @priceFormatter(product.price)</li>
} else {
<li><strike>@product.productName @priceFormatter(product.price)</strike></li>
}
}
<ul>
@for(product <- products) {
@display(product)
}
</ul>
@display キーワードは、単一のProductパラメーターを持つ「display」と呼ばれる関数を定義します。 関数の本体は、返されるテンプレートです。 テンプレート関数でも、以前に挿入されたヘルパー関数を使用できることに注意してください。
8. 結論
この記事では、Play Frameworkでテンプレートを定義し、それらをコントローラーで使用し、依存関係をテンプレートに渡す方法を示しました。
PriceFormatter と残りのコードの実装は、GitHubで利用できます。