我有一张代表目录的 map ,它包含 Chapter
键和List[Section]
值(value)观。现在我正在尝试在我的模板中循环遍历它,如下所示:
<dl>
@table_of_contents.foreach((e) => {
<dt>
@e._1.title
</dt>
for(section <- e._2){
<dd>
@section.title
</dd>
}
})
</dl>
我目前在 <dl>
中没有得到任何输出然而。
我添加了println(table_of_contents)
模板顶部的声明,以确保 map 确实有数据并打印:
{models.Chapter@1=BeanList size[4] hasMoreRows[false] list[models.Section@1, models.Section@2, models.Section@3, models.Section@4], models.Chapter@2=BeanList size[0] hasMoreRows[false] list[]}
也许我需要使用命令式风格?
更新:
仍在研究这个...得到了这个变体来编译,但没有输出。
<dl>
@table_of_contents.foreach{case(a, b) => {
<dt>
@a.title
</dt>
@displaySections(b)
}}
</dl>
...
@displaySections(sections: List[Section]) = {
@for(a_section <- sections) {
<dd>@a_section.title</li>
}
}
最佳答案
tl;博士
到目前为止给出的答案(评论中的 @wbarksdale 、 @PlexQ 和 @Daniel C. Sobral )足以解决此处描述的问题。
但是他们缺少关于为什么使用 foreach
的初始代码不起作用的真正解释。
它无法工作,因为 foreach
返回 Unit
。
游戏理念
让我快速说明/记忆一下模板的工作原理。
Play Framework 2 默认提供的 Scala 模板系统确实是基于 FP 概念构建的,因此它使用了大量不可变结构等等。
此外,这样的 Scala 模板(比如说 myTemplate.scala.html
)将被编译成一个常规的 Scala 对象
,它有一个 apply
方法调用。后一个函数使我们能够将对象作为带有一些参数(在模板第一行中声明的参数)的函数来调用。
这个对象
也依赖于像BaseScalaTemplate
这样的结构。它是用输出格式化程序(Html)构建的。该格式化程序将能够接受一些内容(例如 String
、Unit
、Seq[Int]
、Map[A,B]
, ...) 并将其渲染为 HTML 代码。
格式化将在使用BaseScalaTemplate
的_display_
方法时进行,该方法返回格式化输出的实例。此显示方法将在对象的 apply
方法主体中的 .scala.html
文件的编译代码中调用。
所以正文可以这样结束:
def apply/*1.2*/(testMap:scala.collection.immutable.Map[String, Int]):play.api.templates.Html =
_display_ {
Seq[Any](
_display_(
Seq[Any](
/*3.2*/testMap/*3.9*/.map/*3.13*/ { e =>
_display_(Seq[Any](_display_(Seq[Any](/*5.3*/e))))
}
)
)
)
}
看到了吗? _display_
调用不会改变任何内容,但它们的组合方式使得 apply 本身将返回格式化代码 (Html
) 的实例!
这给了我们线索......
是啊等等……现在为什么?
在给出了有关 Play 内部结构的闪电之后,我们现在可以解决真正的问题:为什么问题帖子中提供的意识形态 Scala 代码不起作用......阅读,根本不输出任何内容。
这非常简单,当在 Map
上使用 foreach
时,您确实循环项目并适应 将它们转换为 Html。但模板系统无法使用这些计算,因为它们包含在 foreach 循环中。也就是说,当序列中的每个项目都需要副作用时,必须使用 foreach
...并在完成后返回 Unit
。
因为,模板系统将尝试_display_
在给定的Map
上foreach
的结果,它只会渲染/格式化 Unit
,因此是一个空的String
!
总而言之,只需使用 map
即可返回一个新序列,其中包含适应项目,即 Html
实例。
嗯,那么 for
呢?
是的,你是对的...根据所说的,为什么建议使用 for
循环的答案有效,因为在不产生值的情况下,一个 for
相当于 foreach
!? (引入 yield
将以类似于 map
的行为结束)
答案就在代码中...模板编译器会将 yield
关键字添加到 for
的主体中 - 请查看 here 。 :-D
瞧,它也有效,因为 for
主体中生成的内容将在完成后附加到返回的序列中。
关于templates - 玩! Framework 2.0 - 循环遍历 scala 模板中的 map ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9946552/