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?
Oh grazie!^_^Nel momento in cui scrissi la domanda non c'erano validatori extra per Parsley 2.0, li controllerò il prima possibile. – goffreder