Reputation: 6177
Given a list of foobars (each of which contain a name, and a slug used to create a URL hyperlink), what would be the idiomatic way in a Play 2.0 template to render each item in this list to a link (or some other HTML), and then intercalate the list with some character, such a comma?
For example, if there were three foobars, the final output might look like this:
<a href="/quux/foobar1">Foobar1</a>, <a href="/quux/foobar2">Foobar2</a>, <a href="/quux/foobar3">Foobar3</a>
My first impulse was to try:
@foobars.map{foobar =>
<a href="@routes.Foobars.quux(foobar.slug)">@foobar.name</a>
}.mkString(", ")
but this outputs escaped HTML, which is not what I want.
This seems like it would be a common use case; is there an idiomatic way it can be accomplished?
Upvotes: 4
Views: 773
Reputation: 2505
I was able to solve this for Play 2.3 as well, using combination of other answers:
@foobars.map{foobar =>
<a href="@routes.Foobar.quux(foobar.slug)">@foobar.name</a>
}.reduceLeftOption((e1: Html, e2: Html) => Html(e1 + "," + e2))
Upvotes: 0
Reputation: 3383
Based on Debilski's idea I built a working version. But sadly I get an extra space when appending. Not a big deal, but it is there:
<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>
Upvotes: 1
Reputation: 81
You should be able to use the Html helper to stop escaping...
@{Html(foobars.map{foobar =>
<a href="@routes.Foobars.quux(foobar.slug)">@foobar.name</a>
}.mkString(", "))}
Upvotes: 2
Reputation: 67888
I haven’t used Play but I think that mkString
seems to be the problem. It transforms your painstakingly built NodeSeq
into a String
which gets then passed to Play’s HTML output routines where it gets transformed to a Text
(escaping included).
To avoid this:
@foobars.map{foobar =>
<a href="@routes.Foobars.quux(foobar.slug)">@foobar.name</a>
}.reduceLeft((e1: xml.NodeSeq, e2: xml.NodeSeq) => e1 ++ xml.Text(", ") ++ e2)
(This will fail for an empty sequence of foobar. You’d have to look into reduceLeftOption
then.)
There might be a dedicated function for this in the Play API, though.
Upvotes: 1