A library to validate and map request parameters for Scalatra.
Notice: This project is maintained no longer because it has been merged into Scalatra! See the Scalatra documentation to know details.
At first, add the following dependency into your build.sbt to use scalatra-forms.
libraryDependencies += "io.github.gitbucket" %% "scalatra-forms" % "1.1.0"
Next, add ValidationJavaScriptProvider
to Bootstrap of your Scalatra application.
import io.github.gitbucket.scalatra.forms._
class ScalatraBootstrap extends LifeCycle {
override def init(context: ServletContext) {
...
context.mount(new ValidationJavaScriptProvider, "/assets/js/*")
...
}
}
scalatra-forms is now ready.
Define a form mapping. It's a similar to Play2, but scalatra-forms is more flexible.
import io.github.gitbucket.scalatra.forms._
case class RegisterForm(name: String, description: String)
val form = mapping(
"name" -> text(required, maxlength(40)),
"description" -> text()
)(RegisterForm.apply)
Next, create a servlet (or filter) which extends ScalatraServlet (or ScalatraFilter).
It also mixed in FormSupport
or ClientSideValidationFormSupport
.
The object which is mapped request parameters is passed as an argument of action.
class RegisterServlet extends ScalatraServlet with ClientSideValidationFormSupport {
post("/register", form) { form: RegisterForm =>
...
}
}
In the HTML, you have to do two things below.
<script>
to import jQuery which is required by validation.js<script>
to import validation.js which helps client side validation provided by ValidationJavaScriptProvider
validation="true"
to your <form>
scalatra-forms registers a submit event listener to validate form contents.
This listener posts all the form contents to FORM_ACTION/validate
.
This action is registered by scalatra-forms automatically to validate form contents.
It returns validation results as JSON.
In the client side, scalatra-forms puts error messages into span#error-FIELD_NAME
.
<script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script src="/assets/js/validation.js"></script>
...
<form method="POST" action="/register" validation="true">
Name: <input type="name" type="text">
<span class="error" id="error-name"></span>
<br/>
Description: <input type="description" type="text">
<span class="error" id="error-description"></span>
<br/>
<input type="submit" value="Register"/>
</form>
You can create custom Constraint
.
def identifier: Constraint = new Constraint(){
override def validate(name: String, value: String): Option[String] =
if(!value.matches("^[a-zA-Z0-9\-_]+$")){
Some(s"${name} contains invalid character.")
} else {
None
}
}
val form = mapping(
"name" -> text(required, identifier),
"description" -> text()
)(RegisterForm.apply)
You can also create multi field validator by overriding validate(String, String, Map[String, String])
.
It's possible to look up other field value via params
.
Other way to create multi field validator is calling verifying
for mapping.
You can give the function yo validate the mapped case class. This function takes the mapped value and returns
Seq[(String, String)]
which contains errors or Nil
.
val form = mapping(
"reason" -> number(required),
"description" -> optional(text)
)(ReasonForm.apply).verifying { value =>
if(value.reason == 4 && value.descripsion){
Seq("description" -> "If reason is 'Other' then description is required.")
} else {
Nil
}
}
For the Ajax action, use ajaxGet
or ajaxPost
instead of get
or post
.
Actions which defined by ajaxGet
or ajaxPost
return validation result as JSON response.
class RegisterServlet extends ScalatraServlet with ClientSideValidationFormSupport {
ajaxPost("/register", form) { form: RegisterForm =>
...
}
}
In the client side, you can render error messages using displayErrors()
.
$('#register').click(function(e){
$.ajax($(this).attr('action'), {
type: 'POST',
data: {
name : $('#name').val(),
description: $('#description').val()
}
})
.done(function(data){
$('#result').text('Registered!');
})
.fail(function(data, status){
displayErrors($.parseJSON(data.responseText));
});
});
io.github.gitbucket
.put()
, delete()
, ajaxPut()
and ajaxDelete()
to ClientSidevalidationFormSupport
.long
value type.%s
) is available in custom messages as same as default messages.dummy()
bug.long
value type.list
bug for un-nested properties.dummy
value type.verifying()
for MappingValueType
and remove MappingConstraint
instead of it.length
constraint.MappingConstraint
to validate converted object by MappingValueType
.list()
mapping for SingleValueType
.ValidationJavaScriptProvider
adds Content-Type header for validation.js.oneOf()
constraint which checks whether the value is one of specified strings.number()
and double()
from ResourceBundle.double()
and date()
mapping.ValidationJavaScriptProvoider
.list()
mapping for List property.validate(String, String, Map[String, String])
to Constraint
.
It makes possible to access other parameter in single field validation.verify()
to MappingValueType
which validates the mapped instance.