2012-05-29 26 views
5

Tengo un formulario para crear un lugar. Dependiendo del país, se requiere o no el campo de provincia (estado, región).Validación validada condicional de Grails o validador personalizado con opción de nulidad

Cuando no es obligatorio, quiero ser una cadena nula, no vacía. Tengo código que hace que todos los campos vacíos, nulo:

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() 

Ahora, en el dominio del lugar, tengo un validador en la provincia:

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

Con esta regla, siempre sale "provincia no puede ser nulo "incluso si se requiere o no.

Creo que esto se debe a que el validador que admite nulos esta predeterminado a falso.

Si estoy añadiendo anulable: verdad, entonces incluso si es necesario provincia, el validador propio se omite y se puede guardar con la provincia de vacío (creo que es porque se crea una instancia con nula)

Ahora , necesito de alguna manera mi validador de encargo y también la capacidad para especificar el anulable en mi validador, algo como esto:

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

¿Cómo puedo lograr esto en Grails 2.0.3?

Respuesta

4

No puedo decir con el código que ha pegado, pero si su problema es que la validación por defecto no permite que la provincia sea nula, ¿ha intentado explícitamente permitir que provincia sea nula? Se le permiten múltiples validadores para cada campo. Así que de vuelta en su código original, basta con especificar el validador anulable así:

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

EDIT: En el validador personalizado, también puede ser que desee evitar el obj siendo nula en el caso de condiciones.

Edit2: proyecto de demostración que muestra la validación anterior trabajando en griales 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'] 
    }) 
    } 
} 

controlador ...

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

Así que la idea es que tengo un controlador ficticia donde puedo invocar la acción de índice que está codificada para crear una instancia de dominio de lugar similar a su ejemplo. Tenga en cuenta que solo definí la cadena del país, así que puedo escribir mi lógica para la validación personalizada. No definí la provincia al crear la instancia Place por lo que debería ser nula. Bajo ese escenario, la página de respuesta se imprimirá el siguiente ...

fragmento de salida ...

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

Si quito la anulable: verdadera limitación de la plaza, entonces el error es el valor nulo como se esperaba ...

salida fragmento ...

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

Gracias por su respuesta, pero hay un problema. Si configuro para ser nulo y place.province es nulo, entonces la validación personalizada se omite por completo. Quiero ser nullable para algunos países pero no para los demás. – Eduard

+0

Para ser claros: si no pongo el valor de nulos como verdadero y el archivo es nulo, el error "No puede ser nulo" se inicia y mi validador personalizado no se ejecuta. Si agrego nullable: true y el valor es nulo, la validación pasará, mi validador personalizado no se ejecutará. Quiero ser nulo para algunos países y no nulo para otros. Esto es algo que no puedo hacer con el comportamiento actual. – Eduard

+0

Quizás sea un error de Grails 2.0.3. Estoy ejecutando 2.0.4 y me funciona con un simple proyecto de demostración que creé que pegaré en mi respuesta anterior para que pueda comparar – Tri

12

Después de mucha investigación y retroalimentación descubrí 2 soluciones que están trabajando. Uno está en el controlador.No añada ninguna validación en el modelo y añadirlos de forma dinámica desde el controlador:

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 
    } 

}

La otra solución es la propuesta por Tri en este hilo, pero poner el validador personalizado antes de la restricción anulable (otra cosa el validador personalizado no se llamará para valores nulos):

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