2014-04-03 4 views
5

Desidero aggiungere un paio di controlli per i miei moduli la cui condizione è correlata ai valori di altri campi (ad esempio, ho un campo intervallo e il campo from deve essere inferiore al campo to e viceversa). Non ho trovato nulla di simile negli attuali Validator, quindi ho provato ad aggiungerli io stesso.Aggiungi validatore Parsley.js con campo di riferimento

Così, ho aggiunto queste due funzioni per Assert.prototype:

GreaterThanReference: function (reference) { 
    this.__class__ = 'GreaterThanReference'; 
    if ('undefined' === typeof reference) 
     throw new Error('GreaterThanReference must be instanciated with a value or a function'); 
    this.reference = reference; 
    this.validate = function (value) { 
     var reference = 'function' === typeof this.reference ? this.reference(value) : this.reference; 
     if ('' === value || isNaN(Number(value))) 
      throw new Violation(this, value, { value: Validator.errorCode.must_be_a_number }); 
     if (this.reference.value >= value) 
      throw new Violation(this, value); 
     return true; 
    }; 
    return this; 
} 

e

LessThanReference: function (reference) { 
    this.__class__ = 'LessThanReference'; 
    if ('undefined' === typeof reference) 
     throw new Error('LessThanReference must be instanciated with a value or a function'); 
    this.reference = reference; 
    this.validate = function (value) { 
     var reference = 'function' === typeof this.reference ? this.reference(value) : this.reference; 
     if ('' === value || isNaN(Number(value))) 
      throw new Violation(this, value, { value: Validator.errorCode.must_be_a_number }); 
     if (this.reference.value <= value) 
      throw new Violation(this, value); 
     return true; 
    }; 
    return this; 
} 

e questi altri due per ParsleyValidator.prototype.validators:

greaterthan: function (value) { 
    return $.extend(new Validator.Assert().GreaterThanReference(value), { 
     priority: 256, 
     requirementsTransformer: function() { 
     return { name : $(value).attr('alt'), value : +$(value).val() }; 
    }}); 
} 

e

lessthan: function (value) { 
    return $.extend(new Validator.Assert().LessThanReference(value), { 
     priority: 256, 
     requirementsTransformer: function() { 
     return { name : $(value).attr('alt'), value : +$(value).val() }; 
    }}); 
} 

Quindi ho voluto aggiungere il controllo revesed sul campo di riferimento, in modo che se cambio solo il valore del campo di riferimento posso ancora convalidare il modulo (nell'esempio di intervallo, se cambio valore, dovrei convalidare a campo. E se cambio valore, dovrei convalidare dal campo). A tal fine, ho modificato ParsleyField.prototype.addConstraint:

addConstraint: function (name, requirements, priority, isDomConstraint, isReference) { 
    name = name.toLowerCase(); 
    if ('function' === typeof window.ParsleyValidator.validators[name]) { 
     var constraint = new ConstraintFactory(this, name, requirements, priority, isDomConstraint); 
     // if constraint is a referenced one, I add the specular constraint on the referenced field 
     if((name == 'lessthan' || name == 'greaterthan') && isReference !== true) { 
      // I check if I already instanciated the referenced ParsleyField 
      var referencedField = $(requirements).data('Parsley') && $(requirements).data('Parsley').__class__ == 'ParsleyField' ? 
       $(requirements).data('Parsley') : 
       new ParsleyField($(requirements), this.parsleyInstance).init(); 
      referencedField.addConstraint(name == 'lessthan' ? 'greaterthan' : 'lessthan', '#' + this.$element.attr('id'), priority, isDomConstraint, true); 
     } 
     // if constraint already exist, delete it and push new version 
     if ('undefined' !== this.constraintsByName[constraint.name]) 
      this.removeConstraint(constraint.name); 
     this.constraints.push(constraint); 
     this.constraintsByName[constraint.name] = constraint; 
    } 
    return this; 
} 

Nel dettaglio, ho aggiunto l'argomento isReference per sapere se avevo già aggiunto il vincolo inversa sul campo di riferimento, al fine di evitare riferimenti circolari. Poi, in un modo abbastanza orribile, controllo se il vincolo che sto aggiungendo ha un riferimento e non è già un vincolo di riferimento (forse può essere migliorato aggiungendo una sorta di "tipo di vincolo" che potrebbe essere indiretto (o referenziato)) per i vincoli che controllano altri campi e diretti per coloro che controllano solo il valore). Se questa condizione è vera, devo aggiungere il nuovo vincolo allo ParsleyField già installato o, se non è stato instanciato, a un nuovo ParsleyField.

Questo metodo ha un problema. Se aggiungo un vincolo su un campo che fa riferimento a un campo che non è stato ancora instanciato, quando il normale flusso di Parsley arriva a quel campo lo sovrascrive, eliminando il vincolo che ho aggiunto prima.

Zero-domanda: è questo il modo giusto per ottenere ciò che voglio? Ammetto che non ho esplorato troppo le API di Parsley, ma mi piacerebbe usare meno funzioni possibili, visto che sto usando lo stesso server di controllo e dovrei essere in grado di fare le stesse cose su entrambi i lati.

Se la risposta zero è "sì", come posso risolvere il problema di sovrascrittura? Probabilmente dovrei essere in grado di eseguire l'istanza ParsleyField per verificare se è già stata instanciata, ma come?

risposta

1

Non so quale versione di parsley js si sta utilizzando e forse la mia risposta non è attuale ora. Tuttavia, ho affrontato lo stesso problema con la v.2.0.2. Fortunatamente, i documenti contengono un'esercitazione per scrivere validatori personalizzati. Potresti controllare i seguenti codici https://github.com/mvpotter/parsley-extra-validators. Se ti capisco correttamente, fanno esattamente ciò di cui hai bisogno. Qualsiasi feedback è apprezzato.

+0

Oh grazie!^_^Nel momento in cui scrissi la domanda non c'erano validatori extra per Parsley 2.0, li controllerò il prima possibile. – goffreder