Why did Playframework 2 use a custom Scala Template Engine instead of scalas build in xml mode?

756 views Asked by At

Play 2.0 uses a custom scala based template engine that allows to use a subset of scala inside html code.

Why was this design decision made instead of using scalas build-in xml mode?

The play template engine has some disadvantages like

  • only a subset of scala is supported, for example it seems not to be possible to define functions inside of functions
  • no editor support in eclipse

On the other hand, I understand that the play scala template engine supports non-well-formed html which wouldn't be possible with scalas xml mode, but I guess it should always be possible to write the templates in a well formed way. I'm just a beginner in play and scala and would simply like to understand the context.

2

There are 2 answers

4
i.am.michiel On

I think it has several answers :

  1. It is a template. Templates are not supposed to hold complex logic. All logic manipulation has to be done in the controller/model.

  2. Templates can have about any format you want : email, CSV, SQL and so on. Restricting a template to valid XML is really limiting the possibilities of the framework.

  3. Everything is compilable. Even routes, assets, template inheritance, etc. In order for those mecanisms to work with the rest of the framework, some choice probably had to be made. But no one will be able to answer you better than the creators of the framework.

0
Sebastian Baltes On

One reason may be the clumsy handling of attributes in xml in scala. There are two problems:

  1. Attributes like "selected" which must either be present or not
  2. Adding a list of attributes dynamically like the htmlArgs of the input helper templates

An example in plain scala shows the difficulties:

def addAttributes(element: Elem, attributes: Map[Symbol, _ <: Any]): Elem = {
    var el = element
    for ((key, value) <- attributes) el = el % Attribute(None, key.name, Text(value.toString), Null)
    el
  }

  def multiselect[T](field: play.api.data.Field,
    options: Seq[T],
    optionValue: T => String,
    optionText: T => String,
    args: (Symbol, Any)*)(implicit handler: FieldConstructor, lang: play.api.i18n.Lang) = {
    val values = { field.indexes.map { v => field("[" + v + "]").value } }
    input(field, args: _*) {
      (id, name, value, htmlArgs) =>
        Html(
          addAttributes(
            <select id={ id } name={ name } multiple="multiple">
              {
                options.map { v =>
                  val z: Option[String] = if (values contains v) Some("selected") else None
                  <option value={ optionValue(v) } selected={ z map Text }>{ optionText(v) }</option>
                }
              }
            </select>,
            htmlArgs).toString)
    }
  }