在运行时更改布局模板

时间:2013-06-24 12:54:05

标签: 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)。
  4. 注意:对于每个操作,布局主题可能会因用户而更改,但内容视图保持不变。

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

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

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

    有什么建议吗?

1 个答案:

答案 0 :(得分: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())
}

这假设twocol中的default/app/views个包有index.scala.html

其他评论

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

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