Matching a list with HTML and intercalating the result in a Play 2.0 template

Given the list of foobars (each of which contains the name and pool used to create the URL hyperlink), what would be the idiomatic way in the Play 2.0 template for each element in this list to refer to a link (or some other HTML), and then rearrange a list with some kind of 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 leads to HTML escaping, which I don't want.

This seems to be a common use case; Is there an idiomatic way this can be achieved?

+4
source share
4 answers

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(", "))} 
+2
source

I have not used Play, but I think mkString seems to be the problem. It converts your painstakingly constructed NodeSeq to String , which is then passed to the Pays HTML output routines, where it is converted to Text (exception thrown).

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 fails for an empty foobar sequence. Then you need to look at reduceLeftOption .)

However, the Play API may have a dedicated function.

+1
source

Based on the idea of โ€‹โ€‹Debilsky, I built a working version. But unfortunately, I get extra space when adding. It doesnโ€™t matter, but it is:

 <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> 
+1
source

I was able to solve this for Play 2.3, using a 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)) 
0
source

Source: https://habr.com/ru/post/1412306/


All Articles