Programowanie wielowarstwowe i komponentowe
Komunikaty
Proste komunikaty Założenia Przechowywanie niezmiennych stringów w prostym pliku tekstowym Załadowanie pliku. Odwołanie się do tekstu przez nazwę, która jest w pliku Cel Ten sam tekst na różnych stronach Zmiana w jednym miejscu Uwagi Właściwości beana powinny być stosowane dla zmiennych w trakcie działania programu Wpisy w pliku są prostsze niż zmienne w kodzie programu
Wyświetlanie stałych komunikatów 1. Utworzenie pliku.properties Zawiera strukturę klucz=wartość Jego miejsce to WEB-INF/classes W przypadku eclipse plik jest w katalogu src 2. Deklaracja resource-bundle w pliku faces-config.xml base-name zawiera nazwę pliku var to nazwa mapy używanej w plikach Przykład <resource-bundle> <base-name>messages</base-name> <var>msg</var> </resource-bundle> 3. Teksty wyświetlane są korzystając z języka wyrażeń EL #{msg.nazwaklucza}
Wyświetlanie stałych komunikatów (wersja z podkatalogiem) 1. Utworzenie pliku.properties Zawiera strukturę klucz=wartość Jego miejsce to WEB-INF/classes/resources W eclipse w katalogu src tworzy się package resources 2. Deklaracja resource-bundle w pliku faces-config base-name zawiera nazwę pliku var to nazwa mapy używanej w plikach Przykład <resource-bundle> <base-name>resource.messages</base-name> <var>msg</var> </resource-bundle> 3. Teksty wyświetlane są korzystając z języka wyrażeń EL #{msg.nazwaklucza}
Konfiguracja w faces-config Tag <resource-bundle> należy umieścić w tagu <application> <?xml version="1.0" encoding="utf-8"?> <faces-config > <application> <resource-bundle> <base-name>message</base-name> <var>msg</var> </resource-bundle> </application> </faces-config>
Przykład pliku src/message.properties registrationtitle=rejestracja registrationtext=proszę podać swoje imię, nazwisko i adres email. firstnameprompt=podaj swoje imię lastnameprompt=podaj swoje nazwisko emailaddressprompt=podaj swój adres email buttonlabel=zarejestruj successtitle=sukces successtext=zarejestrowałeś się pomyślnie. Plik jest w katalogu: /WEB-INF/classes/message.properties Wpis do faces-config.xml <resource-bundle> <base-name>messages</base-name> <var>msgs</var> </resource-bundle> Wpisy na stronach z użyciem języka wyrażeń #{msgs.firstnameprompt}
Przykład plik faces-config.xml <?xml version="1.0"?> <faces-config > <application> <resource-bundle> <base-name>messages</base-name> <var>msgs</var> </resource-bundle> </application> </faces-config>
Przykład rejestracja.xhtml <!DOCTYPE > <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <h:head> <title>#{msgs.registrationtitle}</title> </h:head> <h:body> <table border="5" align="center"> <tr> <th class="title">#{msgs.registrationtitle}</th> </tr> </table> <h3>#{msgs.registrationtext}</h3>
Przykład rejestracja.xhtml <h:form> #{msgs.firstnameprompt}: <h:inputtext value="#{person1.firstname}"/> <br/> #{msgs.lastnameprompt}: <h:inputtext value="#{person1.lastname}"/> <br/> #{msgs.emailaddressprompt}: <h:inputtext value="#{person1.emailaddress}"/> <br/> <h:commandbutton value="#{msgs.buttonlabel}" action="#{person1.doregistration}"/> </h:form> </h:body></html>
Przykład Person.java public abstract class Person { private String firstname, lastname, emailaddress; public String getfirstname() { return(firstname); } public void setfirstname(string firstname) { this.firstname = firstname; } // get/setlastname, get/setemailaddress } public abstract String doregistration();
Przykład Person1.java @ManagedBean public class Person1 extends Person { public String doregistration() { } return( sukces"); }
Przykład sukces.xhtml <!DOCTYPE > <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <h:head><title>#{msgs.successtitle}</title> </h:head> <h:body> <table border="5" align="center"> <tr><th class="title">#{msgs.successtitle}</th></tr> </table> <p>#{msgs.successtext}</p> <ul> <li>#{person1.firstname}</li> <li>#{person1.lastname}</li> <li>#{person1.emailaddress}</li> </ul> </h:body></html>
Komunikaty parametryzowane Założenia Cel Teksty przechowywane są w pliku, każdy z tekstów posiada swoją nazwę. Część tekstu może być modyfikowana Teksty są tworzone bardziej elastyczne Części tekstu są przekazywane do tekstu komunikatu Uwagi Teksty nie są statyczne, ale ich część jest wciąż stała
Wyświetlenie komunikatów parametryzowanych 1. Tworzenie pliku.properties Użycie zapisu {0}, {1}, {2} itd. Teksty zapisane w formie: klucz=wartość {0} wartość {1} 2. Deklaracja pliku w resource-bundle Podobnie jak wcześniej 3. Wyświetlanie komunikatów przy użyciu h:outputformat Tekst wyświetlany jest przy pomocy tagu <h:outputformat >, dane przekazywane są poprzez tag f:param <h:outputformat value="#{msgs.etykieta}"> <f:param value="wartosc wpisana w miejsce {0}"/> <f:param value="#{jakisbean.wartoscobliczonaw1}"/> </h:outputformat>
Przykład message2.properties registrationtitle=rejestracja firstname=imię lastname=nazwisko emailaddress=adres email registrationtext=proszę podać swoje {0}, {1} i {2}. prompt=podaj {0} buttonlabel=zarejestruj successtitle=sukces successtext=zarejestrowałeś się pomyślnie.
Przykład plik faces-config.xml <?xml version="1.0"?> <faces-config > <application> <resource-bundle> <base-name>messages</base-name> <var>msgs</var> </resource-bundle> <resource-bundle> <base-name>messages2</base-name> <var>msgs2</var> </resource-bundle> </application> </faces-config>
Przykład rejestracja2.xhtml <!DOCTYPE > <html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"> <h:head><title>#{msgs2.registrationtitle}</title> <h3> <h:outputformat value="#{msgs2.registrationtext}"> <f:param value="#{msgs2.firstname}"/> <f:param value="#{msgs2.lastname}"/> <f:param value="#{msgs2.emailaddress}"/> </h:outputformat>
Przykład Person2.java @ManagedBean public class Person2 extends Person { public String doregistration() { } return("sukces2"); }
Przykład sukces2.xhtml <!DOCTYPE > <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <h:head><title>#{msgs2.successtitle}</title> </h:head> <h:body> <table border="5" align="center"> <tr><th class="title">#{msgs2.successtitle}</th></tr> </table> <h3>#{msgs2.successtext}</h3> <ul> <li>#{msgs2.firstname}: #{person2.firstname}</li> <li>#{msgs2.lastname}: #{person2.lastname}</li> <li>#{msgs2.emailaddress}: #{person2.emailaddress}</li> </ul> </h:body></html>
Wielojęzyczność Założenia Cel Przechowywanie wielu wersji pliku properties w zależności od języka Strony wyświetlane są w wielu językach Uwaga Sposób na ustawienie języka w zależności od języka przeglądarki
Wielojęzyczność 1. Tworzenie wielu podobnych plików.properties Pliki: message.properties, message_en.properties, message_de.properties 2. Użycie f:view z atrybutem locale <f:view locale="#{facescontext.externalcontext.requestlocale} > Określa język na podstawie języka przeglądarki Można jednak ustawić język ręcznie 3. Deklaracja plików w resource-bundle Wersja języka dobierana jest automatycznie 4. Korzystanie z h:outputformat i języka wyrażeń Jak poprzednio
Przykład pliki.properties message.properties company=nazwafirmy.com feature=twoje {0}: firstname=imię message_en.properties feature=your {0}: firstname=first name
Przykład faces-config.xml bez zmian <?xml version="1.0"?> <faces-config > <application> <resource-bundle> <base-name>messages</base-name> <var>msgs</var> </resource-bundle> </application> </faces-config>
Przykład plik xhtml <!DOCTYPE > <html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"> <f:view locale="#{facescontext.externalcontext.requestlocale}"> <h1>#{msgs.company}</h1> <h2> <h:outputformat value="#{msgs.feature}"> <f:param value="#{msgs.firstname}"/> </h:outputformat> </h2> <img src="swimming-pool.jpg" /> </f:view> </html>
Działanie programu Polski nazwafirmy.com Twoje imię: Angielski nazwafirmy.com Your first name:
Przykład message2.properties registrationtitle=rejestracja firstname=imię lastname=nazwisko emailaddress=adres email registrationtext=proszę podać swoje {0}, {1} i {2}. prompt=podaj {0} buttonlabel=zarejestruj successtitle=sukces successtext=zarejestrowałeś się pomyślnie.
Przykład mesages2_en.properties registrationtitle=registration firstname=first Name lastname=last Name emailaddress=email Address registrationtext=please Enter Your {0}, {1}, and {2}. prompt=enter {0} buttonlabel=register Me successtitle=success successtext=you Registered Successfully.
Przykład messages2_fr.properties registrationtitle=enregistrement firstname=prénom lastname=nom emailaddress=adresse électronique registrationtext=merci de Entrer Votre {0}, {1}, et {2}. prompt=entrez Votre {0} buttonlabel=enregistrez Moi successtitle=succès successtext=vous Avez Enregistré Avec Succès.
Przykład plik faces-config.xml <?xml version="1.0"?> <faces-config > <application> <resource-bundle> <base-name>messages</base-name> <var>msgs</var> </resource-bundle> <resource-bundle> <base-name>messages2</base-name> <var>msgs2</var> </resource-bundle> </application> </faces-config>
Przykład rejestracja3.xhtml <!DOCTYPE > <html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"> <f:view locale="#{facescontext.externalcontext.requestlocale}"> <h:head><title>#{msgs2.registrationtitle}</title> <h3> <h:outputformat value="#{msgs2.registrationtext}"> <f:param value="#{msgs2.firstname}"/> <f:param value="#{msgs2.lastname}"/> <f:param value="#{msgs2.emailaddress}"/> </h:outputformat> </f:view> </html>
Przykład sukces2.xhtml <!DOCTYPE > <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <f:view locale="#{facescontext.externalcontext.requestlocale}"> <h:head><title>#{msgs2.successtitle}</title> </h:head> <h:body> <table border="5" align="center"> <tr><th class="title">#{msgs2.successtitle}</th></tr> </table> <h3>#{msgs2.successtext}</h3> <ul> <li>#{msgs2.firstname}: #{person2.firstname}</li> <li>#{msgs2.lastname}: #{person2.lastname}</li> <li>#{msgs2.emailaddress}: #{person2.emailaddress}</li> </ul> </h:body> </f:view> </html>
Zdarzenia Dwie możliwości obsługi zdarzeń Zdarzenia, który rozpoczyna proces działający po stronie logiki systemu (action) Zdarzenia, na które ma wpływ zachowanie użytkownika w GUI (action event, value change event) Dwa typy zdarzeń: Action controllers dotyczy przekazywania formy (submit) Wykonywana jest po wypełnieniu beana Wykonywana jest po walidacji danych Zwraca łańcuch znaków odpowiadający Event listeners odnosi się do zdarzeń związanych w elementami formatki Często wykonywany jest przed wypełnieniem beana Często omija walidację Nigdy nie wpływa na efekt nawigacji
Typy Event Listeners Action Listener Wywoływane przez przyciski, image maps i odwołania (hypertext links) <h:commandbutton value="...".../> <h:commandbutton image="...".../> <h:commandlink.../> Automatycznie wywołuje submit formy ValueChangeListener Wywoływane przez combobox, checkbox, radio button, pola tekstowe i inne <h:selectonemenu.../> <h:selectbooleancheckbox.../> <h:selectoneradio.../> <h:inputtext.../> Nie wywołuje automatycznie submit formy
ActionListener Przycisk może wykonać submit na formie i rozpocząć działanie logiki systemu <h:commandbutton action="..."...> Inne działanie przycisku Użycie <h:commandbutton actionlistener="...".../> Ten proces może zostać wykonany przed wypełnieniem beana i przed procesem walidacji Użycie atrybutu immediate pozwoli na odpalenie zdarzenia przed procesem walidacji <h:commandbutton actionlistener="..." immediate="true".../>
Implementacja ActionListener Słuchacz (Listener) nie potrzebuje być jednocześnie w klasie beanu-formy Czasami tworzy się oddzielne beany do obsługi informacji z GUI Metoda otrzymuje ActionEvent jako argument Zwracany jest typ void ActionEvent jest w paczce javax.faces.event ActionEvent posiada funkcję getcomponent pozwalające otrzymać referencję do componentu formy (UIComponent) Przykład: public void somemethod(actionevent event) { dosomesideeffects(); }
Przykład Założenie W programie przyciski służą do zmiany wielkości wyświetlanej czcionki Podejście Nazwa stylu dla elementu body jest przechowywana w session beanie <h:body styleclass="#{formsettings.bodystyleclass}"> Dwa przyciski uruchamiają action listeners, które z kolei zmieniają styl elementu body <h:commandbutton value="#{msgs.normalfont}" actionlistener="#{formsettings.setnormalsize} immediate="true"/> <h:commandbutton value="#{msgs.largefont} actionlistener="#{formsettings.setlargesize} immediate="true"/>
Przykład rejestracja.xhtml <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE > <html xmlns="http://www.w3.org/1999/xhtml". > <h:head> <title>#{msgs.registrationtitle}</title> <link href="./css/styles.css" rel="stylesheet" type="text/css"/> </h:head> <h:body styleclass="#{formsettings.bodystyleclass}"> <h:form> <legend>#{msgs.registrationtitle}</legend> <h:outputformat value="#{msgs.prompt}"> <f:param value="#{msgs.firstname}"/> </h:outputformat>: <h:inputtext value="#{person.firstname}"/> <h:commandbutton value="#{msgs.buttonlabel}" action="#{person.doregistration}"/>
Przykład rejestracja.xhtml cd. <br/> <div align="center"> <h:commandbutton value="#{msgs.normalfont}" actionlistener="#{formsettings.setnormalsize}" immediate="true"/> <h:commandbutton value="#{msgs.largefont}" actionlistener="#{formsettings.setlargesize}" immediate="true"/> </div> </h:form> </h:body> </html>
Przykład FormSettings.java @ManagedBean @SessionScoped public class FormSettings implements Serializable { private boolean isnormalsize = true; public String getbodystyleclass() { if (isnormalsize) { return ("normalsize"); } else { return ("largesize"); } } public void setnormalsize(actionevent event) { isnormalsize = true; } } public void setlargesize(actionevent event) { isnormalsize = false; }
Przykład Person.java @ManagedBean public class Person { private String firstname, lastname, emailaddress; // gettery i settery } public String doregistration() { if ("".equals(firstname) && "".equals(lastname) && "".equals(emailaddress)) { return("zle-dane"); } else { return("rejestracja-ok"); } }
Przykład faces-config.xml <?xml version="1.0"?> <faces-config > <application> <resource-bundle> <base-name>messages</base-name> <var>msgs</var> </resource-bundle> </application> </faces-config>
Przykład messages.properties registrationtitle=rejestracja firstname=imię lastname=nazwisko emailaddress=adres email registrationtext=proszę podać swoje {0}, {1} i {2}. prompt=podaj {0} buttonlabel=zarejestruj successtitle=sukces successtext=zarejestrowałeś się pomyślnie. switchlanguage=english normalfont=normalna czcionka largefont=duża czcionka errortitle=błąd! missingdata=złe dane. Spróbuj ponownie.
Przykład - styles.css.normalsize { font-size: 110% }.largesize { font-size: 200% }
Przykład zle-dane.xhtml <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE > <html > <h:head> <link href="./css/styles.css" rel="stylesheet" type="text/css"/> <title>#{msgs.errortitle}</title> </h:head> <h:body styleclass="#{formsettings.bodystyleclass}"> <h1>#{msgs.errortitle}</h1> </h:body> </html>
Przykład rejestracja-ok.xhtml <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE > <html "> <h:head> <link href="./css/styles.css" rel="stylesheet" type="text/css"/> <title>#{msgs.successtext}</title> </h:head> <h:body styleclass="#{formsettings.bodystyleclass}"> <h1>#{msgs.successtext}</h1> <ul> <li>#{msgs.firstname}: #{person.firstname}</li> <li>#{msgs.lastname}: #{person.lastname}</li> <li>#{msgs.emailaddress}: #{person.emailaddress}</li> </ul> </h:body> </html>
Programowa zmiana języka Dwie metody: Wywołanie setlocale FacesContext.getCurrentInstance(). getviewroot().setlocale(currentlocale); Użycie atrybutu locale w elemencie f:view <f:view locale="#{formsettings.currentlocale}"> Odczyt ustawień językowych z przeglądarki: <f:view locale="#{facescontext.externalcontext.requestlocale}"> Powinny być stosowane jednocześnie
Przykład Założenia: Dodanie do poprzedniego przykładu obsługi języka angielskiego Podejście: Utworzenie dwóch plików message.properties i message_en.properties Dodanie przycisku, który wywołuje zdarzenie action listener, które z kolei zmienia ustawienia językowe Dodanie <f:view locale="#{formsettings.locale}" >
Przykład rejestruj2.xhtml <!DOCTYPE > <html > <f:view locale="#{formsettings.locale}"> <! Ta sama zawartość jak rejestruj.xhtml i dodanie przycisku--> <h:commandbutton value="#{msgs.switchlanguage} actionlistener="#{formsettings.swaplocale} immediate="true"/> </f:view></html>
Przykład FormSettings.java @ManagedBean @SessionScoped public class FormSettings implements Serializable { // private boolean isenglish = true; private final Locale ENGLISH = Locale.ENGLISH; private final Locale POLISH = new Locale("pl"); public Locale getlocale() { if (isenglish) { return(english); } else { return(polish); } }
Przykład FormSettings.java cd public void swaplocale(actionevent event) { switchlocale(); } private void switchlocale() { isenglish =!isenglish; Locale newlocale; if (isenglish) { newlocale = ENGLISH; } else { newlocale = POLISH; } FacesContext.getCurrentInstance().getViewRoot().setLocale(newLocale); }
Przykład message_en.properties registrationtitle=registration firstname=first Name lastname=last Name emailaddress=email Address registrationtext=please Enter Your {0}, {1}, and {2}. prompt=enter {0} buttonlabel=register Me successtitle=success successtext=you Registered Successfully. switchlanguage=polski normalfont=normal Font largefont=large Font errortitle=error! missingdata=missing input. Please try again.
Przykład
ValueChangeListener ValueChangeListener jest używany przy combobox, listbox, radio button, checkbox, polach tekstowych itd. Różnice do ActionListener Forma nie jest submitowana Do wykonania submit niezbędna jest JavaScript onclick="submit()" lub onchange="submit()" Zdarzenie niekompatybilne dla Firefox i Internet Explorer Firefox, Opera, Chrome wywołuje metodę, gdy następuje zmiana w wartości kontrolki Internet Explorer wywołuje metodę, gdy nastąpi zmiana i zmieni się fokus OnClick powinno działać wszędzie
Implementacja ValueChangeListener Metoda przyjmuje ValueChangeEvent jako argument Metody klasy ValueChangeEvent: getcomponent podobnie jak w ActionListener getoldvalue poprzednia wartość w kontrolce getnewvalue nowa wartość kontrolki Przykład: public void somemethod(valuechangeevent event) { Boolean flag = (Boolean)event.getNewValue(); wykonajcoszflaga(flag); }
Przykład Założenie Użycie checkboxa do zmiany języka zamiast przycisku Podejście Utworzyć checkboxa, który uruchomi valuechangelistener, która zmieni język valuechangelistener="#{formsettings.swaplocale2}" Checkbox wywoła submit na formatce Checkbox zawsze jest wyłączony, gdy strona jest wyświetlana na nowo value="#{formsettings.checked} ischecked zwraca zawsze false
Przykład rejestracja3.xhtml <!DOCTYPE > <html > <f:view locale="#{formsettings.locale}"> <! Taki sam kod jak w rejestracja2.xhtml, zamiast ostatniego przcisku h:commandbutton jest poniższy checkbox --> <h:selectbooleancheckbox value="#{formsettings.checked}" valuechangelistener="#{formsettings.swaplocale2}" onclick="submit()" immediate="true"/> </f:view></html>
Przykład FormSettings.java public void swaplocale2(valuechangeevent event) { Boolean flag = (Boolean)event.getNewValue(); if (flag) { switchlocale(); } } public boolean getchecked() { return false; } public void setchecked(boolean checked) { }
Prezentacja danych z kolekcji h:datatable <ui:repeat>
h:datatable <h:datatable var="row" //nazwa zmiennej przechowującej każdy element kolekcji value="#{somebean.somedata}" //dane kolekcja (lista, tablica, itp.) border="1" //szerokość ramki styleclass="css-table-style" //nazwa klasy dla tabeli (table class="...) headerclass="css-heading-style" //nazwa klasy dla pierwszego wiersza rowclasses="evenrow,oddrow"> //klasa dla parzystego i nieparzystego wiesza <h:column> <f:facet name="header">col 1 Title</f:facet> //tekst nagłówka #{row.someproperty} //wartość w poszczególnych wierszach </h:column> <h:column> <f:facet name="header">col 2 Title</f:facet> //tekst kolejnego nagłówka wiersza #{row.someotherproperty} //wartość w poszczególnych wierszach w kolumnie 2 </h:column>... </h:datatable>
h:datatable - przykład Klasa Klient public class Klient { private int id; private String imie; private String nazwisko; private Konto [] konta; Klasa Klienci @ManagedBean public class Klienci { public static List<Klient> klients; public List<Klient> getklients () { if (klients ==null) { klients = new ArrayList<Klient>(); klients.add( new Klient(1, "Jan", "Kowalski", new Konto[] { new Konto("1111", 10), new Konto("2222", 1232)} )); klients.add( new Klient(2, "Anna", "Nowak", new Konto[] { new Konto("2333", -234), new Konto("2334", 0), new Konto("3422", 1002)} )); klients.add( new Klient(3, "Jacek", "Iksinski", new Konto[] { new Konto("7434", 1234)} )); } return klients; } }
h:datatable przykład cd..xhtml <h:datatable var="klient" value="#{klienci.klients}" border="1" styleclass="tablica" headerclass="naglowek" > <h:column> <f:facet name="header">id</f:facet> #{klient.id} </h:column> <h:column> <f:facet name="header">nazwisko</f:facet> #{klient.nazwisko} </h:column> <h:column> <f:facet name="header">imie</f:facet> #{klient.imie} </h:column> </h:datatable>
h:datatable przykład cd. css table.tablica { background-color: lightgray; border-spacing: 0px; } table.tablica td { width:200px; }.naglowek { background-color: black; color: white; }
h:datatable inny przykład <h:datatable var="klient" value="#{klienci.klients}" styleclass="tablica" headerclass="naglowek"> <h:column> <f:facet name="header">id</f:facet> #{klient.id} </h:column> <h:column> <f:facet name="header">nazwisko</f:facet> #{klient.nazwisko} </h:column> <h:column> <f:facet name="header">imie</f:facet> #{klient.imie} </h:column> <h:column> <f:facet name="header">konta</f:facet> <h:datatable var="konto" value="#{klient.konta}" styleclass="tablica" rowclasses="odd,even"> <h:column> <f:facet name="header">numer</f:facet> #{konto.numer} </h:column> <h:column> <f:facet name="header">saldo</f:facet> #{konto.saldo} </h:column> </h:datatable> </h:column> </h:datatable>
h:datatable inny przykład table.tablica { background-color: lightgray; border-spacing: 0px; } table.tablica td { width:200px; }.naglowek { background-color: black; color: white; }.odd { }.even { } background-color:yellow; background-color:orange;
ui:repeat <html... xmlns:ui="http://java.sun.com/jsf/facelets"> <ui:repeat var="somevar" value="#{somebean.somecollection}"> <somehtml> #{somevar.someproperty} </somehtml> </ui:repeat> Odpowiednik: for(sometype somevar: somecollection) { dosomethingwith(somevar); }
ui:repeat przykład, pętla zagnieżdzona <ui:repeat var="klient" value="#{klienci.klients}"> <h3>#{klient.id}. #{klient.nazwisko}, #{klient.imie}</h3> <ul> <ui:repeat var="konto" value="#{klient.konta}"> <li> #{konto.numer}: #{konto.saldo} </li> </ui:repeat> </ul> </ui:repeat>
ui:repeat <ui:repeat var="somevar" value="#{somebean.somecollection}" varstatus ="statusvariable" offset ="..." size ="..." step="...">... </ui:repeat> //od którego elementu rozpoczyna się pętla //liczba elementów kolekcji //skok statusvariable.first/last (boolean) pierwszy ostatni element statusvariable.even/odd (boolean) parzysty, nieparzysty element statusvariable.index (int) numer aktualnego elementu kolekcji
Przykład <ui:repeat var="klient" value="#{klienci.klients}"> <h3>#{klient.id}. #{klient.nazwisko}, #{klient.imie}</h3> <ul> <ui:repeat var="konto" value="#{klient.konta}" varstatus="status"> <li> #{konto.numer}: #{konto.saldo} <h:outputtext value="," rendered="#{!status.last}"/> <h:outputtext value="." rendered="#{status.last}"/> </li> </ui:repeat> </ul> </ui:repeat>
Szablony Szablon (template.xhtml) <head> <title> <ui:insert name="title" > Domyślny tytuł </ui:insert> </title> </head> <body> <ui:insert name="body" > Domyśla zawartość </ui:insert> </body> Strona korzystająca z szablonu (index.xhtml): <ui:composition template="/template.xhtml"> <ui:define name="title>strona startowa</ui:define> <ui:define name="body"> Zawartość strony głównej <ui:define> </ui:composition>
Przykład template.xhtml <h:head> </h:head> <h:body> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <link href="./styles.css" rel="stylesheet" type="text/css"/> <title><ui:insert name="title">strona szablonu</ui:insert></title> <div id="container"> <div id="top"> <ui:insert name="header">nagłówek</ui:insert> </div> <div id="leftnav"> <ui:insert name="left_menu">menu</ui:insert> </div> <div id="content"> <ui:insert name="content">content</ui:insert> </div> <div id="footer"> <ui:insert name="content">data ostatniej aktualizacji: 20.10.2014</ui:insert> </div> </div> </h:body>
Przykład index.xhtml <ui:composition template="/template.xhtml"> <ui:define name="title">strona główna</ui:define> <ui:define name="header"><h1>example.com</h1></ui:define> <ui:define name="left_menu"> <h3>menu główne</h3> <a href="stronaa.xhtml">strona a</a> <a href="#">strona B</a> <a href="#">niesamowita strona C</a> <a href="#">strona D</a> <a href="#">o nas</a> </ui:define> </ui:composition> <ui:define name="content"> <h3>wprowadzenie</h3> <p> Lorem ipsum </ui:define>
Przykład stronaa.xhtml <h:head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <link href="./styles.css" rel="stylesheet" type="text/css"/> </h:head> <h:body> <ui:composition template="/index.xhtml"> <ui:define name="title">strona A</ui:define> <ui:define name="content"> <h3>strona A</h3> <p> Lorem ipsum dolor </ui:define> </ui:composition> </h:body>
Walidacja Walidacja wymaga wykonania dwóch czynności: Sprawdzenie, czy wszystkie wartości pól są w odpowiednim formacie Ponowne wyświetlenie strony, gdy wartości są złe lub niepoprawne Ręczna walidacja Odczytanie wartości pól edycyjnych Sprawdzenie wartości w setterach i akcji kontrolera Zwrócenie null-a dla odświeżenia strony Tworzenie komunikatów o błędach i dodawanie ich do FacesMessage Wyświetlenie błędów przy pomocy h:messages Ukryta walidacja Stosowanie zmiennych typu int, double, dodanie required Przeładowanie strony w przypadku błędu konwersji danych h:message wyświetla komunikaty Jawna walidacja Użycie f:validatelength, f:validatedoublerange, f:validatelongrange, f:validateregex Odświeżenie strony w przypadku błędu, h:message wyświetla komunikat
Ręczna walidacja Settery przyjmują tylko wartości typu String Konwersja na inny typ przeprowadzana jest wewnątrz kodu Blok try/catch używany jest do przechwycenia błędnych danych Akcja kontrolera sprawdza wszystkie zmienne Gdy któraś z danych jest błędna: dodawany jest nowy komunikat o błędzie funkcją FacesContext.addMessage Zwracana jest wartość null Błąd wyświetlany jest na stronie poprzez h:messages
Wyświetlanie informacji o błędzie walidacji h:messages wyświetla zbiór komunikatów Umieszczany wewnątrz h:form <h:form><h:messages/> </h:form> Można dodać style Błędy wyświetlane są jako lista lub tabela h:message wyświetlenie indywidualnego błędu Użycie: <h:inputtext id="idelementu" /> <h:message for=" idelementu"/>
Ukryta automatyczna walidacja Właściwości w beanie posiadają typy proste int/integer, long/long, double/double, boolean/boolean JSF konwertuje wartości automatycznie Konwersja przy pomocy funkcji Integer.parseInt, Double.parseDouble itd. Gdy występuje błąd konwersji, strona jest wyświetlana ponownie Komunikat o błędzie jest dodawany automatycznie Można samemu tworzyć komunikaty o błędzie przy pomocy atrybutu conventermessage Atrybut required wymusza wypełnienie pola edycyjnego Wymuszenie może być w każdym z elementów JSF Własny komunikat o błędzie można dodać korzystając z atrybutu requiredmessage h:message wyświetla błąd. Gdy nie ma błędu, komunikat nie jest wyświetlany
Przykład - OfertaBean.java @ManagedBean public class OfertaBean { private String klientid; private String slowokluczowe; private Double kwota; private Integer ilosc; public String dooferta() { //wykonaj logike aplikacji return("pokaz-oferte"); } public Double getkwota() { return kwota; } public void setkwota(double kwota) { this.kwota = kwota; }
Przykład wprowadz-oferte.xhtml <h:form> <h:messages styleclass="error"/> Klient ID: <h:inputtext value="#{ofertabean.klientid}" required="true" requiredmessage="musisz podac ID klienta" id="klientid"/> <h:message for="klientid" styleclass="error"/> <br/> Słowo kluczowe: <h:inputtext value="#{ofertabean.slowokluczowe}" required="true" requiredmessage="musisz podac slowo kluczowe" id="slowokluczowe" /> <h:message for="slowokluczowe" styleclass="error"/> <br/>
Przykład wprowadz-oferte.xhtml cd Kwota zł: <h:inputtext value="#{ofertabean.kwota}" required="true" requiredmessage="musisz podac kwotę" convertermessage="wprowadzona wartość musi być liczbą" id="kwota"/> <h:message for="kwota" styleclass="error"/> <br/> Ilość: <h:inputtext value="#{ofertabean.ilosc}" required="true" requiredmessage="musisz podac ilość" convertermessage="wprowadzona wartość musi być liczbą" id="ilosc"/> <h:message for="ilosc" styleclass="error"/> <br/> <h:commandbutton value="wprowadź" action="#{ofertabean.dooferta}" /> </h:form>
Jawna walidacja walidatory i konwentery f:validatelength minimum maximum f:validatelongrange minimum maximum f:validatedoublerange minimum maximum f:validateregex pattern f:conventernumber curencycode, currencysymbol grupingused integeronly Locale max(min)fractiondigits max(min)integerdigits pattern (DecimalFormat) type: number, currency, procentage f:conventerdatetime type: date, time, both datestyle, timestyle pattern (SimpleDateFormat) locale timezone
Konwersja i walidacja Znaczniki f:convertx i f:validatex sprawdzają format i odświeżają stronę, gdy wartości nie są poprawne f:convertx może zmienić format wyświetlanej zmiennej Działa z h:outputtext Przykład <h:inputtext value="#{zamowieniebean.kod}"> <f:convertnumber maxfractiondigits="2"/> </h:inputtext> Wyświetla 0.75 przy wartości 0.749 <h:outputtext value="#{zamowieniebean.kod}"> <f:convertnumber type="percentage"/> </h:inputtext> Wyświetla 75%
Przykład wprowadz-oferte2.xhtml <h:messages styleclass="error"/> Klient ID: <h:inputtext value="#{ofertabean.klientid}" required="true" requiredmessage="musisz podac ID klienta" validatormessage="id musi posiadać od 5 do 6 znaków" id="klientid" > <f:validatelength minimum="5" maximum="6"/> </h:inputtext> <h:message for="klientid" styleclass="error"/> <br/>.
Przykład wprowadz-oferte2.xhtml cd Słowo kluczowe: <h:inputtext value="#{ofertabean.slowokluczowe}" required="true" requiredmessage="musisz podac slowo kluczowe" validatormessage="słowo kluczowe ma posiadać min. 3 znaki" id="slowokluczowe" > <f:validatelength minimum="3"/> </h:inputtext> <h:message for="slowokluczowe" styleclass="error"/> <br/>
Przykład wprowadz-oferte2.xhtml cd Kwota zł: <h:inputtext value="#{ofertabean.kwota}" required="true" requiredmessage="musisz podac kwotę" convertermessage="wprowadzona wartość musi być liczbą" validatormessage="kowta musi wynosić min. 0.10 zł" id="kwota"> <f:validatedoublerange minimum="0.10"/> </h:inputtext> <h:message for="kwota" styleclass="error"/> <br/>
Przykład wprowadz-oferte2.xhtml cd Ilość: <h:inputtext value="#{ofertabean.ilosc}" required="true" requiredmessage="musisz podac ilość" convertermessage="wprowadzona wartość musi być liczbą" validatormessage="ilość zamówienia musi wynieść min 15" id="ilosc"> <f:validatelongrange minimum="15"/> </h:inputtext> <h:message for="ilosc" styleclass="error"/> <br/>