播放视图中的变量

时间:2016-10-04 14:04:11

标签: scala playframework playframework-2.0

我已经在网上找到了一些我的问题的答案,但所有旧版本的游戏都不再适用。

我试图找到一种方法来将变量用作模板路径的一部分。 我知道这将删除类型检查等,但它用于生成器/原型/内部工具,并且不会看到公共/外部世界。

这里是codez:

我能找到的最佳答案是:

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));
}

我正在使用最新的Play框架(2.5。*)和scala。

唯一的方式是使用匹配? 必须有一个动态的回归视图?

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]]这就是我被困的地方

1 个答案:

答案 0 :(得分:0)

我在这里添加了一个答案,仅仅是为了帮助其他人解决这个问题。

@Mikesname是正确的,删除​​Some()并且'应该'一切正常。

问题是我正在动态加载类/视图名称,但我没有使用完整的类名。我应该在加载something时加载view.html.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的索引视图部分,但它对我正在构建的工具很好