There are a lot of different ways to accomplish this and probably 1 or more plugins to get you going. However, I'll show you how I generally deal with this. I have an object that looks like this...
class AjaxPostResponse {
boolean success
String message
String html
def domainObject
def errors = [:]
}
This is the object I render as JSON. So if there are validation errors, success becomes false and I add all the errors to the errors map. I do this in a service and that method looks like this:
def preparePostResponse(domainInstance) {
def g = grailsApplication.mainContext.getBean('org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib')
def postResponse = new AjaxPostResponse(domainObject: domainInstance)
if (domainInstance.hasErrors()) {
g.eachError(bean: domainInstance) {
postResponse.errors."${it.field}" = g.message(error: it)
}
postResponse.success = false
postResponse.message = "There was an error"
} else {
postResponse.success = true
postResponse.message = "Success"
}
return postResponse
}
So my controller looks something like
def save = {
def someObjInstance = new SomeObj(params)
someObjInstance.save(flush:true)
render myService.preparePostResponse(someObjInstance) as JSON
}
In my client side code I do something like this (using the jQuery form plugin, but this would work with a generic $.ajax / $.post / $.get method as well...
$(formElement).ajaxSubmit({
dataType: 'json',
success: function(jsonData) {
if (jsonData.success) {
// do good stuff
} else {
// bad stuff happened
showErrors(jsonData.errors);
}
}
});
And my showErrors function
function showErrors(errors, element) {
var errorList = $("
for (field in errors) {
errorList.append("
" + errors[field] + "")$('input[name=' + field + ']').addClass('error');
}
if (!element) {
$(".errors").html("").append(errorList).show(500);
} else {
$(element).html("").append(errorList).show(500);
}
}
Hope that helps.