为什么我不能在Play Framework 2视图中将Scala代码与HTML混合使用?

时间:2014-02-09 10:36:29

标签: scala playframework playframework-2.2

我制作了一个应该读取JSON文件的示例,并在Play Framework 2.2的常规视图中将其数据显示为HTML。

视图如下所示:

@(json: play.api.libs.json.JsValue)

@import play.api.libs.json._

@main("JSON Read") {

    <h1>JSON Read</h1>

    <p>This sample reads a JSON file containing some book categories and a few books inside these categories.</p>
    <!-- THIS WORKS -->
    <p>This link demonstrates a route with parameter: <a href="@routes.JsonSamples.bookdetails("12345678")">Link to book 12345678</a></p>

    @json.as[List[JsObject]].map { section =>
        <table>
            <caption>
                <h2>@{(section \ "title").as[String]}</h2>
                <p>@{(section \ "description").as[String]}</p>
            </caption>
            <thead>
                <tr>
                    <th>Book Title</th>
                    <th>Description</th>
                </tr>
            </thead>
            <tbody>
        @{(section \ "entries").as[List[JsObject]].map { entry =>
                <tr>
                    <td>
                        <!-- By the way... I can't even use @* *@ comments here. Why? -->

                        <!-- I DON'T KNOW WHAT TO PUT INTO HREF, NOTHING WORKS, SEE BELOW -->
                        <a href="#">
                            {(entry \ "title").as[String]}
                        </a>

                        <!-- THIS WORKS -->
                        (ID: {(entry \ "id").as[String]})
                    </td>
                    <td>
                        <p>{(entry \ "description").as[String]}</p>
                        <p>Order link: {(entry \ "link").as[String]}</p>
                    </td>
                </tr>
        }}
            </tbody>
        </table>
    }

}

在中间某处您可以看到我尝试为每本书插入生成的链接,但我无法在href=""标记的<a>属性中打印任何内容。我试过了:

Attempt 1:
<a href="@routes.JsonSamples.bookdetails((entry \ "id").as[String])">
...Compilation error: unclosed multi-line string literal

Attempt 2:
<a href="@(routes.JsonSamples.bookdetails((entry \ "id").as[String]))">
...Compilation error: in XML literal: whitespace expected

Attempt 3:
<a href="@{routes.JsonSamples.bookdetails((entry \ "id").as[String])}">
...Compilation error: in XML literal: whitespace expected

Attempt 4:
<a href="{routes.JsonSamples.bookdetails((entry \ "id").as[String])}">
...Compilation error: in XML literal: whitespace expected

有时您只需使用@符号即可显示数据。

有时您必须使用@ 使用{}包裹代码(即@{…})。

有时甚至不允许使用@,您只能使用{}

有时这些方法都不起作用。

很明显,如果代码在另一个代码块内,它必须与事实有关。但是(在大多数情况下)无论如何都会将所有内容都包装到@main {…}中并且它可以正常工作,但是包装的代码块越多,看起来就越难以显示值。

因此,主要的具体问题是:如何在上面显示的链接/路线上显示href="#"

更普遍的问题是:如何将代码与HTML混合有明确的可理解方式吗?

JSON文件:https://github.com/Manc/play-samples/blob/json/data/books.json

控制器:https://github.com/Manc/play-samples/blob/json/app/controllers/JsonSamples.scala

视图:https://github.com/Manc/play-samples/blob/json/app/views/jsonsamples/read.scala.html

我还注意到,在视图中的任何地方都不允许@* *@个注释块。

我来自PHP,它总是很清楚什么是PHP代码,什么不是。甚至,例如Laravel(一个PHP框架)模板引擎 Blade 使用类似的方法,您可以在其中混合使用@符号或{{ … }}来打印变量/函数的值/ method或{{{ … }}}执行相同但HTML安全转义。

1 个答案:

答案 0 :(得分:4)

首先快速修复

@for(entry <- (section \ "entries").as[List[JsObject]]) {
  <tr>
    <td>
      <a href="@routes.JsonSamples.bookdetails((entry \ "id").as[String])">
        @{(entry \ "title").as[String]}
      </a>
    </td>
    <td>
      <p>@{(entry \ "description").as[String]}</p>
      <p>Order link: @{(entry \ "link").as[String]}</p>
    </td>
  </tr>
}

您的代码存在的问题是使用@{...}。问题是,该块内的所有内容都被视为scala代码。这就是@**@注释不起作用的原因,它们不是有效的scala语法。 Scala有xml文字,允许在里面使用html标签。

这意味着我们需要摆脱循环内部的scala语法。问题是,我找不到这样做的方法并保持地图语法。由于section \ "entries"中的@(section \ "entries").as[List[JsObject]].map { entry =>周围有括号,因此模板引擎仅将该部分视为scala代码。要解决此问题,您可以使用for的替代语法。

因此,对于简单表达式使用@。使用@{...}表示不是那么简单的表达式,但请记住,块内的所有内容都是scala代码(因此不再需要@)。您无法使用@的地方位于scala代码中。

当简单表达式不够而且你需要做map或者其他东西时,这可能会导致问题,但总有defining助手,你不应该做太复杂的事情无论如何都是模板。