I recently had to validate a form in my Grails application using jQuery. jQuery has an excellent mechanism to validate a form with certain validation rules. It allows you to prevent form submission if the user input doesn’t pass the validation attached to the form.

Below a simple example HTML snippet to validate a postal code field:

<script type="text/javascript">
$(function (){
	$("#form").validate({
		rules: {
			'address.postalCode': {
				required: true
			},
		},
		messages: {
			'address.postalCode': {
				required: "Please enter a postal code."
			}
		}
	});
});
</script>
<g:form method="post" action="register" name="form">
	<input type="text" name="address.postalCode" id="postalCode" />
	<input type="submit" value="Proceed" />
</g:form>

As you can see: a simple ‘required’ rule is specified for field with name address.postalCode and errormessage to go with it. Notice that special field names e.g. with a dot requires a notation with quotes around it.

Now, let’s say we need to validate the postal code on the server side for validity and still need to have the form validation performed by jQuery – and not inside the controller and returing some kind of error- or flash message. Use the remote rule!

As the documentation states:

The serverside resource is called via $.ajax (XMLHttpRequest) and gets a key/value pair, corresponding to the name of the validated element and its value as a GET parameter. The response is evaluated as JSON and must be true for valid elements, and can be any false, undefined or null for invalid elements, using the default message; or a string, eg. “That name is already taken, try peter123 instead” to display as the error message.

We create a controller which does such a thing: check the submitted postal code, verify it against some kind of backend service or database table and return the expected JSON return values.

E.g. let’s expand our form HTML with the following:

<script type="text/javascript">
	$(function (){
		$("#form").validate({
			rules: {
				'address.postalCode': {
					required: true,
					remote: {
						url: "${createLink(controller:'postalCode', action:'validate')}",
						type: "post",
						data: {
							postalCode: function() {
								return $("#postalCode").val();
						  }
						}
					  }
				},
			},
			messages: {
				'address.postalCode': {
					required: "Please enter a postal code.",
					remote: "Please enter a valid postal code."
				}
			}
		});
	});
</script>
<g:form method="post" action="register" name="form">
	<input type="text" name="address.postalCode" id="postalCode" />
	<input type="submit" value="Proceed" />
</g:form>

As you can see, the remote rule specifies a resource which is one of our controllers and a specified action. As data for our Grails action we pass along the current value of the post code field – using the ‘data’ block with a function.

Our PostalCodeController may have the following validate action:

class PostalCodeController {

	def postalCodeService
	
	def validate = {		
		String pc = params.postalCode
		
		String result = "false"
		if (postalCodeService.checkPostalCode(pc)) {
			result = "true"
		}
				
		response.setContentType("text/json;charset=UTF-8");
		render result
	}
}

Voila! We validate our data (which we simply read from the params) en return a string “true” if it’s valid else “false”.

Upon form submission our action is called and the outcome is used by jQuery to validate the user data! I couldn’t get my response rendered via the usual Grails JSON builder which seems to have trouble with single values (such as “true” or “false”), but set the content type directly. You might want to send additional caching headers along with the JSON response to prevent browser caching, but that’s all left as an excercise for the reader.