Lekce 6 - Wicket - Formulář a model
V minulém díle, Wicket - Internacionalizace a lokalizace, jsme si ukázali, jak ve Wicketu vytvářet internacionalizované a lokalizované webové stránky.
V tomto díle tutoriálu vytvoříme stránku s kontaktním formulářem. Ten bude sloužit k tomu, aby nám mohli návštěvníci stránek napsat a poslat zprávu.
Nejdříve ale vyřešíme drobný nedostatek z přechozí lekce. Budeme chtít, aby se text titulku okna měnil okamžitě při změně locale. Aktuálně se v titulku okna zobrazí text, který předáváme při konstrukci objektu Label titleLB. Je třeba nastavit objektu titleLB model a tento model (data, která model vrací) měnit dle jazykového nastavení.
V balíčku cz.mujweb.basepage vytvoříme třídu modelu. Každý model obsahuje metodu getObject(), která vrací data a metodu setObject(), která data změní (metodu public void detach() nebudeme potřebovat, a proto ji necháme prázdnou). Náš model je jednoduchý.
TitleModel.java
public class TitleModel implements IModel { private String title = ""; @Override public void detach() { } @Override public Object getObject() { return title; } @Override public void setObject(Object object) { title = (String) object; } }
Ve třídě BasePage.java vytvoříme instanci tohoto modelu a při konstrukci titleLB ji předáme jako parametr. Metodu public abstract String getTitle(); již potřebovat nebudeme, místo ní vytvoříme public abstract void setTitleModelObject();
BasePage.java
public abstract class BasePage extends WebPage { protected IModel titleModel; public BasePage() { Link homePageLink = new Link("homePage") { … }; add(homePageLink); Link photosPageLink = new Link("photosPage") { … }; add(photosPageLink); add(new Link("en") { … }); add(new Link("cs") { … }); titleModel = new TitleModel(); Label titleLB = new Label("title", titleModel); add(titleLB); } public abstract void setTitleModelObject(); }
Vytváříme protected proměnnou titleModel, která bude přístupná v třídách, které z BasePage.class budou dědit.
protected IModel titleModel;
Dále do proměnné titleModel přiřadíme instanci TitleModelu a použijeme ji jako parametr Label konstruktoru. Dále pak musíme metodu setTitleModelObject zavolat. Výsledkem je to, že pokaždé, když se titleLB bude vykreslovat, zavolá metodu getObject() svého modelu a data, které touto metodou dostane, zobrazí.
titleModel = new TitleModel(); Label titleLB = new Label("title", titleModel); add(titleLB); setTitleModelObject();
Nyní musíme v HomePage.java a v PhotosPage.java smazat nyní již nepotřebnou metodu public String getTitle() a místo toho implementovat metodu public void setTitleModelObject(). Metoda setTitleModelObject() nastaví objekt metody (v našem případě textový řetězec) na novou hodnotu. Tato nová hodnota se použije při dalším vykreslení objektu titleLB.
HomePage.java
@Override public void setTitleModelObject() { titleModel.setObject(getString("title.homePage")); }
PhotosPage.java
@Override public void setTitleModelObject() { titleModel.setObject(getString("title.photosPage")); }
Nyní jsme dosáhli předchozí funkcionality jiným způsobem. Při vytvoření stránky je nastaven titulek dle jazykového nastavení. Aby se titulek změnil při kliknutí na odkaz, je třeba změnit data modelu při kliknutí. To provedeme v metodě public void onClick() odkazu (zavoláme metodu setTitleModelObject()).
BasePage.java
add(new Link("en") { @Override public void onClick() { Session.get().setLocale(Locale.ENGLISH); setTitleModelObject(); } }); add(new Link("cs") { @Override public void onClick() { Session.get().setLocale(new Locale("cs")); setTitleModelObject(); } });
Formulář
Formuláře ve Wicketu úzce spolupracují s modely = objekty, které zpracovávají a poskytují data. Wicket nám umožňuje napsat si vlastní modely (jak jsme viděli v předchozí části), ale zároveň pro nejčastější situace přichází s připravenými modely. Právě zpracování formulářů je častou činností a modely pro práci s formulářemi jsou ve Wicektu připraveny.
Pro práci s formuláři je přímo vytvořen CompoundPropertyModel, který využívá dědičnosti modelů. To znamená, že nemusíme přiřazovat model každé komponentě ve formuláři, ale přidáme model formuláři a komponenta, pokud nemá model přiřazen, se dotáže nadřazené komponenty (např. formuláře). Pokud jako id komponenty zvolíme název property ušetříme si hodně psaní. Model si odvodí, že daná property se vztahuje k dané komponentě.
V projektu si vytvoříme nový balíček (package) např. cz.mujweb.contatpage a v něm třídu formuláře, třídu kontaktní stránky a soubor .html
ContactForm.java
public class ContactForm extends Form { private String email; private String text; public ContactForm(String id) { super(id); System.out.println("form working"); setDefaultModel(new CompoundPropertyModel(this)); add(new TextField("email")); add(new TextArea("text")); } @Override protected void onSubmit() { System.out.println("Zadaný email: " + email); System.out.println("Zadaný text: " + text); } }
Náš formulář obsahuje dvě property.
private String email; private String text;
Dále formuláři nastavíme jako model CompoundPropertyModel. setDefaultModel(new CompoundPropertyModel(this));
Do formuláře vložíme dvě komponenty. Dáme jim id, které odpovídá názvu dané property ve formuláři.
add(new TextField("email")); add(new TextArea("text"));
Nakonec překryjeme metodu onSubmit(), která se provede po odeslání formuláře. Prozatím nám bude stačit, že hodnoty property vypíšeme.
@Override protected void onSubmit() { System.out.println("Zadaný email: " + email); System.out.println("Zadaný text: " + text); }
ContactPage.java
public class ContactPage extends BasePage { public ContactPage() { Form form = new ContactForm("form"); add(form); } @Override public void setTitleModelObject() { titleModel.setObject(getString("title.contactPage")); } }
ContactPage.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <wicket:extend> <form wicket:id="form"> <input type="text" wicket:id="email" id="email"/><br/> <textarea wicket:id="text" id="text" cols="40" rows="6"/><br/> <input type="submit" value="Odeslat"/> </form> </wicket:extend> </body> </html>
BasePage.java
Link contactPageLink = new Link("contactPage") { @Override public void onClick() { setResponsePage(ContactPage.class); } }; add(contactPageLink);
BasePage.html
<div id="menu"> <ul> <li><a href="#" wicket:id="homePage"><wicket:message key="menu.homePage"/></a></li> <li><a href="#" wicket:id="photosPage"><wicket:message key="menu.photos"/></a></li> <li><a href="#" wicket:id="contactPage"><wicket:message key="menu.contact"/></a></li> </ul> </div>
WicketApplication_cs.properties
title.contactPage=Kontaktní stránka menu.contact=Kontakt
WicketApplication.properties
title.contactPage=Contact page menu.contact=Contact
Výsledek v konzoli po odeslání formuláře.
Zadaný email: [email protected] Zadaný text: Pokusný text.
Stránka s formulářem se sice zobrazí a je funkční, ale má daleko k dokonalosti. Na stránku přidáme lokalizovaný nadpis, lokalizujeme nápis tlačítka a přidáme lokalizované popisky ke komponentám.
WicketApplication_cs.properties
text.contact=Kontaktní formulář form.email=Email form.text=Komentář form.submit=Odeslat
WicketApplication.properties
text.contact=Contact form form.email=Email form.text=Comment form.submit=Submit
ContactPage.html
<wicket:extend> <h2><wicket:message key="text.contact"/></h2> <form wicket:id="form"> <input type="text" wicket:id="email" id="email"/><label for="email"><wicket:message key="form.email"/></label><br/> <textarea wicket:id="text" id="text" cols="40" rows="6"/><label for="text"><wicket:message key="form.text"/></label><br/> <input type="submit" wicket:message="value:form.submit"/> </form> </wicket:extend>
style.css
form { padding-top: 5px; padding-bottom: 5px; } form label { padding-left: 5px; } form input { margin-bottom: 5px; margin-top: 5px; }
Pěkné, ne? Ale k užitečnosti to má zatím daleko.
To napravíme v příštím díle, Wicket - Databáze, kde se podíváme na propojení naší stránky a databáze.