Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala Play template vararg HtmlContent

I have a generic template in play 2.6, that I want to pass in a variable amount of HtmlContents. I've defined the template like this (including the implicit parameter I have in case that changes anything):

@(foo: String)(content: Html*)(implicit bar: Bar)

On the template side, this works fine-- I can dissect content with for and render it as I want. However, I haven't been able to figure out a clean way to invoke the variable arguments from the underlying template.

e.g, I have a view named "Baz":

@(something: String)(implicit bar: Bar)

In it, I try to invoke the template with multiple Html arguments. I've tried the following:

@template("fooString"){{123},{abc}}
and
@template("fooString")({123}, {abc})
and
@template("fooString"){{123}, {abc}})

And various other permutations, but inside of an enclosing bracket it seems to interpret everything literally as a single parameter in the HtmlContent vararg.

However, this ended up working as I intended, passing in multiple HtmlContents:

@template("fooString")(Html("123"), Html("abc"))

So that works, and I can use a triple-quoted interpolated string for a large Html block-- but it seems like there should be a cleaner way to do this, and the string interpolation is dangerous as it doesn't do html escaping.

Is there a way to do this using the { enclosed syntax? I'd like to understand more what is actually happening on an underlying level, and how play parses and generates HtmlContent in brackets.

like image 839
Nathan Avatar asked Nov 25 '16 18:11

Nathan


1 Answers

So consider you have below template

// main.scala.html
@(title: String)(contents: Html*)

There are different ways you can call this template

Option #1

This is what you already posted in the question

@main("This is a title")(Html("abc"), Html("123"))

Options #2

@html1 = {
    Hello
}
@html2 = {
    <div>Tarun</div>
}

@main("This is a title")(html1, html2)

Option #3

@main("This is a title")(Html(<div>Tarun
</div>.toString), Html(<div>
Lalwani
</div>.toString))

Options #4

This is not exactly same option, but needs change in Template signature itself

@(title: String)(contents: List[String])  

And then calling it like below

@main("This is a title")(List(
  """<div>
     Tarun
    </div>
  """, """Hello"""))

Option #5

This requires code files and was already answered on another SO thread

Paul Draper's answer on Why doesn't this pass multiple HTML parameters to template

like image 183
Tarun Lalwani Avatar answered Oct 20 '22 00:10

Tarun Lalwani