私の意見では、テンプレートが静的に型付けされるという事実は実際には良いことですことです。コンパイルしてもテンプレートの呼び出しが失敗しないことが保証されています。
ただし、実際には呼び出し元サイトに定型文が追加されます。しかし、あなたはそれを減らすことができます(静的型付けの利点を失うなく)。
Scalaでは、それを実現する2つの方法を考えます。アクションの合成を使用する方法と、暗黙のパラメーターを使用する方法です。Javaでは、Http.Context.args
マップを使用して有用な値を格納し、テンプレートパラメータとして明示的に渡す必要なくテンプレートからそれらを取得することをお勧めします。
暗黙的なパラメーターの使用
テンプレートパラメータのmenus
最後にパラメータを配置し、main.scala.html
「暗黙的」としてマークします。
@(title: String)(content: Html)(implicit menus: Seq[Menu])
<html>
<head><title>@title</title></head>
<body>
<div>
@for(menu<-menus) {
<a href="#">@menu.name</a>
}
</div>
@content
</body>
</html>
このメインテンプレートを呼び出すテンプレートがある場合、これらのテンプレートでも暗黙的なパラメーターとして宣言されている場合、Scalaコンパイラーによってmenus
パラメーターがテンプレートに暗黙的に渡されますmain
。
@()(implicit menus: Seq[Menu])
@main("SubPage") {
...
}
ただし、それをコントローラーから暗黙的に渡したい場合は、テンプレートを呼び出すスコープから使用できる暗黙的な値として提供する必要があります。たとえば、コントローラーで次のメソッドを宣言できます。
implicit val menu: Seq[Menu] = Menu.findAll
次に、アクションで次のように書くことができます:
def index = Action {
Ok(views.html.index())
}
def index2 = Action {
Ok(views.html.index2())
}
このアプローチの詳細については、このブログの投稿とこのコードサンプルをご覧ください。
更新:このパターンを示す素晴らしいブログ投稿もここに書かれています。
アクション構成の使用
実際、RequestHeader
テンプレートに値を渡すと便利な場合があります(このサンプルを参照)。暗黙のリクエスト値を受け取るアクションを簡単に記述できるため、これはコントローラーコードにそれほど多くの定型文を追加しません。
def index = Action { implicit request =>
Ok(views.html.index()) // The `request` value is implicitly passed by the compiler
}
したがって、テンプレートは少なくともこの暗黙的なパラメータを受け取ることが多いため、メニューなどを含むより豊富な値に置き換えることができます。これは、Play 2のアクション構成メカニズムを使用して行うことができます。
これを行うにはContext
、基になるリクエストをラップしてクラスを定義する必要があります。
case class Context(menus: Seq[Menu], request: Request[AnyContent])
extends WrappedRequest(request)
次に、次のActionWithMenu
メソッドを定義できます。
def ActionWithMenu(f: Context => Result) = {
Action { request =>
f(Context(Menu.findAll, request))
}
}
これは次のように使用できます:
def index = ActionWithMenu { implicit context =>
Ok(views.html.index())
}
また、コンテキストをテンプレートの暗黙的なパラメーターとして使用できます。例main.scala.html
:
@(title: String)(content: Html)(implicit context: Context)
<html><head><title>@title</title></head>
<body>
<div>
@for(menu <- context.menus) {
<a href="#">@menu.name</a>
}
</div>
@content
</body>
</html>
アクションコンポジションを使用すると、テンプレートに必要なすべての暗黙的な値を1つの値に集約できますが、一方で柔軟性が失われる可能性があります…
Http.Contextの使用(Java)
JavaにはScalaの暗黙のメカニズムなどがないため、テンプレートパラメータを明示的に渡さないようにしたい場合Http.Context
は、リクエストの期間のみ有効なオブジェクトにテンプレートパラメータを格納する方法が考えられます。このオブジェクトには、args
タイプの値が含まれますMap<String, Object>
。
したがって、ドキュメントで説明されているように、インターセプターを作成することから始めることができます。
public class Menus extends Action.Simple {
public Result call(Http.Context ctx) throws Throwable {
ctx.args.put("menus", Menu.find.all());
return delegate.call(ctx);
}
public static List<Menu> current() {
return (List<Menu>)Http.Context.current().args.get("menus");
}
}
staticメソッドは、現在のコンテキストからメニューを取得するための省略形です。次に、Menus
アクションインターセプターと混合するようにコントローラーに注釈を付けます。
@With(Menus.class)
public class Application extends Controller {
// …
}
最後に、menus
次のようにテンプレートから値を取得します。
@(title: String)(content: Html)
<html>
<head><title>@title</title></head>
<body>
<div>
@for(menu <- Menus.current()) {
<a href="#">@menu.name</a>
}
</div>
@content
</body>
</html>