Chiunque abbia mai utilizzato Liferay ed il Service Builder saprà che il portale mette a disposizione una potente infrastruttura di validazione dei campi lato client, sfruttando le taglib ed i componenti di Alloy.
E' infatti possibile utilizzare la taglib aui:validator
all'interno di una taglib aui:input
per specificare i validatori necessari: required
, url
, email
, ...
In aggiunta alle taglib è poi sempre possibile associare i validatori direttamente ai propri model attraverso il file portlet-model-hints.xml
generato dal Service Builder.A partire dalla versione 6.2 di Liferay è stato addirittura aggiunto l'attributo booleano required
alla taglibaui:input
pervelocizzare le cose.
Ma non sono qui adesso per parlare di validazione fine a se stessa ma per vedere come risolvere un problema abbastanza tipico: modificare l'obbligatorietà di un campo del form non in maniera statica, non a priori, ma a runtime in base ai valori assunti da altri campi durante la compilazione del form stesso.
Supponiamo quindi di avere definito un nostro form HTML, nel modo seguente classico:
<aui:form action="..." method="post" name="fm">
<aui:model-context bean="<%=mioBean %>" model="<%=MioBean.class %>" />
<aui:input name="mioBeanId" type="hidden" />
...
<aui:input name="myField" />
<aui:input name="myChoice" />
...
</aui:form>
Supponiamo che myField
sia un normale campo di testo facoltativo e che myChoice
sia invece un campo booleano (renderizzato quindi mediante checkbox) che a runtime discrimina se myField
deve essere obbligatorio oppure no: in pratica se myChoice
è selezionato allora myField
è obbligatorio, altrimenti no.
La prima cosa da fare, al caricamento della pagina, è quello di recuperare l'istanza Javascript del validatore associato al form:
<aui:script use="aui-base">
var <portlet:namespace/>formValidator;
Liferay.after('form:registered', function(event) {
if(event.formName == '<portlet:namespace/>fm') {
<portlet:namespace/>formValidator = event.form.formValidator;
}
});
</aui:script>
Come si può notare, quello che facciamo è intercettare l'evento di registrazione del form e memorizzare la reference del suo validatore in una variabile Javascript globale.
Dopodichè andiamo a gestire il click sulla nostra checkbox e di conseguenza anche l'obbligatorietà del campo myField
:
A.one('#<portlet:namespace />myChoiceCheckbox').on('click', function(event) {
var required = {
custom: false,
required: true
};
var notrequired = {
custom: false,
required: false
};
var formRules = <portlet:namespace/>formValidator.get('rules');
if(this.attr('checked') == true) { formRules['<portlet:namespace/>myField'] = required;
} else { formRules['<portlet:namespace/>myField'] = notrequired;
} });
In pratica quello che abbiamo fatto è stato definire inline due oggetti Javascript, required
e notrequired
, contenenti le impostazioni di obbligatorietà per il validatore del form; abbiamo creato due regole di validazione.
Dopodichè abbiamo recuperato l'insieme di tutte le regole di validazione associate al form attraverso l'oggetto Javascript formValidator
salvato in precedenza; questo insieme di regole non è altro che un array associativo in cui le chiavi sono i nomi dei campi del form.
Quindi,a seconda dello stato della checkbox, siamo andati ad applicare al campo MyField
una regola di validazione piuttosto che l'altra.
Occhio ai namespace e buona validazione!