给定一个foobars列表(每个都包含一个名称,以及一个用于创建URL超链接的slug),Play 2.0模板中的惯用方法是将此列表中的每个项目呈现给链接(或者其他一些HTML),然后将列表插入一些字符,如逗号?
例如,如果有三个foobars,最终输出可能如下所示:
<a href="/quux/foobar1">Foobar1</a>, <a href="/quux/foobar2">Foobar2</a>, <a href="/quux/foobar3">Foobar3</a>
我的第一个冲动是尝试:
@foobars.map{foobar =>
<a href="@routes.Foobars.quux(foobar.slug)">@foobar.name</a>
}.mkString(", ")
但是这会输出转义的HTML,这不是我想要的。
这似乎是一个常见的用例;是否有一种惯用的方式可以实现?
答案 0 :(得分:2)
您应该可以使用Html帮助程序来停止转义...
@{Html(foobars.map{foobar =>
<a href="@routes.Foobars.quux(foobar.slug)">@foobar.name</a>
}.mkString(", "))}
答案 1 :(得分:1)
我没有使用Play,但我认为mkString
似乎是问题所在。它将您精心构建的NodeSeq
转换为String
,然后将其传递给Play的HTML输出例程,并将其转换为Text
(包括转义)。
为避免这种情况:
@foobars.map{foobar =>
<a href="@routes.Foobars.quux(foobar.slug)">@foobar.name</a>
}.reduceLeft((e1: xml.NodeSeq, e2: xml.NodeSeq) => e1 ++ xml.Text(", ") ++ e2)
(对于一个空的foobar序列,这将失败。你必须先查看reduceLeftOption
。)
但Play API中可能有一个专门的功能。
答案 2 :(得分:1)
根据Debilski的想法,我建立了一个工作版本。但遗憾的是,在追加时我得到了额外的空间。没什么大不了的,但它就在那里:
<td>
@r.countries.map{ country =>
<a href="@routes.Items.editCountry(country.toString, "main")">
@Country.findOneByID(country).map(_.name)
</a>
}.reduceLeftOption((e1: Html, e2: Html) => e1 += Html(",") += e2)
</td>
答案 3 :(得分:0)
我也可以使用其他答案的组合来解决Play 2.3的问题:
@foobars.map{foobar =>
<a href="@routes.Foobar.quux(foobar.slug)">@foobar.name</a>
}.reduceLeftOption((e1: Html, e2: Html) => Html(e1 + "," + e2))