Tải bản đầy đủ - 0 (trang)
Chapter 9. Custom Components, Converters, and Validators

Chapter 9. Custom Components, Converters, and Validators

Tải bản đầy đủ - 0trang

Figure9-1.Thespinnerandthetabbedpane



TheJSFAPIletsyouimplementcustomcomponentsand

associatedtagswiththesamefeaturesastheJSFstandard

tags.Forexample,h:inputusesavalueexpressionto

associateatextfield'svaluewithabeanproperty,soyou

couldusevalueexpressionstowirecalendarcellstobean

properties.JSFstandardinputcomponentsfirevaluechange

eventswhentheirvaluechanges,soyoucouldfirevalue

changeeventswhenadifferentdateisselectedinthe

calendar.

Thefirstpartofthischapterusesthespinnercomponentto

illustratebasicissuesthatyouencounterinallcustom

components.Wethenrevisitthespinnertoshowmore

advancedissues:



"UsinganExternalRenderer"onpage387

"CallingConvertersfromExternalRenderers"onpage

393

"SupportingValueChangeListeners"onpage394

"SupportingMethodExpressions"onpage396

Thesecondhalfofthechapterexaminesatabbedpane

componentthatillustratesthefollowingaspectsofcustom

componentdevelopment.

"ProcessingSelectItemChildren"page411

"ProcessingFacets"onpage412

"EncodingCSSStyles"onpage413

"UsingHiddenFields"onpage415

"SavingandRestoringState"onpage415

"FiringActionEvents"onpage418



ClassesforImplementingCustomComponents

Inthefollowingsections,wediscusstheclassesthatyou

needtoimplementcustomcomponents.

Tomotivatethediscussion,wewilldevelopaspinner

component.Aspinnerletsyouenteranumberinatextfield,

eitherbytypingitdirectlyintothefieldorbyactivatingan

incrementordecrementbutton.Figure9-2showsan

applicationthatusestwospinnersforacreditcard's

expirationdate,oneforthemonthandanotherfortheyear.

Figure9-2.Usingthespinnercomponent



InFigure9-2,fromtoptobottom,allproceedsasexpected.

Theuserentersvalidvalues,sonavigationtakesustoa

designatedJSFpagethatechoesthosevalues.

Thespinnerinsistsonintegervalues.Figure9-3showsan

attempttoenterbaddata.Weletthestandardinteger

converterhandleconversionerrors.Youcanseehowwedid

itin"UsingConverters"onpage369.

Figure9-3.Handlingconversionfailures



Hereishowyouusecorejsf:spinner:

<%@tagliburi="http://corejsf.com/spinner"prefix="corejsf"%>

...


id="monthSpinner"minimum="1"maximum="12"size="3"/>



...


id="yearSpinner"minimum="1900"maximum="2100"size="5"/>





Thecorejsf:spinnertagsupportsthefollowingattributes:

binding

id

minimum

maximum



rendered

size

value



Onlyoneoftheattributes—value—isrequired.

Theminimumandmaximumattributesletyouassignarangeof

validvalues—forexample,themonthspinnerhasaminimum

of1andamaximumof12.Youcanalsolimitthesizeofthe

spinner'stextfieldwiththesizeattribute.Thevalueattribute

cantakealiteralstring—forexample,value="2";oravalue

expression—forexample,value="#{someBean.someProperty}".

Finally,thespinnersupportsthebinding,id,andrendered

attributes,whicharediscussedinChapter4.Supportfor

thoseattributesisfreebecauseourtagclassextendsthe

javax.faces.webapp.UIComponentELTagclass.

Intheprecedingcodefragmentweassignedexplicit

identifierstoourspinnerswiththeidattribute.Wedidthat

sowecoulddisplayconversionerrorswithh:message.The

spinnercomponentdoesnotrequireuserstospecifyan

identifier.Ifanidentifierisnotspecified,JSFgeneratesone

automatically.

UsersofJSFcustomtagsneednotunderstandhowthose

tagsareimplemented.Userssimplyneedtoknowthe

functionalityofatagandthesetofavailableattributes.Just

asforanycomponentmodel,theexpectationisthatafew

skilledprogrammerswillcreatetagsthatcanbeusedby

manypagedevelopers.



TagsandComponents

Minimally,atagforaJSFcustomcomponentrequirestwo

classes:



Aclassthatprocessestagattributes.Byconvention,the

classnamehasaTagsuffix—forexample,SpinnerTag.

Acomponentclassthatmaintainsstate,rendersauser

interface,andprocessesinput.Byconvention,theclass

namehasaUIprefix—forexample,UISpinner.

Thetagclassispartoftheplumbing.Itcreatesthe

componentandtransferstagattributevaluestocomponent

propertiesandattributes.Theimplementationofthetag

classislargelymechanical.See"ImplementingCustom

ComponentTags"onpage372formoreinformationontag

classes.

TheUIclassdoestheimportantwork.Ithastwoseparate

responsibilities:

Torendertheuserinterfacebyencodingmarkup

ToprocessuserinputbydecodingthecurrentHTTP

request

Componentclassescandelegaterenderingandprocessing

inputtoaseparaterenderer.Byusingdifferentrenderers,

youcansupportmultipleclients,suchaswebbrowsersand

cellphones.Initially,ourspinnercomponentwillrenderitself,

butin"UsinganExternalRenderer"onpage387,weshow

youhowtoimplementaseparaterendererforthespinner.

Acomponent'sUIclassmustextendtheUIComponentclass.

Thatclassdefinesover40abstractmethods,soyouwillwant

toextendanexistingclassthatimplementsthem.Youcan

choosefromtheclassesshowninFigure9-4.

Figure9-4.JSFcomponenthierarchy(notallclasses

areshown)

[Viewfullsizeimage]



OurUISpinnerclasswillextendUIInput,whichextendsUIOutput

andimplementstheEditableValueHolderinterface.Our

UITabbedPanewillextendUICommand,whichimplementsthe

ActionSource2interface.

Note

TheActionSource2interfacewasaddedinJSF1.2.

AnActionSourcehasmethodstomanageaction

listeners.AnActionSource2additionallymanages

actions.InJSF1.1,theActionSourceinterface

handledbothactionsandactionlisteners.



TheCustomComponentDeveloper'sToolbox

Whenyouimplementcustomcomponents,youwillbecome

veryfamiliarwithahandfulofJSFclasses:



javax.faces.component.UIComponent

javax.faces.webapp.UIComponentELTag

javax.faces.context.FacesContext

javax.faces.application.Application

javax.faces.context.ResponseWriter

UIComponentisanabstractclassthatdefineswhatitmeansto



beacomponent.Eachcomponentmanagesseveral

importantcategoriesofdata.Theseinclude:

Alistofchildcomponents.Forexample,thechildrenof

theh:panelGridcomponentarethecomponentsthatare

placedinthegridlocation.However,acomponentneed

nothaveanychildren.

Amapoffacetcomponents.Facetsaresimilartochild

components,buteachfacethasakey,notapositionina

list.Itisuptothecomponenthowtolayoutitsfacets.

Forexample,theh:dataTablecomponenthasheaderand

footerfacets.

Amapofattributes.Thisisageneral-purposemapthat

youcanusetostorearbitrarykey/valuepairs.

Amapofvalueexpressions.Thisisanothergeneralpurposemapthatyoucanusetostorearbitraryvalue

expressions.Forexample,ifaspinnertaghasan

attributevalue="#{cardExpirationDate.month}",thenthe

componentstoresaValueExpressionobjectforthegiven

valueexpressionunderthekey"value".

Acollectionoflisteners.Thiscollectionismaintainedby

theJSFframework.



WhenyoudefineyourownJSFcomponents,youusually

subclassoneofthefollowingthreestandardcomponent

classes:

UICommand,ifyourcomponentproducesactionssimilartoa



commandbuttonorlink

UIOutput,ifyourcomponentdisplaysavaluebutdoesnot



allowtheusertoeditit

UIInput,ifyourcomponentreadsavaluefromtheuser



(suchasthespinner)

IfyoulookatFigure9-4,youwillfindthatthesethree

classesimplementinterfacesthatspecifythesedistinct

responsibilities:

ActionSourcedefinesmethodsformanagingaction



listeners.

ActionSource2definesmethodsformanagingactions.

ValueHolderdefinesmethodsformanagingacomponent



value,alocalvalue,andaconverter.

EditableValueHolderextendsValueHolderandaddsmethods



formanagingvalidatorsandvaluechangelisteners.

Tip

YouoftenneedtocastagenericUIComponent

parametertoasubclasstoaccessvalues,

converters,andsoon.Ratherthancastingtoa

specificclasssuchasUISpinner,casttoan

interfacetype,suchasValueHolder.Thatmakes

iteasiertoreuseyourcode.



TheFacesContextclasscontainsJSF-relatedrequest

information.Amongotherthings,youcanaccessrequest

parametersthroughFacesContext,getareferencetothe

Applicationobject,getthecurrentviewrootcomponent,or

getareferencetotheresponsewriter,whichyouuseto

encodemarkup.

TheApplicationclasskeepstrackofobjectssharedbyasingle

application—forexample,thesetofsupportedlocales,and

availableconvertersandvalidators.TheApplicationclassalso

servesasafactory,withfactorymethodsforcomponents,

converters,andvalidators.Inthischapter,wearemostly

interestedinusingtheApplicationclasstocreateconverters,

andtoobtainanexpressionfactoryforvalueandmethod

expressions.

Nearlyallcustomcomponentsgeneratemarkup,soyouwill

wanttousetheResponseWriterclasstoeasethattask.

ResponsewritershavemethodsforstartingandendingHTML

elements,andmethodsforwritingelementattributes.

Wenowreturntothespinnerimplementationandviewthe

spinnerfromanumberofdifferentperspectives.Westart

witheverycomponent'smostbasictasks—generating

markupandprocessingrequests—andthenturntothemore

mundaneissueofimplementingthecorrespondingtag

handlerclass.



Encoding:GeneratingMarkup



JSFcomponentsgeneratemarkupfortheiruserinterfaces.Bydefault,th

standardJSFcomponentsgenerateHTML.Componentscandotheirown

encoding,ortheycandelegateencodingtoaseparaterenderer.Thelatte

isthemoreelegantapproachbecauseitletsyouplugindifferent

renderers—forexampletoencodemarkupinsomethingotherthan

However,forsimplicity,wewillstartoutwithaspinnerthatrenders

Componentsencodemarkupwiththreemethods:

encodeBegin()

encodeChildren()

encodeEnd()



ThemethodsarecalledbyJSFattheendofthelifecycle,intheorderin

whichtheyarelistedabove.JSFinvokesencodeChildrenonlyifacomponen

returnstruefromitsgetRendersChildrenmethod.Bydefault,

getRendersChildrenreturnsfalseformostcomponents.



Forsimplecomponents,likeourspinner,thatdonothavechildren,youd

notneedtoimplementencodeChildren.Sincewedonotneedtoworry

getsencodedbeforeorafterthechildren,wedoallourencodingin

encodeBegin.

ThespinnergeneratesHTMLforatextfieldandtwobuttons;thatHTML

lookslikethis:





"/>



HereishowthatHTMLisencodedinUISpinner:

publicclassUISpinnerextendsUIInput{

privatestaticfinalStringMORE=".more";

privatestaticfinalStringLESS=".less";



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Chapter 9. Custom Components, Converters, and Validators

Tải bản đầy đủ ngay(0 tr)

×