Uno dei problemi più noiosi da gestire nello sviluppo di una web-application è il caso in cui non si conosce a priori il numero di elementi che saranno postati attraverso una form. Questo capita quando c’è di mezzo una tabella con dati provenienti da database e bisogna eseguire su questi piu operazioni con un solo submit della form stessa.
Un esempio classico è il carrello. Un carrello contiene da 1 a infiniti elementi e per ognuno di essi è definita una quantità. Questo viene mostrato all’utente sottoforma di una tabella e l’utente può modificare più quantità contemporaneamente ed eseguire, quando tutto è a posto, un singolo “aggiorna totali” o “check-out”.
Per gestire questo problema senza l’ausilio di un framework bisognerebbe decidere una strategia di naming dei campi della form che permetta ovviamente la non-sovrapposizione dei dati inseriti dall’utente e garantisca la possibilità di ricollegare le modifiche richieste agli oggetti su cui bisogna effettivamente effettuarle. Fisicamente il name del tag <input /> dovrebbe avere una parte fissa e una parte dinamica che varia di riga in riga. Quando questi dati vengono poi postati vanno riorganizzati in una struttura sensata (una lista, un vettore ….) e trattati dalla business-logic. E’ piu semplice dirlo che farlo.
Se invece utiliziamo Struts qualche aiuto c’è.
Abbiamo fondamentalmente 4 oggetti in gioco. Una pagina JSP che si occupa di visualizzare il contenuto di una lista, e contiene una form. Un oggetto di tipo actionForm che recepisce tutti i dati provenienti dalla from, sia indicizzati sottoforma di una lista che non. Un oggetto che costituisce il modello della singola riga e una Action che costituisce il punto di accesso alla logica applicativa ( a.k.a. fa quello che l’utente si aspetta che faccia)
La JSP è necessario che sia già fatta utilizzando gli strumenti del framework, e non scrivendo codice java.
Per esempio per generare la visualizzazione di una lista di elementi di un carrello faremo quacola di simile a:
<logic:present name="carrello" scope="request"> <logic:iterate id="elemento" name="carrello"> <tr> <td class="small"> <html:hidden name="elemento" property="id" indexed="true"/> <bean:write name="elemento" property=" descr" /> </td> <td> <html:text name="elemento" property="qt" indexed="true" ></html:text></td> </tr> </logic:iterate> </logic:present>
Gli elementi indicizzati in questo caso sono 2, un tag nascosto contenente un identificativo e un TextField contente la quantità. Il framework in fase di rendering si preoccupera di generare un nome differente per ogni volta che viene iterata questa porzione di codice. Il primo giro i due elementi della form si chiameranno elemento[0].id e elemento[0].qt, la seconda volta elemento[1].id e elemento[1].qt e cosi via.
Ora serve predisporre i due oggetti che “tasportano” i dati dalla visualizzazione al controllore. Il primo di cui ci occupiamo è quello che descrive una “riga” e che verrà istanziato tante volte quante sono le righe stesse. E sarà, pressapoco, simile a quanto segue :
package form; public class Line { private string id; private string qt; public Line() { ; } [… getter e setter standard per entrambe per le proprietà…] }
Basta costruire un oggetto con proprietà adatte a contenere i dati della singola riga di tabella e relativi metodo per accedervi … semplice no ? Ora l’oggetto che descrive la form è un pochetto più complesso. Se la form contiene dati non indicizzati vanno inserite le relative proprietà come di consueto. Mentre per le righe, non sapendo a priori quante sono, ci affidiamo ad una lista ( LinkedList, ArrayList … o quello che vi sembra più opportuno )
Package form; [... include vari...] Public class formCarrello extends ActionForm { Private List elemento; Public List getElemento() { // Non verrà mai usato dal framework, ma puo tornare utile Return this.elemento; } Public void populateElemento(List elemento) { //Inutilizzato dal FW, di comodo This.elemento = element } Public void setElemento(Line myLine) { elemento.add(myLine); } Public Line getElemento(int index) { If(this.elemento == null) { This.elemento = new ArrayList(); } While (index >= elemento.size) { This.elemento.add(new Line()); } Return (Line)this.elemento.get(index); } }
La proprietà deve avere lo stesso nome utilizzato in visualizzazione. Il metodo che serve al framework è solo il getter con parametro.
Tutto questo perchè ? Perche il framework non crea autonomamente una lista e la assegna tramite una singola chiamata ad un setter non potendo immaginare che tipo di lista volete usare, o costituita da che tipo di oggetti. Questa è una vostra scelta e tocca quindi a voi l’implementazione. Il framework chiama prima il getter con l’indice della riga, riceve un oggetto di cui non sà nulla, chiama i setter in base al nome delle proprieta nella form e stop. In effeti l’unico metodo strettamente necessario è l’ultimo, che crea la lista se non c’è e crea l’oggetto di indice “index” se non esiste. Gli atri verranno usati nella logica applicativa per-fare-ciò-che-ci-si-aspetta-che-faccia.
Il file di configurazione si configura in modo usuale. Il form-bean è ovviamente “formCarrello” , la Action è quella che andrete a definire per gestire questa complicatissima logica applicativa.
Lascia un commento