230 likes | 381 Views
Udvikling af egne komponenter. UI Components. Egne komponenter Composite Components. Hvornår?. En eksisterende komponents opførsel skal modificeres, eks skal komponenten sende en ekstra event
E N D
UI Components • Egne komponenter • Composite Components
Hvornår? • En eksisterende komponents opførsel skal modificeres, eks skal komponenten sende en ekstra event • Når eksisterende komponenter kan samles til ny komponent. Eks. når dato dropdowns benyttes til at vælge en dato • Du skal bruge et HTML element som understøttes af HTML klient, men som ikke understøttes af eksisterende JavaServer Faces HTML komponenter. • Du skal rendere til en klient, der ikke forstår HTML. Eksempelvis en WML-klient (mobile håndholdte apparater)
Hvornår ikke? • Når komponent allerede er lavet af andre. Tjek: • http://www.jsfcentral.com • http://jamesholmes.com/JavaServerFaces • Ny opførsel kan opnås uden ny komponent, eksempelvis ved indførelse af custom validator/converter
Hvad består en UI komponent af? Kan rendere en komponent og nogen gange også decode data fra et request. Facelets tag library descriptor fil, som associerer UIComponent klasser med tags på xhtml-siden. Renderer klasse (optional) <f:view> <html> <body> <sh:sayhello.../> </body> </html> </f:view> TLD UIComponent Klasse Converter Validator Converter Converter Klasse der repræsenteret opførslen af en komponent. Den kan eventuelt renderer sig selv
Et eksempel på en komponent • Vi vil nu vise hvordan man laver en simpel komponent á la ’Hello World’. • Du kan se det samlede eksempel i projektet: Facelets - Ex – UIComponents-CustomComponent.
Krav til komponenten • Vores simple komponent skal kunne byde en bruger velkommen og derudover udskrive det aktuelle tidspunkt. • Den skal kunne konfigureres med navn – evt. i form af et Expression Language udtryk et EL-udtryk
Hvad består komponenten af? • En komponent-klasse der implementerer komponentens funktionalitet • En component-entry i faces.config. • En entry i Facelets TLD-filen faces-config Component type Konfiguration. v. Component type TLD UI Komponent Klasse
Komponent-klassen <<interface>> StateHolder • Vi starter med at undersøge om vikan nedarve fra en eksisterendekomponent. • Der er ingen oplagte JSF-komponenter at nedarve fra, så vi beslutter at lave en direkte subklasse til UIComponentBase. • Endvidere vælger vi, at bruge direct rendering, dvs. at komponenten selv producerer den HTML der sendes til brugeren. UIComponent UIComponentBase SayHelloUIComponent
Komponent-klassen package dk.lundogbendsen.jsf.sayhello; import ...; public class SayHelloUIComponent extends UIComponentBase { private String name; public String getName() {return name;} public void setName(String name) {this.name = name;} public void encodeBegin(FacesContext context) throws IOException { ResponseWriter writer = context.getResponseWriter(); String name = (String) getAttributes().get("name"); writer.startElement("h2", this); writer.write("Hello, "); if (name != null) writer.writeText(name, "name"); else writer.writeText("Stranger!", null); writer.endElement("h2"); writer.startElement("p", this); writer.writeText(" Dags dato: " + new Date(), null); writer.endElement("p"); } public String getFamily() { return null; } } Family er kun relevant når komponenten skal renderes af en eller flere renderers. Derfor returneres null.
Registrering i faces-config <faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"> <component> <component-type>dk.lundogbendsen.SayHello</component-type> <component-class > dk.lundogbendsen.component.SayHelloUIComponent </component-class> </component> </faces-config> I JSF 2.x kan man alternativt bruge annotationen @FacesComponent.
Tag Library Descriptor (1/3) • En Facelets Tag Library Descriptor-fil er et XML-dokument, der definerer en samling af tags – deraf også navnet et tag library • Kan bl.a. angive hvilken klasse, der ligger bag det enkelte tag • kan også indeholde EL-funktioner. • Den fulde dokumentation for formattet findes her: https://facelets.java.net/nonav/docs/dev/docbook.html#taglib-create-schema
Tag Library Descriptor (2/3) <?xml version="1.0" encoding="UTF-8"?> <facelet-taglib xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd" version="2.0"> <namespace>http://lundogbendsen.dk/sayHello</namespace> <tag> <tag-name>sayHello</tag-name> <component> <component-type>dk.lundogbendsen.SayHello</component-type> </component> </tag> </facelet-taglib> Læg mærke til at TLD-filen ikke specificerer hvilke attributter, komponenten har. Det er nødvendigt at specificere attributterne i en JSP Tag Library Descriptor hvis man arbejder med JSP-sider i stedet for Facelet xhtml-sider.
Tag Library Descriptor (3/3) • Tag LibraryDescriptor filen kan placeres 3 steder: • I et Java Archive (jar)’s META-INF folder. Denne fremgangsmåde bruges når et antal komponenter pakkes i en jar fil. • I en Web-applikations META-INF folder. • I en Web-applikations rod, dvs i .war filen ved siden af web.xml. Dette kræver dog en ekstra konfiguration i web.xml filen: <context-param> <param-name>javax.faces.FACELETS_LIBRARIES</param-name> <param-value>/WEB-INF/sayhello.taglib.xml</param-value> </context-param>
Overførsel af tag attributter til komponent • Vi så lige, at tag-attributter ikke konfigureres i Facelets TLD’en. Hvorfor ikke? • Hvis komponenten nedarver fra ActionSource(2), ValueHolder eller EditableValueHolder forsøger Facelets automatisk at autowire standardattributterne. • Facelets tolerer alle tag attributter på en side (ingen fejl) og forsøger at sætte værdien af tag attributterne på den tilhørende komponent.
Overførsel af tag-attributter til komponent Så tilføjes værdien til komponentens ValueExpression-Map ved et kald til setValueExpression • Hvis værdien er et ValueExpression og komponenten nedarver fra UIComponent • Facelets forsøger at finde og eksekvere en settter-metode på komponenten svarende til tag-attributnavnet. • En entry tilføjes i komponentens generiske attributsæt UIComponent … <sh:sayHello name=“#{param.name}"/> … setValueExpression(name, expr) getAttributes(): Map … … <sh:sayHello name="Peter"/> … SayHello getName():String setName(String) getAttributes().put(”foo”, ”Bar”): … <sh:sayHello foo=“Bar"/> …
UI Components • Egne komponenter • Composite Components
Når komponenter er basale... • De fleste komponenter er i virkeligheden bare kombinationer af eksisterende JSF-komponenter. • Eksempler: • Søgefelt i et hjørne af siden m. Tilhørende options • Tekstfelter med indbyggede suggestions
Composite Components • Hvis en komponent ikke skal være alt for avanceret, kan man ofte slippe afsted med at lave en Composite Component. • Composite Components er en ny feature i JSF 2.x, som er blevet mulig med Facelets’ indtog. Idéen er at hele komponenten skrives i en enkelt Facelet og man undgår Java-klasser, taglibs, registering i faces-config.xml osv.
Component Interface • Komponentens interface bestemmer kontrakten med JSF: hvilke attributter udstiller komponenten, så siden kan kommunikere med den? • Der autogenereres en TLD på baggrund af disse attributter. • Defineres i tagget <composite:interface>.
Component Implementation • Selve implementeringen foregår i tagget <composite:implementation>. • Her laves layout (typisk via andre JSF-komponenter) og refereres til de værdier, som kommunikeres ind via interfacet. Dette gøres vha. referencer på cc.attrs:
Brug af komponenten • I stedet for at registrere komponenten i faces-config.xml lægger man den bare ned i folderen /resources – så er den klar til brug:
Eksempel Læg mærke til: • Brugen af composite components indeni andre composite components. • Hvordan tovejskommunikation (validators) er muligt mellem side og komponent. JSF-Ex-Composite