View Templates
Scalate
Skinny framework basically follows Skinny Micro’s Scalate Support, but Skinny has an additional convention.
Template paths should be of the form {path}.{format}.{extension}
. Expected {format} are html
, json
, js
and xml
.
For instance, assuming your controller code looks like this:
class MembersController extends SkinnyController {
def index = {
set("members", Member.findAll())
render("/members/index")
}
}
The render method expects that src/main/webapp/WEB-INF/views/members/index.html.ssp
exists.
<%@val s: skinny.Skinny %>
<%@val members: Seq[model.Member] %>
<h3>Members</h3>
<hr/>
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th></th>
</tr>
</thead>
<tbody>
#for (member <- members)
<tr>
<td>${member.id}</td>
<td>${member.name}</td>
<td>
<!-- Using reverse routes is recommended -->
<a href="${s.url(MembersController.editUrl, "id" -> member.id)}"
class="btn btn-info">Edit</a>
<a data-method="delete" data-confirm="Are you sure?"
href="${s.url(MembersController.deleteUrl, "id" -> member.id)}"
class="btn btn-danger">Delete</a>
<!-- Primitive HTML coding is also possible -->
<a href="/members/${member.id}/edit" class="btn btn-info">Edit</a>
<a data-method="delete" data-confirm="Are you sure?"
href="/members/${member.id}" class="btn btn-danger">Delete</a>
</td>
</tr>
#end
</tbody>
</table>
Scalate supports many template engines.
- Mustache
- Scaml
- Jade
- SSP
http://scalate.github.io/scalate/
For example, if you want to write your template using Jade, save it as src/main/webapp/WEB-INF/views/members/index.html.jade
instead.
Scaffolding will be the easiest way to understand. Try it now!
./skinny g scaffold members member name:String activated:Boolean birthday:Option[LocalDate]
./skinny g scaffold:scaml companies company name:String
./skinny g scaffold:jade countries country name:String code:Int
./skinny db:migrate
./skinny run
./skinny run
evaluates Scalate templates on runtime and that makes your Skinny app developmeent so interactive.
When you edit a template file a little, just reload the page without waiting for Scala code compilation and Jetty restart due to Scala compilation detection.
However, in some cases, error messages may be difficult to investigate the reason or page response may be slow when it’s the first request to the page. If you’d like to use Scalate precompilation in development, just append -precompile
option as follows.
./skinny run -precompile
For instance, if you use Jade instead, the above code will look like this. Scaml is very similar.
-@val s: skinny.Skinny
-@val members: Seq[model.Member]
h3 Members
hr
table(class="table table-bordered")
thead
tr
th ID
th Name
th
tbody
-for (member <- members)
tr
td #{member.id}
td #{member.name}
td
a(href={s.url(MembersController.editUrl, "id" -> member.id)} class="btn btn-info") Edit
a(data-method="delete" data-confirm="Are you sure?" href={s.url(MembersController.deleteUrl, "id" -> member.id)} class="btn btn-danger") Delete
a(href={s"/members/${member.id}/edit"} class="btn btn-info") Edit
a(data-method="delete" data-confirm="Are you sure?" href={s"/members/${member.id}"} class="btn btn-danger") Delete
Layouts
To avoid unnecessary repetition and ease maintenance, you may want to extract common parts of your Scalate templates into ‘layouts’. See the Scalate documentation for more details.
If you do not specify which layout to use, Skinny will look for a ‘default’ layout at WEB-INF/layouts/default.{extension}
. (Note that the layout does not necessarily have to use the same template language as the template.)
If you want to use a custom layout for a particular action, use the layout
method in your controller:
class MyController extends SkinnyController {
def foo = {
layout("custom.ssp")
render("foo") // Renders WEB-INF/views/foo.html.ssp using layout WEB-INF/layouts/custom.ssp
}
}
FreeMarker
If you prefer the FreeMarker template engine, you can easily use it with Skinny framework.
First, add skinny-freemarker
to your library-dependencies.
libraryDependencies += "org.skinny-framework" %% "skinny-freemarker" % skinnyVersion
Mixin FreeMarkerTemplateEngineFeature
to your controllers.
import skinny.controller.feature.FreeMarkerTemplateEngineFeature
class MembersController extends SkinnyController
with FreeMarkerTemplateEngineFeature {
def index = {
set("members", Member.findAll())
render("/members/index")
}
}
And then, use src/main/webapp/WEB-INF/views/members/index.html.ftl
instead.
Thymeleaf
If you prefer the Thymeleaf template engine, you can easily use it with Skinny framework.
First, add skinny-thymeleaf
to your library-dependencies.
libraryDependencies += "org.skinny-framework" %% "skinny-thymeleaf" % skinnyVersion
Mixin ThymeleafTemplateEngineFeature
to your controllers.
import skinny.controller.feature.ThymeleafTemplateEngineFeature
class MembersController extends SkinnyController
with ThymeleafTemplateEngineFeature {
def index = {
set("members", Member.findAll())
render("/members/index")
}
}
And then, use src/main/webapp/WEB-INF/views/members/index.html
instead.
Velocity
If you prefer the Velocity template engine, you can easily use it with Skinny framework.
First, add skinny-velocity
to your library-dependencies.
libraryDependencies += "org.skinny-framework" %% "skinny-velocity" % skinnyVersion
Mixin VelocityTemplateEngineFeature
to your controllers.
import skinny.controller.feature.VelocityTemplateEngineFeature
class MembersController extends SkinnyController
with VelocityTemplateEngineFeature {
def index = {
set("members", Member.findAll())
render("/members/index")
}
}
And then, use src/main/webapp/WEB-INF/views/members/index.html.vm
instead.