在运行时更改布局模板

You*_*Ahn 6 playframework playframework-2.1

在Kohana(PHP框架)中,布局是通过Template_Controller实现的,它继承了一个名为$ template的成员变量,用作布局视图.然后在action方法中,您可以使用更多子视图(通常是内容视图)填充$ template.(http://forum.kohanaframework.org/discussion/3612/kohana-layout-system/p1)

这允许我在运行时更改布局"主题".它对多租户系统很有用,租户可以选择自己的主题(两个col,三个col等)

如何使用Scala模板引擎在playframework 2 Scala中实现这一点?换句话说,我想有一个租户可以选择的多个布局模板.然后,控制器呈现布局模板和特定于操作的内容模板.

像(Controller的动作伪代码):

  1. 基于用户,检索布局主题(在数据库中存储在字符串中的名称,并具有相应的映射视图文件).
  2. 呈现特定于操作的内容视图.
  3. 渲染从(1)获得的布局视图以及(2).

注意:对于每个操作,布局主题可能会因用户而更改,但内容视图保持不变.

在它的文档(http://www.playframework.com/documentation/2.1.1/ScalaTemplateUseCases)中
,内容模板(例如index.scala.html)包含对main.scala.html中定义的main的调用. ,布局模板.换句话说,它是硬编码的,因此index.scala.html与main.scala.html紧密耦合.

我虽然使用反射从控制器调用main,然后传递内容.

另一种方法是使用解释模板引擎,如Scalate.

有什么建议吗?

Jon*_*xon 2

我看到有两种选择可以实现您的目标。第一种是将主题参数传递给模板(即告诉被调用模板要使用哪个主题/布局的参数)并使用该参数有条件地调用布局模板。第二种是根据所选主题返回适当的视图来处理控制器内的条件。

选项1

在您的操作中,您将需要向模板传递一些值以指示要使用哪个主题。

def index = Action {
  Ok(views.html.index("two-col"))
}
Run Code Online (Sandbox Code Playgroud)

然后在你的index.scala.html你会做这样的事情:

@(theme: String)

@content = {
  <h1>Action Specific Content</h1>
}

@if("two-col" eq theme) {
  @twoCol("title")(content)
} else {
  @main("title")(content)
}
Run Code Online (Sandbox Code Playgroud)

这期望有一个twoCol.scala.html模板,例如:

@(title: String)(content: Html)
<!DOCTYPE html>
<html>
  ...
  <body>
    <h1>Two Column</h1>
    @content
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

注意:您还可以使用隐式参数传递主题,请参阅此问题。这将减少在每次渲染时显式传递模板的需要。

选项2

这将与控制器中的以下内容一样简单,但在视图模板中可能需要更多重复代码。

def index = Action {
  var theme = ...
  ...
  if (theme eq 'tow-col') {
    Ok(views.html.twocol.index("two-col"))
  } else {
    Ok(views.html.default.index())
}
Run Code Online (Sandbox Code Playgroud)

这假设有一个twocoldefault包,其中/app/views有一个index.scala.html.

补充评论

从选项 1 可以看出,index.scala.html 与 main.scala.html 并没有紧密耦合。您可以将对 main 的调用替换为对任何其他模板的调用,甚至不调用任何模板。

FWIW,我会选择选项 1,它可能会演变成一个更好的解决方案。