在play1中,我通常在操作中获取所有数据,直接在视图中使用它们。因为我们不需要在视图中显式声明参数,所以这非常简单。
但是在play2中,我发现我们必须在视图的头部声明所有的参数(包括request
),在操作中获取所有数据并将它们传递到视图中将非常乏味。
例如,如果我需要在首页显示从数据库加载的菜单,我必须在main.scala.html
中定义它
@(title: String, menus: Seq[Menu])(content: Html)
<html><head><title>@title</title></head>
<body>
<div>
@for(menu<-menus) {
<a href="#">@menu.name</a>
}
</div>
@content
</body></html>
然后我必须在每个子页面中声明它:
@(menus: Seq[Menu])
@main("SubPage", menus) {
...
}
然后,我必须获取菜单,并在每个操作中将其传递给视图:
def index = Action {
val menus = Menu.findAll()
Ok(views.html.index(menus))
}
def index2 = Action {
val menus = Menu.findAll()
Ok(views.html.index2(menus))
}
def index3 = Action {
val menus = Menu.findAll()
Ok(views.html.index(menus3))
}
现在它在main.scala.html
中只有一个参数,如果有多个呢?
所以最后,我决定把所有的Menu.findAll()
都直接放在视图中:
@(title: String)(content: Html)
<html><head><title>@title</title></head>
<body>
<div>
@for(menu<-Menu.findAll()) {
<a href="#">@menu.name</a>
}
</div>
@content
</body></html>
我不知道它是好的还是推荐的,有没有更好的解决方案?
发布于 2012-12-17 15:02:16
我支持stian的回答。这是获得结果的一种非常快速的方法。
我刚从Java+Play1.0迁移到Java+Play2.0,到目前为止,模板是最难的部分,也是我找到的实现基本模板(标题、标题等)的最好方法。就是通过使用Http.Context。
有一个非常好的语法,你可以用标签来实现。
views
|
\--- tags
|
\------context
|
\-----get.scala.html
\-----set.scala.html
其中,get.scala.html是:
@(key:String)
@{play.mvc.Http.Context.current().args.get(key)}
set.scala.html是:
@(key:String,value:AnyRef)
@{play.mvc.Http.Context.current().args.put(key,value)}
意味着您可以在任何模板中编写以下代码
@import tags._
@context.set("myKey","myValue")
@context.get("myKey")
所以它的可读性和美感都很好。
这就是我选择的方式。stian -好的建议。证明了向下滚动查看所有答案的重要性。:)
传递HTML变量
我还没有弄清楚如何传递Html变量。
@(标题:String,内容:Html)
但是,我知道如何将它们作为块传递。
@(title:String)(content:Html)
因此,您可能希望将set.scala.html替换为
@(key:String)(value:AnyRef)
@{play.mvc.Http.Context.current().args.put(key,value)}
这样,您就可以像这样传递Html块
@context.set("head"){
<meta description="something here"/>
@callSomeFunction(withParameter)
}
编辑:我的"Set“实现的副作用
一个常见的用例:它的模板继承。
您有一个base_template.html,然后您有一个扩展base_template.html的page_template.html。
base_template.html可能看起来像这样
<html>
<head>
<title> @context.get("title")</title>
</head>
<body>
@context.get("body")
</body>
</html>
而页面模板可能看起来像这样
@context.set("body){
some page common context here..
@context.get("body")
}
@base_template()
然后您有一个页面(假设是login_page.html),如下所示
@context.set("title"){login}
@context.set("body"){
login stuff..
}
@page_template()
这里需要注意的重要一点是,您设置了两次"body“。一次在"login_page.html“中,然后在"page_template.html”中。
这似乎会触发一个副作用,只要你像我上面建议的那样实现set.scala.html。
@{play.mvc.Http.Context.current().put(key,value)}
因为页面会显示“登录资料...”两次,因为put返回了第二次放入相同键时弹出的值。(参见在java文档中放入签名)。
scala提供了一种更好的修改map的方法
@{play.mvc.Http.Context.current().args(key)=value}
不会引起这种副作用。
发布于 2012-12-12 18:14:04
如果您正在使用Java,并且只想以最简单的方式访问HTTP上下文,而不必编写拦截器和使用@With注释,那么您也可以直接从模板访问HTTP上下文。
例如,如果您需要模板中提供的变量,您可以使用以下命令将其添加到HTTP上下文中:
Http.Context.current().args.put("menus", menus)
然后,您可以使用以下命令从模板访问它:
@Http.Context.current().args.get("menus").asInstanceOf[List<Menu>]
显然,如果你用Http.Context.current().args.put("","")来乱用你的方法,你最好使用一个拦截器,但对于简单的情况,它可能会起作用。
发布于 2013-03-24 08:42:04
从Stian的回答中,我尝试了一种不同的方法。这对我很有效。
在JAVA代码中
import play.mvc.Http.Context;
Context.current().args.put("isRegisterDone", isRegisterDone);
在HTML模板标题中
@import Http.Context
@isOk = @{ Option(Context.current().args.get("isOk")).getOrElse(false).asInstanceOf[Boolean] }
并像这样使用
@if(isOk) {
<div>OK</div>
}
https://stackoverflow.com/questions/9629250
复制相似问题