diff --git a/build.sbt b/build.sbt index 2b6ef8be2..c72048467 100644 --- a/build.sbt +++ b/build.sbt @@ -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", diff --git a/scalate/src/main/scala/org/scalatra/scalate/ScalatraFormsHelpers.scala b/scalate/src/main/scala/org/scalatra/scalate/ScalatraFormsHelpers.scala new file mode 100644 index 000000000..c810962d2 --- /dev/null +++ b/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"""""") + } + + /** + * Render a password field. + */ + def password(name: String, attributes: (String, String)*): Unit = { + unescape(s"""""") + } + + /** + * Render a textarea. + */ + def textarea(name: String, attributes: (String, String)*): Unit = { + unescape(s"""""") + } + + /** + * Render a checkbox. + */ + def checkbox(name: String, value: String, attributes: (String, String)*): Unit = { + val checked = if (params(name).contains(value)) "checked" else "" + unescape(s"""""") + } + + /** + * Render a radio button. + */ + def radio(name: String, value: String, attributes: (String, String)*): Unit = { + val checked = if (param(name) == value) "checked" else "" + unescape(s"""""") + } + + /** + * 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"""") + 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("&", "&").replace("<", "<").replace(">", ">").replace("\"", """) + } + + 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(" ") + } +} diff --git a/scalate/src/main/scala/org/scalatra/scalate/ScalatraRenderContext.scala b/scalate/src/main/scala/org/scalatra/scalate/ScalatraRenderContext.scala index d08c29436..6cda85fa6 100644 --- a/scalate/src/main/scala/org/scalatra/scalate/ScalatraRenderContext.scala +++ b/scalate/src/main/scala/org/scalatra/scalate/ScalatraRenderContext.scala @@ -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)