I'm sure I'm missing the obvious but is there a way to create a collection of Html objects to pass to a Play template like @(title: String)(content: Seq(Html))
? I am trying to dynamically generate a group of tab pages where each Html object is the body of the tab.
Where my confusion lies is with how to create the Seq(Html) in the template.
Something like @main("Home") Seq({...},{...})
doesn't work and using @(title: String)(contentTab1: Html)(contentTab2: Html)
and @main("Home") {...}, {...}
defeats the purpose.
Something like:
Tab content(tab.scala.html
):
@(content: Html, tab: models.Tab, isActive: String)
<section class="mdl-layout__tab-panel @isActive" id="[email protected]">
<div class="page-content">@content</div>
</section>
Main template (main.scala.html
):
@main(title: String, tabs: List[models.Tab])(contentSeq: Seq[Html])
Page template:
@(tabs: List[models.Tab])
@main("title", tabs) {
<!-- tab1 content -->
} {
<!-- tab2 content -->
}
*ignore bad design of matching Seq[Html]
and List[models.Tab]
sizes
Compiled Play templates are basically just functions (or rather, objects with an apply(...)
method), so assuming you have a single (partial) template for the tab content you can just apply it to the tab data using map
, e.g:
Main template (main.scala.html
):
@main(title: String, tabs: Seq[Html])(content: Html)
<h1>@title</h1>
<ul class="tabs">
@tabs.map { tab =>
@tab
}
</ul>
@content
Tab content (tab.scala.html
):
@(name: String)
<li>@name</li>
So each page template would look something like:
@(title: String)
@main(title, Seq("tab1", "tab2", "tab3").map(name => views.html.tab(name)) {
<p>This is some content</p>
}
... or if you have more than one tab partial:
@main(title, Seq(views.html.tab1("tab1"), views.html.tab2("tab2"))) {
<p>This is some content</p>
}
Yet another way is to render each tab as a reusable block and pass them to the master template as a sequence:
@(title: String)
@tab1 = {
<li>Content for tab 1</li>
}
@tab2 = {
<li>Content for tab 2</li>
}
@main(title, Seq(tab1, tab2)) {
<p>This is some content</p>
}