Playframework: use Scalatags instead of Twirl

I would prefer to use the former over the latter, but not sure how to include Scalatags in the playframework.

This is my simple layout:

object Test { import scalatags.Text.all._ def build = { html( head( title := "Test" ), body( h1("This is a Triumph"), div( "Test" ) ) ) } } 

Here is how I am trying to do this:

 Ok(views.Test.build.render) 

The problem is that I get it as a regular string, and not as HTML.

Now, of course, one solution would be to simply add.

 Ok(views.Test.build.render).as("text/html") 

but is this really the only way? (Without creating the helper method that is)

+7
scala playframework scalatags
source share
1 answer

I assume you want to call Ok(views.Test.build) . The game does not know ScalaTags, so we will have to write something here.

Play uses a slightly implicit mechanism to generate HTTP responses. When you call Ok(...) , you actually call apply by the value of play.api.mvc.Results . Let's take a look at his signature:

 def apply[C](content: C)(implicit writeable: Writeable[C]): Result 

So we see that we need an implicit Writeable[scalatags.Text.all.Tag] :

 implicit def writeableOfTag(implicit codec: Codec): Writeable[Tag] = { Writeable(tag => codec.encode("<!DOCTYPE html>\n" + tag.render)) } 

Remember to include a doctype declaration. ScalaTags does not give you one.

This call to Writeable.apply itself requires another implicit definition of the content type. Here is his signature:

 def apply[A](transform: A => ByteString)(implicit ct: ContentTypeOf[A]): Writeable[A] 

So write the implicit ContentTypeOf[Tag] :

 implicit def contentTypeOfTag(implicit codec: Codec): ContentTypeOf[Tag] = { ContentTypeOf[Tag](Some(ContentTypes.HTML)) } 

This avoids the need to explicitly write as("text/html") and include an encoding (kindly provided by an implicit codec), resulting in a Content-Type header text/html; charset=utf-8 text/html; charset=utf-8 .

Putting it all together:

 import play.api.http.{ ContentTypeOf, ContentTypes, Writeable } import play.api.mvc.Results.Ok import scalatags.Text.all._ def build: Tag = { html( head( title := "Test" ), body( h1("This is a Triumph"), div( "Test" ) ) ) } implicit def contentTypeOfTag(implicit codec: Codec): ContentTypeOf[Tag] = { ContentTypeOf[Tag](Some(ContentTypes.HTML)) } implicit def writeableOfTag(implicit codec: Codec): Writeable[Tag] = { Writeable(tag => codec.encode("<!DOCTYPE html>\n" + tag.render)) } def foo = Action { implicit request => Ok(build) } 

You probably want to hide these implications somewhere in a convenient place, and then import them into your controller (s).

+9
source share

All Articles