I write web applications in Scala using its XML-literal support. This provides me the advantage of a statically-typed language while rendering templates.
Sometimes objections are raised. I will not address the most common of these objections in any detail. However, I will say that if you read a book on MVC and believe you are “separating concerns”, then you have been misguided. I have touched on the thesis of functional programming before, which provides composition in its true sense. I recommend Why Functional Programming Matters by John Hughes to get started on obtaining a true understanding of so-called separating concerns. Moving on…
I will present a trivial example of rendering objects in XHTML. Suppose we are building a criminology database which currently has two people in it.
val persons = List(
Person("Fred Bloggs",
"111 That Street Knobville",
"12345678",
"Knobs Inc.",
Set(Stalking, SexualHarassment)),
Person("Anthony McCrary",
"31291 Tecla Drive Warren Michigan 48088",
"5869447833",
"l33t labs",
Set(Stalking, PhoneHarassment))
)
Then we wish to render these in an XHTML table — let’s ignore the objections to using tables for now.
def personsTable =
<table border="1">
<tr>
<th>Name</th>
<th>Address</th>
<th>Phone</th>
<th>Employer</th>
<th>Offences</th>
</tr>
{
persons map (p => <tr>{
<td>{ p.name }</td>
<td>{ p.address }</td>
<td>{ p.phone }</td>
<td>{ p.employer }</td>
<td>{ p.offences.mkString(", ") }</td>
}</tr>)
}
</table>
In a templating language we might use a loop and have limited library access without any checking. Unfortunately, your favourite HTML editor will not allow this method of development. There is a way to accommodate this. I will expand on it in the next post.
Here is a full compilable and executable source file:
case class Person(name: String, address: String, phone: String, employer: String, offences: Set[Offence])
sealed trait Offence
case object Stalking extends Offence
case object PhoneHarassment extends Offence
case object SexualHarassment extends Offence
object P {
val persons = List(
Person("Fred Bloggs",
"111 That Street Knobville",
"12345678",
"Knobs Inc.",
Set(Stalking, SexualHarassment)),
Person("Anthony McCrary",
"31291 Tecla Drive Warren Michigan 48088",
"5869447833",
"l33t labs",
Set(Stalking, PhoneHarassment))
)
def personsTable =
<table border="1">
<tr>
<th>Name</th>
<th>Address</th>
<th>Phone</th>
<th>Employer</th>
<th>Offences</th>
</tr>
{
persons map (p => <tr>{
<td>{ p.name }</td>
<td>{ p.address }</td>
<td>{ p.phone }</td>
<td>{ p.employer }</td>
<td>{ p.offences.mkString(", ") }</td>
}</tr>)
}
</table>
def main(args: Array[String]) {
println(personsTable)
}
}
Here is how the output renders:
| Name | Address | Phone | Employer | Offences |
|---|---|---|---|---|
| Fred Bloggs | 111 That Street Knobville | 12345678 | Knobs Inc. | Stalking, SexualHarassment |
| Anthony McCrary | 31291 Tecla Drive Warren Michigan 48088 | 5869447833 | l33t labs | Stalking, PhoneHarassment |
Please ask questions if you have any.
No objections here. I quite like it.
If you needed more interactivity then a good xml templating language doesn’t seem to be the most important factor. While XML could be used, JSON seems more appropriate for async calls.
I quite like how SmartGWT is looking for very interactive web apps.
http://www.smartclient.com/smartgwt/showcase/#grid_editing_cell
or perhaps using the SmartClient library directly
http://www.smartclient.com/#editByCell
I got a whole bunch of questions reguarding XML in Scala…
– How are namespaces used?
– What about DTD/Schema validation at development time?
– How are tag-libraries or macros created?
It goes and goes…
Nice to see Scala’s XML literals being used for templating! I gave a short talk at the Jazzon09 conference about using Scala within the Apache Sling web framework for doing type safe templating. See http://michid.wordpress.com/2009/06/26/scala-for-sling-jazzon-09/