I have a form to create a place. Depending of the country, the province (state, region) field is required or not.
When is not required, I want to be null, not empty string. I have code that makes all empty form fields, null:
def newparams = [:]
place = new Place()
params.each() { k, v ->
if (v instanceof String && place.hasProperty(k)) {
if (!v.trim().length()) {
newparams[k] = null
} else {
newparams[k] = v
}
}
}
place = new Place(newparams)
place.validate()
Now, in the place domain, I have a validator on the province:
province validator: {val, obj -> if (obj.country in obj.requiresRegionCountries() && !obj.province) return [province.required]}
With this rule, I always get "province can't be null" even if it is required or not.
I think this is because the nullable validator that is set default to false.
If I am adding nullable: true, then even if province is required, the custom validator is skipped and it is possible to save with empty province (I think that is because it gets instantiated with null)
Now, I need somehow my custom validator and also ability to specify the nullable in my validator, something like this:
province validator: {val, obj ->
if (obj.country in obj.requiresRegionCountries() && !obj.province) {
nullable: false
return [province.required] }
else {
nullable: true
}
}
How can I achieve this in Grails 2.0.3?
After lots of research and feedback I found out 2 solutions that are working. One is in controller. Do not add any validation in model and add them dynamically from controller:
class PlacesController {
def create() {
def place = new Place(params.address)
if (place.country in placesThatRequiresProvinceArray) {
place.constrains.province.nullable = false
} else {
place.constrains.province.nullable = true
}
}
The other solution is the one proposed by Tri in this thread, but put the custom validator before the nullable constraint (else the custom validator will not be called for null values):
static constraints = {
province (validator: {val, obj ->
if (obj.country == 'Canada' && !val)
return ['province.required']
}, nullable: true)
}