问题(有效):
我在我的应用程序中使用Play 2.1.x版本。我的应用程序有一个静态标题/工具栏,其中包含SignIn / SignOut链接。我没有在所有模板中重复状态标头html代码,而是在main.scala.html模板中创建了它。现在要更改SignIn / SignOut状态,我需要将参数传递给main.scala.html。 如果我是对的,这是我们在play中使用的所有模板的父模板,所以如果我们向主模板添加任何参数,它必须由子模板提供,例如索引,登录等(你的名字)< / p>
到目前为止,我能够通过在特征中创建隐式def并让控制器实现这样的特征(混合组合......)来实现这一点。
class ApplicationController extends Controller with ImplicitSession{
}
trait ImplicitSession {
implicit def status(implicit session: play.api.mvc.Session): Boolean = {
session.get("session") match {
case None => false
case _ => true
}
}
让我的所有其他控制器扩展ApplicationController而不是只播放Controller
object LoginController extends ApplicationController{...}
现在我的模板参数看起来像这样......
主要模板
@(title: String)(content: Html)(implicit status : Boolean)
其他模板,例如登录...
@(message: String)(implicit status : Boolean)
这很好用,但我对解决方案不满意,因为它迫使我将这个额外的隐式参数传递给我的所有模板
我真的想避免将此隐式参数传递给我的所有子模板
因为我觉得这是一个冗余的代码,实际上并不是一个好的编程实践。所以看起来我并没有在脑海中清楚地理解这个概念
编译器也迫使我将Action {隐式请求=&gt; 放到我正在创建的所有控制器上,否则只会抛出编译错误
我检查了播放包中提供的示例代码,它们很好,但我对流程的疑问并不清楚..
先谢谢
答案 0 :(得分:1)
我真的想避免将此隐式参数传递给我的所有子模板
答案是无法避免(遗憾地)。
Here's an excellent blog describing this by James Roper(谁是Typesafe的Play Framework开发人员)。
我也使用这种模式,但我更倾向于将名称ApplicationContext
用于我传递给我所有视图的案例类。
case class ApplicationContext(user: Option[User], moreData: SomeData)
trait ApplicationController extends Controller {
implicit def context[A](implicit request: Request[A]): ApplicationContext = {
// Find all necessary data needed
...
ApplicationContext(user, data)
}
}
然后我的观点通常采用以下参数(包括Lang
以使用i18n):
@(message: String)(implicit lang: Lang, context: ApplicationContext)
答案 1 :(得分:1)
为了避免这种情况,我建议不要让每个页面都使用main.scala.html。
有几种方法可以做到这一点。一种是通过连接,因为你的视图实际上只是返回连接字符串以被Result包装(Ok,BadRequest等)。
def getStuff = Action { Ok(header.scala.html(someData) + stuff.scala.html()) }
然而,这有点难看。
第二种方法是尽可能少地发送初始页面加载数据,并使用AJAX请求逐步增强视图。
//服务器端
def getStuff = Action { Ok(stuff.scala.html()) }
def getMoarStuff = Action { Ok(moarStuff.scala.html(someData)) }
//客户端
$.ajax({
method : "GET",
url : "http://localhost:9000/moar/stuff",
success : function() {
console.log("got stuff");
},
failure:function() {
console.log("failed");
}
});
这是single page application的前提和优势。您可以通过滚动自己的AJAX处理程序(参见上面的愚蠢)或使用诸如Backbone,Ember或Angular之类的JavaScript框架来实现此目的。每个都有自己的特点/优点/缺点,但重要的是要理解它们每个都可以用于Play。