Lavorando con le applicazioni web, prima o poi ci si trova a dover compilare un form e, di conseguenza, a validare i dati che vengono inseriti. Alloy UI mette a disposizione dello sviluppatore strumenti molto interessanti per gestire la validazione dei dati direttamente in pagina.
Modello dei dati
Prima di affrontare nel vivo l’aspetto della validazione dei dati con Alloy UI è necessario fare una piccola premessa sul modello dei dati. Liferay, da un certo punto di vista, lavora al contrario: nel senso che lo sviluppatore deve definire il proprio datamodel in un file XML che successivamente viene elaborato dal Service Builder e dal quale vengono in automatico generate le tabelle del database.
Senza entrare nel merito del perche’ avvenga ciò, ricordiamo che a partire da questo file XML (il famoso service.xml) Liferay genera tutte le classi Java che rappresentano il datamodel e che lo sviluppatore deve utilizzare come DTO.
Questo passaggio è fondamentale perche’ il framework di validazione, come vedremo, ha un legame molto stretto con le classi del datamodel.
Prepariamo il form HTML
Iniziamo quindi l’analisi della validazione dei dati dall’elemento principale: il form HTML che deve contenere i dati. Ricordiamo subito che tipicamente ad un form viene associato un actionURL in quanto al submit viene di solito eseguita della logica di business. Ecco quindi la classica definizione:
Questo fa sì che, al submit del form, il portale cerchi e invochi sulla portlet uno dei seguenti metodi:
public void saveTimesheet(ActionRequest actionRequest, ActionResponse actionResponse) throws Exception @ProcessAction(name="submit") public void submit(ActionRequest actionRequest, ActionResponse actionResponse) throws IOException, PortletException;
A questo punto dobbiamo ricordarci del datamodel; già perche’ dobbiamo pensare al form HTML come ad una rappresentazione del nostro modello. Quindi dobbiamo chiederci quale sia la classe Java che contiene i dati che devono essere inseriti nel form.
La classe Persona
Supponiamo di avere generato una classe Persona con i seguenti campi:
- personaId, long, chiave primaria;
- nome, String;
- cognome, String,
- nascita, Date, data di nascita;
- email, String;
- maschio, boolean, sesso della persona;
- altezza, int, altezza della persona.
La cosa che dobbiamo ricordarci è che dobbiamo portare sempre in pagina un oggetto di tipo Persona, valorizzato oppure no; ciò significa che all’interno del metodo doView della portlet dovremo scrivere uno snippet simile al seguente:
/* * Recupero di un'istanza dell'oggetto dalla request. * L'oggetto sarà sempre a null, a meno che non sia stato * valorizzato nel metodo processAction a seguito di un submit. */ Persona persona = (Persona) renderRequest.getAttribute("persona"); if (persona == null) { /* Creo l'istanza vuota da portare in pagina */ persona = new PersonaImpl(); /* Eventualmente preconfiguro i campi dell'oggetto */ // persona.setNome(""); // persona.setCognome(""); // ... } /* Metto l'oggetto nella request */ renderRequest.setAttribute("persona", persona);
A questo punto, una volta arrivati in pagina, è possibile recuperare l’istanza dell’oggetto:
Usare le taglib
Ma perche’ tutta questa fatica? Perche’ finalmente è possibile definire il form HTML, mediante le taglib di Alloy, e associarlo al nostro datamodel:
Come si potrà facilmente capire, l’elemento centrale è la taglib che definisce nel contesto della pagina il bean di riferimento del datamodel.
Questo fa sì che le singole taglib possano ricavare, attraverso l’attributo name, il nome del campo del modello e di conseguenza renderizzare a video l’elemento più corretto, unitamente alla label descrittiva:
- campo di testo, per i campi stringa;
- textarea;
- radio button, per il campo booleano maschio;
- calendario, per il campo nascita;
- …
I campi di tipo Date richiedono un minimo di spiegazione in più perche’ sono quelli che traggono il maggior beneficio dall’utilizzo delle taglib di Alloy; infatti vengono automaticamente renderizzati (ed eventualmente prevalorizzati) con 3 caselle combinate (giorno, mese e anno) e un pulsante per selezionare il giorno direttamente dal calendario, modificando alcune impostazioni è possibile visualizzare anche l’orario. La cosa però veramente potente delle taglib è che il render è internazionalizzato: vale a dire che la data viene visualizzata in conformità alla lingua dell’utente. Ad esempio, per l’utente italiano i campi saranno nell’ordine giorno-mese-anno con l’orario nel formato 24 ore; mentre per l’utente americano i campi saranno nell’ordine anno-mese-giorno con l’orario nel formato 12 ore (AM/PM).
Per visualizzare il testo corretto di ciascuna label, la taglib internamente recupera la traduzione che ha come chiave il valore dell’attributo name; chiaramente è possibile sovrascrivere questo comportamento utilizzando l’apposito attributo label.
Ovviamente, il form HTML presentato sopra è solo una forma minimale, perche’ le taglib di Alloy hanno molti attributi che possono essere utilizzati. Tuttavia questa forma è già sufficiente perche’ le taglib di Alloy, unendo HTML e CSS, sono in grado di renderizzare a video tutto il form in maniera corretta e gradevole; tipicamente i campi vengono tutti visualizzati uno sotto l’altro, ciascuno preceduto dalla propria label.
Validazione in pagina
Una volta definito il form, possiamo passare al primo livello di validazione, ossia quello da fare direttamente in pagina attraverso la taglib ; la taglib è piuttosto semplice e presenta solamente due attributi e un body opzionale:
<aui:validator name="name" errorMessage="error-message-key"> ruleValue (opzionale)
L’attributo name rappresenta il nome di una delle regole (o regex) predefinite oppure la stringa custom nel caso si voglia inserire una propria funzione custom di validazione; le regole predefinite sono numerose e molto utili, pertanto ne citiamo qualcuna:
- alphanum, regex, verifica se il contenuto del campo è alfanumerico;
- number, regex, verifica se il contenuto del campo è numerico;
- email, regex, verifica se il contenuto del campo è un indirizzo email formalmente valido;
- url, regex, verifica se il contenuto del campo è un’URL valido;
- equalTo, regola, verifica che il contenuto del campo sia uguale a un altro;
- max/min, regola, verifica il valore numerico massimo/minimo del testo inserito;
- maxLength/minLength, regola, verifica la lunghezza massima/minima del testo inserito;
- range, regola, verifica che il valore rientri nel range specificato;
- required, regola, verifica che il campo venga compilato.
Modifichiamo quindi il nostro form HTML andando ad introdurre tutti i validatori che possono servire:
3 3 function(value, node) { // value è il valore del campo // node è l'oggetto Node // deve restituire un booleano che // attesti la validazione o meno return true/false; } 100 250
Come accennato in precedenza questo è il primo livello di validazione che ci consente di specificare in pagina tutti i validatori da utilizzare.
Questa soluzione però ha un limite molto evidente: i validatori vanno specificati in ogni pagina e questo potrebbe essere dispendioso. Sarebbe sicuramente più comodo poter mettere a fattore comune le validazioni standard; vediamo come.
Model hints
All’inizio dell’articolo abbiamo parlato di datamodel e Service Builder, due argomenti ben noti a chi sviluppa su Liferay.
Ma “forse non tutti sanno che…” il Service Builder genera, tra i tanti, anche un file XML molto utile:
src/META-INF/portlet-model-hints.xml
Come dice il nome, si tratta di un file in cui definire tutti i suggerimenti di validazione da applicare ai singoli campi del nostro datamodel. Nel caso della nostra classe Persona il file avrebbe questo aspetto:
Sfruttando questo file è possibile associare a ciascun campo il proprio validatore, senza quindi doverlo specificare nelle pagine JSP; vediamo come:
3 true ...
Hint collection
Ma non finisce qui; è infatti possibile definire genericamente un set di suggerimenti (detta hint collection) a cui associare un nome univoco e da applicare poi a tutti i campi ove necessario.
Ad esempio, analizziamo un paio di collection predefinite di Liferay per capire meglio:
105 500 4000 true true true false ...
La prima collection definisce un set di regole chiamato TEXTAREA che potrà essere applicato ai campi testuali multiriga e come impostazioni vengono specificate la dimensione a video in pixel dell’elemento di testo (display-height e display-width) e la lunghezza massima di caratteri digitabili nell’elemento (max-length).
La seconda collection invece definisce un set di regole chiamato SEARCHABLE-DATE che verrà applicato ai campi di tipo Date da usare eventualmente per le ricerche; come impostazioni viene specificato che i campi di giorno, mese e anno possono non essere valorizzati e che l’orario non deve essere visibile.
Una volta definiti i propri set di regole, è possibile applicarli ai campi del datamodel in maniera molto semplice; ad esempio:
...
Gestire la data di nascita
Ad integrazione di quanto detto fin qui, vediamo un esempio piuttosto comune tratto direttamente dal blog D’vel: la data di nascita. Spesso infatti capita di dover visualizzare in pagina la data di nascita e questo normalmente richiede alcuni requisiti funzionali da tenere in considerazione:
- l’anno di nascita non può essere futuro;
- l’orario non è necessario.
Implementare questi requisiti con le taglib di Alloy è veramente molto semplice; è infatti sufficiente definire un opportuno set di regole, come segue:
90 false false
Cosa abbiamo fatto? Abbiamo semplicemente dichiarato una regola che stabilisce un intervallo di 90 anni a partire dall’anno corrente, senza poter usare gli anni futuri e senza mostrare l’orario; non ci resta che applicare la regola ai nostri campi ed abbiamo finito.
... ...
Conclusioni
In conclusione si è visto come sia semplice ma allo stesso tempo robusto gestire la validazione dei dati in pagina con Alloy UI, senza necessariamente mettere mano al codice; non possiamo quindi che sperare nell’introduzione di nuovi validatori.
La nostra serie su AlloyUI continua nei prossimi numeri, con ulteriori approfondimenti ed esempi.
Riferimenti
[1] Alloy UI
http://www.liferay.com/community/liferay-projects/alloy-ui/
[2] Alloy UI demo
http://www.liferay.com/community/liferay-projects/alloy-ui/demos
[3] Alloy UI API
http://alloyui.com/deploy/api/
[4] Alloy UI issue tracker
http://issues.liferay.com/browse/AUI
[5] Model Hints
[6] Gestire la data di nascita
http://blog.d-vel.com/web/blog/home/-/blogs/gestire-la-data-di-nascita-con-liferay