6

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

这允许我在运行时更改布局“主题”。这对于多租户系统很有用,租户可以选择自己的主题(两列、三列等)

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

类似于(控制器的操作伪代码):

  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。

有什么建议吗?

4

1 回答 1

2

我看到 2 个选项来完成你所追求的。第一个是将主题参数传递给您的模板(即告诉被调用模板使用哪个主题/布局)并使用该参数有条件地调用布局模板。第二个是通过基于所选主题返回适当的视图来处理控制器内部的条件。

选项1

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

def index = Action {
  Ok(views.html.index("two-col"))
}

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

@(theme: String)

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

@if("two-col" eq theme) {
  @twoCol("title")(content)
} else {
  @main("title")(content)
}

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

@(title: String)(content: Html)
<!DOCTYPE html>
<html>
  ...
  <body>
    <h1>Two Column</h1>
    @content
  </body>
</html>

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

选项 2

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

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

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

附加评论

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

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

于 2013-07-23T20:44:47.423 回答