[ ].blue

Angular Filters for Play

May 8, 2014

I was looking at the Angular filters a bit. As a pattern I think they are conceptually simpler than our current notion of presenters in Scala. For consistency of development on a Play/Angular project, I was wondering if it would be good to have one concept of how to deal with presentation for both JS and Scala. I prototyped a filter system for Twirl that is functionally equivalent to Angular filters in Scala and the syntax is super close too (unfortunately Twirl has already reserved | and || so I used |||, but that operator could be whatever).

It's pretty common to use implicit classes to apply the presenter pattern in Play...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// presenters.scala
object presenters {
  implicit class StringPresenter(s: String) {
    def reverse = Html(s.reverse)
  }

  implicit DateTimePresenter(dt: DateTime){
    def format(f: String) = DateTimeFormat.forPattern(f).print(dt)
  }
}


// index.scala.html
@import presenters._

@main {
  <h1>@message.reverse</h1>
  <h3>@event.start.format("YYYY-MM-dd")</h3>
}

Filters as a concept however are really just a function. You could make a | method that implicitly used such functions...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// filters.scala
object filters {

  // --- Setup (once for all filters) ---

  type HtmlFilter[A] = (A) => Html

  implicit class Filtererer[A](a: A) {
    def |||(filter: HtmlFilter[A]): Html = filter(a)
  }

  // --- Filter Examples ---

  val reverse = new HtmlFilter[String] {
    def apply(s: String) = Html(s.reverse)
  }

  def format(f: String) = new HtmlFilter[DDateTime] {
    def apply(date: DateTime) = Html(DateTimeFormatter.forPattern(f).print(date))
  }
}


// index.scala.html
@import filters._

@main {
  <h1>@{ message ||| reverse }</h1>
  <span>@{ event.start ||| format("YYYY-MM-dd") }</span>
}

The limitation here compared to Angular filters is that they cannot be chained. ...or at least I haven't yet figured that part out.

gist