JUG – Ancona Italy
Il framework Wicket
Andrea Del Bene
Jug Marche
[email protected]
Quali sono i “guai” della programmazione
web?
●
●
Le tecnologie su cui si basa il web si basano su paradigmi molto
diversi da quelli dei linguaggi di programmazione moderni (OOP in
primis).
Quando scegliamo le pagine web come GUI dobbiamo affrontare
due grossi limiti di questa tecnologia:
1) Le pagine (le viste del programma) sono dei semplici file di testo
da spedire al browser e non possono essere rappresentate ed usate
con gli strumenti dell'OOP
2) L'HTTP è stateless e dobbiamo fare i salti mortali per associare
uno stato alla navigazione di un utente sul nostro sito (di solito si
ricorre all'oggetto Session)
Wicket: pagine come oggetto
●
●
●
●
Wicket è un framework a componenti per lo sviluppo di soluzioni
web Java che propone una soluzione ad entrambi i problemi visti
A differenza di altre soluzioni (JSP, Struts, Spring MVC, ecc...) le
pagine web sono trattate come vere e proprie istanze di oggetto
(classe WebPage). Non dobbiamo più usare direttamente Request e
Response nel nostro codice e l'HTML è usato solo come template di
visualizzazione, non contiene nè taglib nè codice java.
Per fare ciò Wicket offre una gerarchia di classi molto simile a
quella proposta da Swing per realizzare le GUI di applicazioni
desktop
Come vedremo trattare le pagine come oggetti offre una soluzione
trasparente anche al problema della conservazione dello stato...
Wicket VS Swing
●
In Wicket ogni entità è un componente e la pagina (la classe
WebPage) contiene a sua volta istanze di componenti. WebPage ha
una funzione analoga alla classe JWindow (o JFrame) in Swing.
Dov'è finito l'HTML?
●
●
●
Se la pagina per lo sviluppatore è una classe Java come ottengo
l'HTML finale da inviare al Browser?
In Wicket la classe che rappresenta una pagina ha associata una pagina
HTML standard che funziona da template e che per default deve trovarsi
nella stessa cartella della classe ed avere lo stesso nome.
La classe Wicket può mappare i suoi componenti interni con i tag
presenti nella pagina HTML. Wicket offre un set di componenti con cui
mappare i vari elementi di una pagina HTML ( paragrafi <p>, form, div,
span, controlli di input, ecc...)
Il file web.xml
●
●
E' il momento di vedere un primo esempio di utilizzo di Wicket.
L'applicazione è una classica web application Java.
Il file web.xml deve dichiarare un elemento <filter> che istanzi una
sottoclasse di org.apache.wicket.protocol.http.WebApplication
(nel nostro caso la classe helloWorld.WicketApplication).
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>Wicket HelloWorld</display-name>
<filter>
<filter-name>WizardApplication</filter-name>
<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
<init-param>
<param-name>applicationClassName</param-name>
<param-value>helloWorld.WicketApplication</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>WizardApplication</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
La classe WicketApplication
●
●
La classe WicketApplication oltre ad essere il cardine dell'applicazione
Wicket, può sovrascrivere numerosi metodi della classe madre per
customizzare il comportamento della nostra applicazione.
Sovrascrivendo la funzione getHomePage si può specificare la pagina
home page della nostra applicazione (HomePage nel nostro caso).
package helloWorld;
import org.apache.wicket.Page;
import org.apache.wicket.protocol.http.WebApplication;
public class WicketApplication extends WebApplication {
@Override
public Class<? extends Page> getHomePage() {
return HomePage.class;
}
}
Pagina HelloWorld
●
La mappatura tra elementi HTML ed oggetti Java avviene aggiungendo
al tag l'attributo wicket:id=””
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1 wicket:id="label"></h1>
</body>
</html>
HelloWorld.html
●
Nella classe della pagina Wicket bisogna aggiungere un componente
con id uguale al wicket:id dell'elemento che si vuole mappare.
package helloWorld;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
public class HomePage extends WebPage {
public HomePage(){
super();
add(new Label("label", "Hello World"));
}
}
HelloWorld.java
WicketHelloWorld
●
Nel tag <h1> è stato inserito il
testo fornito come secondo
parametro nel costruttore del
componente Label.
...
<body>
<h1 wicket:id="label"></h1>
</body>
...
...
public HomePage(){
super();
add(new Label("label", "Hello World"));
}
...
Wicket come template per layout
●
●
●
L'esempio appena visto usa in maniera molto primitiva la capacità di
Wicket di manipolare il contenuto di una pagina HTML usando codice
Java.
Questa tecnica può essere usata per creare il layout grafico delle nostre
pagine usando un numero arbitrario di wicket:id nella nostra pagina ed
“inniettando” il codice HTML dei vari elementi che la compongono (ad
esempio: l'header, il menù di navigazione, il footer, il contenuto, ecc...)
Per fare ciò useremo l'oggetto Panel di Wicket che permette di
associare il contenuto di una pagina HTML ad un componente custom
di Wicket e poterlo aggiungere in una pagina del framework.
JUG – Ancona Italy
Il framework Wicket
Il layout con Wicket
●
Layout di una pagina web
●
Ora vogliamo espandere quanto visto nell'esempio precedente per
creare un classico layout per le pagine del nostro sito: un header, un
menù di sinistra, il contenuto centrale ed un footer conclusivo.
Header
Menù
Contenuto
Footer
L'approccio “classico”
●
Di solito per conferire alle pagine un layout stabilito ci si affida a
tecnologie di templating server side che caricano i vari “pezzi” della
pagina prima di spedirla al browser.
<%@include file="../common/Jug4TendaHeader.jsp"%>
<%@include file=
"gestioneOspiteMenu.htm
"%>
<div id="Content">
<%@include file="../common/Jug4TendaFooter.jsp"%>
Layout in Wicket
●
Con Wicket possiamo creare una pagina di template principale
(chiamiamola Jug4TendaTemplate) suddivisa nei componenti desiderati,
ognuno rappresentato da un <div> e con il proprio wicket:id
<div wicket:id=”headerPanel”></div>
<div
wicket:id=”menuPanel”>
</div>
<div wicket:id=”contentPanel”></div>
<div wicket:id=”footerPanel”></div>
I pannelli di Wicket
●
I pannelli sono lo strumento con cui possiamo creare componenti
personalizzati. Di fatto sono quasi come le pagine Wicket vere e proprio
in quanto anche i pannelli:
1) Sono associati a pagine HTML (pagine HTML complete!)
2) Possono a loro volta contenere altri componenti
●
●
A differenza delle pagine però i pannelli non possono essere
rendereizzati stand alone, ma devono essere inseriti in una pagina web
I pannelli sono gli strumenti ideali per suddividere la pagina nei sui
componenti grafici e per poterli riutilizzare in più pagine.
Il pannello header
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<wicket:panel>
<table width="100%" style="border: 0px none;">
<tbody><tr>
<td><img alt="Jug4Tenda"
src="wicketLayout_files/logo_jug4tenda.gif"></td>
<td><h1>Gestione Anagrafica Accoglienze</h1></td>
<td><img alt="Associazione di volontariato La Tenda d'Abramo"
src="wicketLayout_files/logo_latendadabramo.gif"></td>
</tr>
</tbody>
</table>
</wicket:panel>
</body>
</html>
●
HeaderPanel.html
La pagina HTML di un pannello deve avere il tag <wicket:panel>
all'interno del quale si trova l'HTML del pannello stesso.
La classe del pannello header
package helloWorld.layoutTenda;
import org.apache.wicket.markup.html.panel.Panel;
public class HeaderPanel extends Panel {
}
●
●
public HeaderPanel(String id) {
super(id);
}
HeaderPanel.java
La classe di un pannello Wicket deve avere almeno un costruttore che
richiama il costruttore padre passandogli il wicket id come parametro
stringa.
Anche i pannelli così come le pagine devono avere la classe e il file
HTML nella stessa cartella e devono avere lo stesso nome.
Il pannello footer
…
<wicket:panel>
<span class="piccolo">Powered by </span>
<a target="_blank" title="vai al sito dello JUG Ancona,..” href="http://www.jugancona.it/">
<img title="vai al sito dello JUG Ancona, ..." alt="JUG Ancona, Java User
Group di Ancona" src="wicketLayout_files/logo_jugancona.gif"></a>
<img title="JUG, Java User Group" alt="JUG, Java User Group"
src="wicketLayout_files/logo_jug.gif">
<a title="vai al sito del framework Spring " href="http://www.springframework.org/">
<img title="vai al sito del framework Spring" alt="Spring"
src="wicketLayout_files/logo_spring.gif"></a>
<a title="vai al sito di Mozilla Firefox..." href="http://www.mozilla.com/">
<img title="vai al sito di Mozilla Firefox..." alt="Firefox"
src="wicketLayout_files/logo_firefox.gif"></a>
</wicket:panel>
FooterPanel.html
…
package helloWorld.layoutTenda;
import org.apache.wicket.markup.html.panel.Panel;
public class FooterPanel extends Panel {
public FooterPanel(String id) {
super(id);
}
}
HeaderPanel.java
Il pannello menu
…
<div class="menuTitle">Menu principale</div>
<ul class="menuItems">
<li>
<img src="wicketLayout_files/home.gif">
<a class="Offmouse"
href="http://localhost:8080/jug4tenda/index.jsp"
id="newOspite" onmouseout="this.className='Offmouse'"
onmouseover="this.className='Onmouse'">Home</a></li>
</ul>
…
MenuPanel.html
package helloWorld.layoutTenda;
import org.apache.wicket.markup.html.panel.Panel;
public class MenuPanel extends Panel {
public MenuPanel(String id) {
super(id);
}
}
MenuPanel.java
La pagina template Jug4Wicket
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Jug4Tenda - Home page</title>
...
</head>
<body>
<div id="intestazione" wicket:id="headerPanel">intestazione</div>
<div id="pagina">
<div id="Menu" wicket:id="menuPanel">Menu</div>
<div id="Content" wicket:id="content">Content</div>
</div>
<div id="piedipagina" wicket:id="footerPanel">piedipagina</div>
</body>
</html>
package helloWorld.layoutTenda;
import org.apache.wicket.markup.html.WebPage;
public class JugTemplate extends WebPage {
public JugTemplate(){
add(new HeaderPanel("headerPanel"));
add(new MenuPanel("menuPanel"));
add(new FooterPanel("footerPanel"));
add(new Label("contentComponent", "content"));
}
}
Demo
JavaScript e CSS in Wicket
●
Come abbiamo visto il codice HTML dei pannelli Wicket deve essere
una pagina HTML a tutti gli effetti. Se nel file HTML di un pannello
vogliamo scrivere (o importare) codice JavaScript o CSS questo va
racchiuso nel tag <wicket:head>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;
charset=UTF-8">
<title>Insert title here</title>
<wicket:head>
<script>...</script>
<wicket:head>
...
</head>
<body>
...
<wicket:panel>
…
</wicket:panel>
...
JUG – Ancona Italy
Il framework Wicket
●
Pagine come oggetti
L'ereditarietà delle pagine Wicket
●
●
●
Ora che abbiamo una pagina di template con il layout del nostro sito,
possiamo sfruttare la normale ereditarietà degli oggetti per creare le
altre pagine.
In Wicket una sottoclasse di una pagina eredita dalla classe madre
anche l'html (oltre al codice ovviamente).
Questo vuol dire che la pagina figlia avrà di default lo stesso
identico aspetto della pagina padre.
package helloWorld.layoutTenda;
import org.apache.wicket.markup.html.basic.Label;
public class ChildPage extends JugTemplate {
public ChildPage(){
super();
addOrReplace(new Label("contentComponent",
"L'ereditariatà delle pagine Wicket e sia a livello di codice che di
html"));
}
}
Pagina “figlia” del template
addOrReplace(new Label("contentComponent",
"L'ereditariatà delle pagine Wicket e sia a livello di codice che di html")
●
Per la pagina figlia non è stato necessario creare un HTML .
Abbiamo solo “personalizzato” il contenuto.
JUG – Ancona Italy
Il framework Wicket
I link e lo stato delle pagine
●
I Wicket link
●
●
●
In Wicket i link sono molto più complessi del loro corrispondente
HTML e non hanno come scopo esclusivo quello di permettere ad
un utente di cambiare pagina.
Come gli altri componenti Wicket i link sono associabili ad un tag
della pagina HTML tramite l'attributo wicket:id. Si noti che un link
non deve per forza essere associato ad un tag anchor <a> ma può
essere associato a qualsiasi tag che supporti l'evento JavaScript
onClick (quasi tutti quindi).
Quando si aggiunge un componente Link ad una pagina occorre
sovrascrivere il metodo onClick() per specificare cosa deve essere
fatto quando l'utente preme il link:
add(new Link("link"){
@Override
public void onClick() {
}
});
I Wicket link 2
●
Se si vuole cambiare pagina facendo click su un Link Wicket
occorre esplicitarlo nel metodo onClick() usando la funzione
setResponsePage():
add(new Link("link"){
@Override
public void onClick() {
setResponsePage(JugTemplate.class);
}
});
●
Se un link non mi fa cambiare pagina Wicket restituisce nuovamente
la pagina corrente, senza però ricrearne un'istanza nuova,
conservando quindi lo stato della mia pagina fino a quando non la
abbandono. (Vi ricordate all'inizio il problema della conservazione
dello stato in HTTP?)
Il metodo onBeforeRender
●
●
●
Una pagina Wicket prima di essere trasmessa al browser effettua il
“pre-rendering” tramite l'evento before render che viene gestito nel
metodo onBeforeRender della classe WebPage.
Sovrascrivendo questo metodo possiamo ulteriormente modificare
l'aspetto e i componenti della pagina.
Abbiamo detto che se un Link Wicket non causa il cambiamento di
pagina viene restituita la pagina che lo contiene, senza creare una
nuova istanza.
Dopo il click il costruttore della pagina non verrà invocato mai il metodo
onBeforeRender si!
Pagina di esempio sui Link
●
●
Nella pagina di esempio abbiamo due timestamp, uno aggiunto nel
costruttore della pagina e l'altro nel metodo onBeforeRender().
Sono presenti anche due link che non fanno cambiare pagina.
Cliccando sui link si aggiorna solo il timestamp costruito su
onBeforeRender().
Codice della pagina di esempio
public class HomePage extends WebPage {
public HomePage(){
super();
add(new Label("label", "Hello World"));
add(new Label("timeStamp", "" + new Date()));
add(new Link("link"){
@Override
public void onClick() {
}
});
add(new Link("spanLink"){
@Override
public void onClick() {
}
});
....
@Override
protected void onBeforeRender() {
super.onBeforeRender();
addOrReplace(new Label("timeStampFresh", "" + new Date()));
}
}
JUG – Ancona Italy
Il framework Wicket
Il model dei componenti Wicket
●
Il ruolo del “model” in wicket 1
●
●
Tutti i componenti Wicket (input form, radio button, select ecc...)
memorizzano il valore ad essi associato in un'istanza dell'interfaccia
Imodel e dispongono di un metodo getModel() per accedervi
dall'esterno.
Attraverso il model Wicket offre uno strumento universale per
leggere i valori dei suoi componenti, come il contenuto di un campo
testuale o l'opzione scelta in una select.
public interface IModel
{
public Object getObject();
public void setObject(final Object object);
}
●
Anche se ogni componente Wicket può avere un model il suo
significato e la sua utilità diventano chiari quando si usano i
componenti di una form (campi testo, select, radio button...) che
memorizzano nel model il valore inserito in input dall'utente.
Il ruolo del “model” in wicket 2
●
Anche le Label hanno un model associato, ed è il secondo parametro
stringa del costruttore che viene visualizzato nella label:
add(new Label("label", "Hello World"));
...
●
●
Nel caso della Label il modello è creato implicitamente dal costruttore e
contiene la stringa passata come secondo argomento.
Le classi model possono contenere una generica istanza di object ma di
solito si ricorre al meccanismo dei generics per esplicitare il tipo di
istanza in essi contenuta
new Model<String>("label");
…
new Model<Persona>(new Persona(“Mario”, “Rossi”));
…
I Form di Wicket
●
Wicket fornisce una sua classe Form per mappare i form HTML in
oggetti Java ed associare a loro uno stato. Il mapping tra classe e tag
avviene sempre attraverso l'attributo wicket:id:
<form wicket:id="form">
...
●
●
Così come il form HTML anche il corrispondente Wicket si
caratterizza in base ai controlli di input che contiene (text field,
select, radio button, ecc...) e i pulsanti di submit (di solito uno solo)
che avviano la trasmissione dei dati al server.
Quindi anche il Form Wicket così come le pagine ed i pannelli è un
componente container, ossia può contenere altri componenti al suo
interno che devono però essere sottoclassi di FormComponent.
Il componente TextField
●
●
●
I campi testuali di una form vengono mappati in Wicket con la
classe TextField e di solito è utile associare un model String che
memorizza il valore inserito dall'utente.
Purtroppo i TextField di Wicket non hanno un costruttore che crea
in automatico il model secondo il tipo desiderato e dobbiamo farlo a
mano :-(:
Esempio di mapping di un campo testo di una form:
Classe Java
new TextField<String>(“username”,new Model<String>(“Inserisci
il tuo username”));
Codice HTML
Username: <input type="text" wicket:id="username"/>
●
Ora vediamo un esempio di model più chiaro, realizzando una
pagina di login con due campi testuali “username” e “password”.
Prototipo maschera di login
Il pannello di login (HTML)
<html>
…
<wicket:panel>
<div style="margin: auto; width: 40%" class="crop_content_contenuti">
<form id="ricerca" method="get" wicket:id="form">
<fieldset id="ricerca1" class="center">
<legend wicket:id="message">Ricerca</legend>
<p wicket:id="loginStatus" style="font-weight: bold;color: red;textalign: left"></p>
<span>Username: </span>
<input wicket:id="username" type="text" id="username" /><br/>
<span >Password: </span>
<input wicket:id="password" type="password" id="password" />
<p>
<input type="submit" name="login" value="login"/>
</p>
</fieldset>
</form>
</div>
</wicket:panel>
…
</html>
●
Nella pannello di login oltre ai campi username/password abbiamo
inserito anche un titolo attraverso il tag <legend> e abbiamo inserti un
paragrafo che contiene eventuali messaggi di errore se il login non va a
buon fine.
Il pannello e la form di login (Java) 1
public class LoginPanel extends Panel {
public LoginPanel(String id) {
super(id);
init();
}
private void init(){
Form loginForm = new LoginForm("form");
add(loginForm);
}
}
●
Il pannello di login serve esclusivamente da “wrapper” per l'oggetto
form vero e proprio che contiene i campi username e epassword e che
gestisce il login.
Il pannello e la form di login (Java) 2
public class LoginForm extends Form {
private TextField usernameField = null;
private PasswordTextField passwordField = null;
private Label loginStatus = null;
public LoginForm(final String componentName) {
super(componentName);
usernameField = new TextField("username", new Model<String>(""));
passwordField = new PasswordTextField("password", new
Model<String>(""));
loginStatus = new Label("loginStatus");
Wicket dispone di un componente
apposito per i campi password.
add(usernameField);
add(passwordField);
add(new Label("message", "Login"));
L'evento onSubmit della form scatta
add(loginStatus);
}
prima di inviare i parametri della form al
server.
public final void onSubmit() {
String username = usernameField.getValue();
String password = passwordField.getValue();
if((username.equals("Mario") && password.equals("Rossi")))
loginStatus.setDefaultModel(new Model<String>("Complimenti!"));
else
loginStatus.setDefaultModel(new Model<String>("Username o
password errate!"));
}
Il pannello di login (Java)
public class LoginPanel extends Panel {
public LoginPanel(String id) {
super(id);
init();
}
private void init(){
Form loginForm = new LoginForm("form");
add(loginForm);
}
public final
private
private
private
class LoginForm extends Form {
TextField usernameField = null;
PasswordTextField passwordField = null;
Label loginStatus = null;
public LoginForm(final String componentName) {
super(componentName);
Wicket dispone di un componente
apposito per i campi password.
usernameField = new TextField("username", new Model<String>(""));
passwordField = new PasswordTextField("password", new Model<String>(""));
loginStatus = new Label("loginStatus");
add(usernameField);
add(passwordField);
add(new Label("message", "Login"));
add(loginStatus);
}
L'evento onSubmit della form scatta
prima di inviare i parametri della form
al server.
public final void onSubmit() {
String username = usernameField.getValue();
String password = passwordField.getValue();
if((username.equals("Mario") && password.equals("Rossi")))
loginStatus.setDefaultModel(new Model<String>("Complimenti!"));
else
loginStatus.setDefaultModel(new Model<String>("Username o password errate!"));
...
La pagina di login
●
Visto che ci siamo usiamo il layout di Jug4Tenda.....
package helloWorld.layoutTenda;
import helloWorld.LoginPanel;
import org.apache.wicket.markup.html.basic.Label;
public class LoginPage extends JugTemplate {
public LoginPage(){
super();
}
addOrReplace(new LoginPanel("contentComponent"));
}
Demo
JUG – Ancona Italy
Il framework Wicket
Gestione avanzata dello stato
●
I repeat viewer
●
I bean come model Wicket
●
●
●
Abbiamo visto cosa è il model in Wicket e lo abbiamo applicato nel
modo più semplice possibile agli oggetti TextField
Tuttavia la vera utilità del model si comprende usando funzioni più
raffinate che permettono di associare a form e controlli delle
semplici istanze di Java Bena da usare come model.
Ciò permette di ragionare in maniera completamente object oriented
e di usare il model di wicket in maniera molto più naturale.
Esempio: Vogliamo realizzare un pannello e con una form con dei
semplici dati anagrafici (nome, cognome, indirizzo, email).
Premendo submit la form:
1) crea un'istanza della classe Person (il nostro JavaBean) che contiene
i dati anagrafici
2) la aggiunge alla lista di istanze precedentemente create
3) visualizza le istanze della lista.
Il JavaBean Person
package helloWorld;
import java.io.Serializable;
public class Person implements Serializable {
private
private
private
private
String
String
String
String
name;
sureName;
address;
email;
public
public
public
public
String getAddress() {return address;}
void setAddress(String address) {this.address = address;}
String getEmail() {return email;}
void setEmail(String email) {this.email = email;}
public
public
public
public
String getName() {return name;}
void setName(String name) {this.name = name;}
String getSureName() {return sureName;}
void setSureName(String sureName) {this.sureName = sureName;}
}
La form
class CreatePerson extends Form{
private Person person = new Person();
public Person getPerson() {
return person;
}
public CreatePerson(String id) {
super(id);
setDefaultModel(new CompoundPropertyModel<Person>(this));
add(new
add(new
add(new
add(new
TextField<String>("person.name"));
TextField<String>("person.sureName"));
TextField<String>("person.address"));
TextField<String>("person.email"));
}
@Override
protected void onSubmit() {
super.onSubmit();
personsArray.add(person);
person = new Person();
}
}
La form
class CreatePerson extends Form{
private Person person = new Person();
Uso la stessa form come modello per i
public Person getPerson() {
miei dati ed avrò accesso ai sui campi
return person;
}
public CreatePerson(String id) {
super(id);
setDefaultModel(new CompoundPropertyModel<Person>(this));
add(new
add(new
add(new
add(new
TextField<String>("person.name"));
TextField<String>("person.sureName"));
TextField<String>("person.address"));
TextField<String>("person.email"));
}
Si traduce in
@Override
getPerson().getPerson().set/getName, quindi il
protected void onSubmit()
{
TextFiled
legge/scrive direttamente sui campi
super.onSubmit();
dell'istanza di Person
personsArray.add(person);
person = new Person();
}
La form sarà una inner class del pannello è
}
vedrà la sua variabile personsArray
Il pannello
<wicket:panel>
<div style="text-align: center;float: left;">
<form wicket:id="form" id="form">
...
</form>
</div>
<br style="clear: both;"></br>
<span wicket:id="persons" >
<div style="background-color: rgb(255, 245, 236); border: ">
<b>Nome:</b> <span wicket:id="personName"></span><br></br>
<b>Cognome:</b> <span wicket:id="personSurename"></span><br></br>
<b>Indirizzo:</b> <span wicket:id="address"></span><br></br>
<b>Cognome:</b><span wicket:id="email"></span>
</div><br/>
</span>
</wicket:panel>
●
Nel pannello oltre alla form c'è un componente con id persons. E'un
nuovo tipo di componente Wicket che visualizza collezioni di oggetti
ripetendo il codice HTML al suo interno per ogni elemento della
collezione.
Il pannello
public class PersonsManager extends Panel {
private List<Person> personsArray = new ArrayList<Person>();
Il codice nell'ellisse è il repeat viewer
public PersonsManager(String id, List<Person>
personsArray)
{
che visualizza
la lista di persone
create
super(id);
add(new CreatePerson("form"));
PageableListView<Person> persons = new
PageableListView<Person>("persons",
personsArray,30){
@Override
protected void populateItem(ListItem<Person> personHtml) {
personHtml.add(new Label("personName",
personHtml.getModel().getObject().getName()));
personHtml.add(new Label("personSurename",
personHtml.getModel().getObject().getSureName()));
personHtml.add(new Label("address",
personHtml.getModel().getObject().getAddress()));
personHtml.add(new Label("email",
personHtml.getModel().getObject().getEmail()));
}
};
add(persons);
this.personsArray = personsArray;
}
Demo
Conclusioni
Pro:
Permette di applicare la
programmazione OO dal
backend alla GUI, quindi...
Rende le applicazioni web
testabili molto più facilmente.
Gestione dello stato
trasparente.
Grande varietà di componenti
pronti all'uso.
...
Contro:
Cambio di prospettiva radicale!
Documentazione utente e
tutorial frammentari e scarni.
...
JUG – Ancona Italy
Grazie !
Andrea Del Bene
JUG Marche - www.jugancona.it