Skip to content

Commit

Permalink
Merge pull request #766 from takezoe/forms-helpers-for-scalate
Browse files Browse the repository at this point in the history
Add helpers to render forms in Scalate templates
  • Loading branch information
takezoe committed Nov 25, 2017
2 parents 2948df0 + c0473c4 commit b22c2fd
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 2 deletions.
2 changes: 1 addition & 1 deletion build.sbt
Expand Up @@ -132,7 +132,7 @@ lazy val scalatraScalate = Project(
libraryDependencies += scalate,
description := "Scalate integration with Scalatra"
)
) dependsOn(scalatraCore % "compile;test->test;provided->provided")
) dependsOn(scalatraCore % "compile;test->test;provided->provided")

lazy val scalatraJson = Project(
id = "scalatra-json",
Expand Down
101 changes: 101 additions & 0 deletions scalate/src/main/scala/org/scalatra/scalate/ScalatraFormsHelpers.scala
@@ -0,0 +1,101 @@
package org.scalatra.scalate

import org.fusesource.scalate.servlet.ServletRenderContext
import org.scalatra.MultiParams

/**
* Supplies helper methods to render forms in Scalate templates.
*/
trait ScalatraFormsHelpers { self: ServletRenderContext =>

private val RequestAttributeParamsKey = "org.scalatra.forms.params"
private val RequestAttributeErrorsKey = "org.scalatra.forms.errors"

/**
* Render a text field.
*/
def text(name: String, attributes: (String, String)*): Unit = {
unescape(s"""<input type="text" name="${escape(name)}" value="${escape(param(name))}" ${attrs(attributes: _*)}>""")
}

/**
* Render a password field.
*/
def password(name: String, attributes: (String, String)*): Unit = {
unescape(s"""<input type="password" name="${escape(name)}" ${attrs(attributes: _*)}>""")
}

/**
* Render a textarea.
*/
def textarea(name: String, attributes: (String, String)*): Unit = {
unescape(s"""<textarea name="${escape(name)}" ${attrs(attributes: _*)}>${escape(param(name))}</textarea>""")
}

/**
* Render a checkbox.
*/
def checkbox(name: String, value: String, attributes: (String, String)*): Unit = {
val checked = if (params(name).contains(value)) "checked" else ""
unescape(s"""<input type="checkbox" name="${escape(name)}" value="${escape(value)}" $checked ${attrs(attributes: _*)}>""")
}

/**
* Render a radio button.
*/
def radio(name: String, value: String, attributes: (String, String)*): Unit = {
val checked = if (param(name) == value) "checked" else ""
unescape(s"""<input type="radio" name="${escape(name)}" value="${escape(value)}" $checked ${attrs(attributes: _*)}>""")
}

/**
* Render a select box.
*/
def select(name: String, values: Seq[(String, String)], multiple: Boolean, attributes: (String, String)*): Unit = {
val sb = new StringBuilder()
sb.append(s"""<select name="${escape(name)}" ${if (multiple) "multiple" else ""}>""")
values.foreach {
case (value, label) =>
val selected = if (params(name).contains(value)) "selected" else ""
sb.append(s"""<option value="${escape(value)}" $selected>${escape(label)}</option>""")
}
sb.append("</select>")
unescape(sb.toString)
}

/**
* Retrieve an error message of the specified field.
*/
def error(name: String): Option[String] = {
Option(request.getAttribute(RequestAttributeErrorsKey)).flatMap { errors =>
errors.asInstanceOf[Seq[(String, String)]].find(_._1 == name).map(_._2)
}
}

/**
* Retrieve all error messages of the specified field.
*/
def errors(name: String): Seq[String] = {
Option(request.getAttribute(RequestAttributeErrorsKey)).map { errors =>
errors.asInstanceOf[Seq[(String, String)]].collect { case error if error._1 == name => error._2 }
}.getOrElse(Nil)
}

private def escape(value: String): String = {
value.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;").replace("\"", "&quot;")
}

private def params(name: String): Seq[String] = {
Option(request.getAttribute(RequestAttributeParamsKey)).flatMap { params =>
params.asInstanceOf[MultiParams].get(name)
}.getOrElse(Nil)
}

private def param(name: String): String = {
params(name).headOption.getOrElse("")
}

private def attrs(attrs: (String, String)*): String = {
attrs.map { case (name, value) => s"""${escape(name)}="${escape(value)}"""" }.mkString(" ")
}
}
Expand Up @@ -17,7 +17,7 @@ class ScalatraRenderContext(
engine: TemplateEngine,
out: PrintWriter,
req: HttpServletRequest,
res: HttpServletResponse) extends ServletRenderContext(engine, out, req, res, kernel.servletContext) {
res: HttpServletResponse) extends ServletRenderContext(engine, out, req, res, kernel.servletContext) with ScalatraFormsHelpers {

def flash: scala.collection.Map[String, Any] = kernel match {
case flashMapSupport: FlashMapSupport => flashMapSupport.flash(request)
Expand Down

0 comments on commit b22c2fd

Please sign in to comment.