Grails conditional nullable validation or custom validator with nullable option

你说的曾经没有我的故事 提交于 2019-12-04 06:42:31

I can't tell with the code you've pasted but if your problem is that the default validation doesn't allow province to be null, have you tried explicitly allowing province to be null? You are allowed multiple validators for each field. So back in your original code, just specify the nullable validator as well:

province nullable: true, validator:  {val, obj -> 
  if (obj != null && obj.country in obj.requiresRegionCountries() && !obj.province) 
    return [province.required]
}

EDIT: In the custom validator, might also want to guard against the obj being null in the if condition.

EDIT2: Demo project showing the above validation working on grails 2.0.4

class Place {
String country
Province province

  static constraints = {
    province (nullable: true, validator: {val, obj ->
        if (obj.country == 'Canada' && !val) return ['province.required']
    })
  }
}

Controller...

 class MainController {
  def index() {
    def place = new Place(country: 'Canada')
    if (!place.validate()) {
        render "need province<br/>" + place.errors
    } else {
        render "cool"
    }

So the idea is that I have a dummy controller where I can invoke the index action which is hardcoded to create a Place domain instance similar to your example. Notice I only defined the country string so I can key my logic on that for the custom validation. I didn't define the province when creating the Place instance so it should be null. Under that scenario, the response page will print the following...

Output snippet ...

need province 
grails.validation.ValidationErrors: 1 .... does not pass custom validation]

If I remove the nullable: true constraint from Place, then the error is the null value as expected...

Output snippet ...

need province
grails.validation.ValidationErrors: 1 .... cannot be null]
Eduard

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)
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!