将参数传递给main.scala.html

时间:2013-09-16 22:33:40

标签: playframework playframework-2.0 scala-2.10

问题(有效)

我在我的应用程序中使用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; 放到我正在创建的所有控制器上,否则只会抛出编译错误

我检查了播放包中提供的示例代码,它们很好,但我对流程的疑问并不清楚..

先谢谢

2 个答案:

答案 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。