播放视图中的变量
variables in play views
我在网上找到了一些关于我的问题的答案,但都是针对不再有效的旧版游戏。
我正在尝试找到一种方法来使用变量作为模板路径的一部分。
我知道这将删除类型检查等,但它是一个 generator/prototyping/internal 工具,不会看到 public/outside 世界。
代码如下:
我能找到的最佳解决方案是:
def index(page: String) = Action {
page match {
case "something" => Ok(views.html.examples.something())
case "else" => Ok(views.html.examples.else())
case "another" => Ok(views.html.examples.elements.another())
}
}
理想情况下,这样的事情会更有意义:
def index(page: String) = Action {
Ok(views.html.getClassFromStringOrSomething(page));
}
我正在使用带有 scala 的最新播放框架 (2.5.*)。
使用火柴是唯一的方法吗?
一定要有动态为什么要return一个视图?
n.b。我在网上发现了很多使用 play.api.templates.Html/play.twirl.api.Html
的建议,但似乎不再有效,无法找到 Html
,所以我猜 api 已经改变了其他版本。
使用我得到:
def index(page: String, parent: String) = Action {
val clazz: Class[_] = Play.current.classloader.loadClass(page)
val render: Method = clazz.getDeclaredMethod("render")
val view = Some(render.invoke(clazz).asInstanceOf[play.twirl.api.Html])
Ok(view)
}
这给我错误
Cannot write an instance of Some[play.twirl.api.Html] to HTTP response. Try to define a Writeable[Some[play.twirl.api.Html]]
这就是我卡住的地方
我在这里添加了一个答案,只是为了帮助遇到此问题的其他人。
@Mikesname 是正确的,删除 Some()
并且它 'should' 一切正常。
问题是我动态加载了 class/view 名称,但我没有使用完整的 class 名称。当我应该加载 view.html.something
.
时,我正在加载 something
这是我用来使该功能正常工作的代码
(需要清理但它正在工作,还考虑了目录中名为 index
的视图,即 views.html.parent -> /parent/index.scala.html
package controllers
import javax.inject.{Inject, Singleton}
import play.api.Play
import play.api.mvc.{Action, Controller}
import play.twirl.api.Html
@Singleton
class PathController @Inject() extends Controller {
def index(page: String, parent: String, grandparent: String) = Action {
Ok(buildView(buildClassName(page, parent, grandparent)))
}
def buildClassName(page: String, parent: String, grandparent: String): String = {
val pathGrandParent = if (grandparent != null) grandparent + '.' else ""
val pathParent = if (parent != null) parent + '.' else ""
"views.html." + pathGrandParent + pathParent + page
}
def loadClass(name: String): Class[_] = {
try {
Play.current.classloader.loadClass(name)
} catch {
case _: Throwable => {
Play.current.classloader.loadClass(name + ".index")
}
}
}
def buildView(name: String): Html = {
val clazz = loadClass(name)
clazz.getDeclaredMethod("render").invoke(clazz).asInstanceOf[play.twirl.api.Html]
}
}
我想有一种比 try/catch 更好的方法来处理索引视图部分,但是对于我正在构建的工具来说这很好
我在网上找到了一些关于我的问题的答案,但都是针对不再有效的旧版游戏。
我正在尝试找到一种方法来使用变量作为模板路径的一部分。 我知道这将删除类型检查等,但它是一个 generator/prototyping/internal 工具,不会看到 public/outside 世界。
代码如下:
我能找到的最佳解决方案是:
def index(page: String) = Action {
page match {
case "something" => Ok(views.html.examples.something())
case "else" => Ok(views.html.examples.else())
case "another" => Ok(views.html.examples.elements.another())
}
}
理想情况下,这样的事情会更有意义:
def index(page: String) = Action {
Ok(views.html.getClassFromStringOrSomething(page));
}
我正在使用带有 scala 的最新播放框架 (2.5.*)。
使用火柴是唯一的方法吗? 一定要有动态为什么要return一个视图?
n.b。我在网上发现了很多使用 play.api.templates.Html/play.twirl.api.Html
的建议,但似乎不再有效,无法找到 Html
,所以我猜 api 已经改变了其他版本。
使用我得到:
def index(page: String, parent: String) = Action {
val clazz: Class[_] = Play.current.classloader.loadClass(page)
val render: Method = clazz.getDeclaredMethod("render")
val view = Some(render.invoke(clazz).asInstanceOf[play.twirl.api.Html])
Ok(view)
}
这给我错误
Cannot write an instance of Some[play.twirl.api.Html] to HTTP response. Try to define a Writeable[Some[play.twirl.api.Html]]
这就是我卡住的地方
我在这里添加了一个答案,只是为了帮助遇到此问题的其他人。
@Mikesname 是正确的,删除 Some()
并且它 'should' 一切正常。
问题是我动态加载了 class/view 名称,但我没有使用完整的 class 名称。当我应该加载 view.html.something
.
something
这是我用来使该功能正常工作的代码
(需要清理但它正在工作,还考虑了目录中名为 index
的视图,即 views.html.parent -> /parent/index.scala.html
package controllers
import javax.inject.{Inject, Singleton}
import play.api.Play
import play.api.mvc.{Action, Controller}
import play.twirl.api.Html
@Singleton
class PathController @Inject() extends Controller {
def index(page: String, parent: String, grandparent: String) = Action {
Ok(buildView(buildClassName(page, parent, grandparent)))
}
def buildClassName(page: String, parent: String, grandparent: String): String = {
val pathGrandParent = if (grandparent != null) grandparent + '.' else ""
val pathParent = if (parent != null) parent + '.' else ""
"views.html." + pathGrandParent + pathParent + page
}
def loadClass(name: String): Class[_] = {
try {
Play.current.classloader.loadClass(name)
} catch {
case _: Throwable => {
Play.current.classloader.loadClass(name + ".index")
}
}
}
def buildView(name: String): Html = {
val clazz = loadClass(name)
clazz.getDeclaredMethod("render").invoke(clazz).asInstanceOf[play.twirl.api.Html]
}
}
我想有一种比 try/catch 更好的方法来处理索引视图部分,但是对于我正在构建的工具来说这很好