Layout Components
Component Naming Schemes Here is the general naming scheme for ICEfaces component tags: Layout Components: panel* Input Components: input* Output Components: output* Selection Components: select*
ice:panelgroup Work horse of the panel components Renders child components surrounded by a HTML <div></div> Base container for the following dynamic behaviours Drag and drop source and target configuration Draggable container option Context menu linking Panel tool tip linking Effects container Default CSS class name is icepnlgrp
ice:panelgrid Convenient wrapper for displaying non-iterative data in an HTML <table/> tag Child components are each place in a table cell. New rows are defined by the integer attribute columns. Once x number or child component are rendered a new row is started Default CSS class name applied to the <table /> tag is icepnlgrd. CSS class can be applied to rows and columns Warning! No functionality for column or row spanning
ice:panelseries The panelseries component provides a mechanism for dynamically generating a series of repeating childcomponents within a panel Child components define the rendered layout Default CSS name applied to the parent <div/> is icepnlsrs Flexible component iterator -- essentially a datatable with out the <table /> Ability to use with an ice:datapaginator in order to provide pagination of results
ice:paneltabset Renders a table driven tabbed user interface. Comes in two flavours, declarative and iterative The parent tag <ice:paneltabset /> contain child tags <ice:paneltab /> in either flavour Selected tab change event can be optionally configured Selected tab can also be dynamically changed via a backing bean value CSS styling for this component is complex but also very flexible
ice:panelcollabsible This component allows the user to hide content and have it expand when the header is clicked
Other Layout Components panelpopup Modal and popup modes, will be covered in Facelet composite components panelstack Similar to Swing component of the same name. Not a good component to use when trying to minimize the weight of the component tree on the server Newer Components: paneldivider, split pain with dynamic divider paneltooltip, popup container menucontext, right-click popup context menu
Auto Complete Component
Auto-Complete Component ice:selectinputtext component provides an inputtext component enhanced with auto-complete functionality The component requires developers to implement the matching list search algorithm in their backing bean The ice:selectinputtext component can generate one of two types of lists: A list of String data A list of arbitrarily complex child components
Exercise: Overview The goal of this exercise is to add auto-complete functionality to the city field of the form When done, the user will be able to select a city from an auto-complete drop-down list, and the city, provinceid, and postalcode fields will be updated automatically
Step 1: Auto-Complete Component The city field is currently using an ice:inputtext component for user entry Rename ice:inputtext with ice:selectinputtext for the city field
Step 2: Add valuechangelistener for city In order to detect that the user has typed in some characters into the city field, we need to add a valuechangelistener Add the following attribute to the ice:selectinputtext component: valuechangelistener="#{applicantform.citylistener}" Open ApplicantForm.java in the IDE and paste the following method: public void citylistener(valuechangeevent valuechangeevent) { FacesContext facescontext = FacesContext.getCurrentInstance(); UIViewRoot uiviewroot = facescontext.getviewroot(); String citynamestartswith = (String)valueChangeEvent.getNewValue(); getcitysupport().filterselectitems(citynamestartswith); City city = getcitysupport().getcitybyname(citynamestartswith); if (city!= null) { UIInput cityinputtext = (UIInput) uiviewroot.findcomponent("applicantform:city"); cityinputtext.setsubmittedvalue(city.getcityname()); cityinputtext.setvalue(city.getcityname()); UIInput provinceinputtext = (UIInput) uiviewroot.findcomponent("applicantform:provinceid"); provinceinputtext.setsubmittedvalue(long.tostring(city.getprovinceid())); provinceinputtext.setvalue(city.getprovinceid()); UIInput postalcodeinputtext = (UIInput) uiviewroot.findcomponent("applicantform:postalcode"); postalcodeinputtext.setsubmittedvalue(city.getpostalcode()); postalcodeinputtext.setvalue(city.getpostalcode()); FacesContextHelper.clearImmediateFacesMessages(facesContext); } } Note the call to getcitybyname() which will eliminate the hard coded value of Orlando in the backing bean
Step 3: Add immediate attribute Normally valuechangelisteners fire during the PROCESS_VALIDATIONS phase of the JSF lifecycle But in order to avoid seeing extraneous validation failures, we need to add immediate= true to the auto-complete component Open the applicantform.xhtml file in the IDE Add the following to the ice:selectinputtext tag: immediate="true"
Step 4: Replace valuechangelistener for postalcode Replace the entire postalcodelistener() method with the following code: public void postalcodelistener(valuechangeevent valuechangeevent) { } FacesContext facescontext = FacesContext.getCurrentInstance(); UIViewRoot uiviewroot = facescontext.getviewroot(); String newpostalcode = (String) valuechangeevent.getnewvalue(); City city = getcitysupport().getcitybypostalcode(newpostalcode); if (city!= null) { } UIInput cityinputtext = (UIInput) uiviewroot.findcomponent("applicantform:city"); cityinputtext.setsubmittedvalue(city.getcityname()); cityinputtext.setvalue(city.getcityname()); UIInput provinceinputtext = (UIInput) uiviewroot.findcomponent("applicantform:provinceid"); provinceinputtext.setsubmittedvalue(long.tostring(city.getprovinceid())); provinceinputtext.setvalue(city.getprovinceid()); UIInput postalcodeinputtext = (UIInput) uiviewroot.findcomponent("applicantform:postalcode"); postalcodeinputtext.setsubmittedvalue(city.getpostalcode()); postalcodeinputtext.setvalue(city.getpostalcode()); FacesContextHelper.clearImmediateFacesMessages(facesContext); Note the call to getcitybypostalcode() which will eliminate the hard coded value of 32801 for Orlando in the backing bean now the code will work with any known postal code
Step 5: Add Select Items In order to populate the auto-complete list with items: Add the following iterator attributes to the ice:selectinputtext component: listvar="city" listvalue="#{citysupport.selectitems}" Add the following f:facet component as a child of the ice:selectinputtext component: <f:facet name="selectinputtext"> <ice:panelgrid columns="2"> <ice:outputtext id="autocompletecity" value="#{city.cityname}" /> <ice:outputtext id="autocompletepostalcode" value="#{city.postalcode}" /> </ice:panelgrid> </f:facet>
Step 6: Add City Transfer Object Create a new Java class: training.jobapplication.transfer.city Add the following properties: private long cityid; private long provinceid; private String cityname; private String postalcode; Generate getters/setters for each property Add the following constructor: public City(long cityid, long provinceid, String cityname, String postalcode) { } this.cityid = cityid; this.provinceid = provinceid; this.cityname = cityname; this.postalcode = postalcode;
Step 7: Remove Obsolete Injection Open the ApplicantForm.java file in the IDE Remove the following line, because we don t need it anymore: private ProvinceSupport provincesupport; Remove the corresponding getprovincesupport() and setprovincesupport() method, because we don t need it anymore either Open the faces-config.xml file in the IDE Remove the managed-property that injects the provincesupport into the applicantform backing bean: <managed-property> <property-name>provincesupport</property-name> <value>#{provincesupport}</value> </managed-property>
Step 8: Add CitySupport Bean Create a new Java class: training.jobapplication.bean.support.citysupport The code we need to paste is too large, so find the CitySupport.java file in the solutions folder and copy the contents Note the foreign-key relationship with provinceid, and that the provincesupport bean will be injected into the citysupport bean in order to lookup provinceid keys Walk through the filterselectitems() method and look at how the filter is applied
Step 9: Define CitySupport Bean Open the following file in the IDE: jobapplication/web-inf/faces-config.xml Add the following managed-bean and managed-property: <managed-bean> <managed-bean-name>citysupport</managed-bean-name> <managed-beanclass>training.jobapplication.bean.support.citysupport</managedbean-class> <managed-bean-scope>request</managed-bean-scope> <!-- Inject the provincesupport bean into the --> <!-- citysupport bean in order to promote loose coupling --> <managed-property> <property-name>provincesupport</property-name> <value>#{provincesupport}</value> </managed-property> </managed-bean>
Step 10: Specify Injection into Backing Bean Open the faces-config.xml file in the IDE Add the following managed-property to the applicantform backing bean: <!-- Inject the citysupport bean into the --> <!-- backing bean in order to promote loose coupling --> <managed-property> <property-name>citysupport</property-name> <value>#{citysupport}</value> </managed-property> Open the ApplicantForm.java file in the IDE Add the following property: private CitySupport citysupport; Generate a getters and setters for citysupport
Step 11: Run Application Re-publish/deploy the jobapplication project Run the application in the browser Enter a value for First Name, Last Name, Travel Percentage, and Date of Birth Click in the City field and type the letter A Notice that Atlanta and Albany appear Select Atlanta from the list Note that the Province is GA and the Postal Code is 30329 Enter a postal code: 32801 Note that the Province is FL and the City is Orlando
Rich Text Editor Component
Rich Text Editor The h:inputtextarea and ice:inputtextarea render themselves as an HTML <textarea /> tag which provides the user with the ability to enter only plain text The ice:inputrichtext component enables the user to enter rich text like bold, italic, hyperlinks, and bullets:
Implementation The ice:inputrichtext component is currently implemented as a wrapper around the FCKEditor open source project The name comes from the initials of Frederico Caldeira Knabben, the project founder The FCKEditor represents rich text as HTML, and allows the user to click on a Source button to work directly with the underlying HTML if desired
Toolbar Setting the Toolbar <ice:inputrichtext toolbar="#{inputrichtextbean.toolbarmode} /> Toolbar types Default Basic
Language Setting the Language <ice:inputrichtext language="en" /> Available Languages Afrikaans (af) Arabic (ar) Basque (eu) Bengali/Bangla (bn) Bosnian (bs) Bulgarian (bg) Catalan (ca) Chinese Simplified (zh-cn) Chinese Traditional (zh) Croatian (hr) Czech (cs) Danish (da) Dutch (nl) English (en) English (Australia) (en-au) English (Canadian) (en-ca) English (United Kingdom) (en-uk) Esperanto (eo) Estonian (et) Faroese (fo) Finnish (fi) French (fr) Galician (gl) German (de) Greek (el) Hebrew (he) Hindi (hi) Hungarian (hu) Italian (it) Japanese (ja) Khmer (km) Korean (ko) Latvian (lv) Lithuanian (lt) Malay (ms) Mongolian (mn) Norwegian (no) Norwegian Bokmal (nb) Persian (fa) Polish (pl) Portuguese (Brazil) (pt-br) Portuguese (Portugal) (pt) Romanian (ro) Russian (ru) Serbian (Cyrillic) (sr) Serbian (Latin) (sr-latn) Slovak (sk) Slovenian (sl) Spanish (es) Swedish (sv) Thai (th) Turkish (tr) Ukrainian (uk) Vietnamese (vi)
Skins Skins <ice:inputrichtext skin= office2003 /> Available Skins default office2003 silver
Save Button / Submit Behavior The default behavior of the ice:inputrichtext is to only save its data when the save icon is clicked In order to make the ice:inputrichtext participate in normal ICEfaces form submission, the saveonsubmit attribute must be set to true <ice:inputrichtext saveonsubmit= true />
Exercise: Overview The goal of this exercise is to replace the ice:inputtextarea component with an ice:inputrichtext component This will allow the user to enter text like bold, italic, bullets in the resume, rather than simply plain text
Step 1: Replace Component Open the applicantform.xhtml file in the IDE Replace the ice:inputtextarea component with the following markup: <ice:inputrichtext id="resume" saveonsubmit="true" toolbar="basic" width="500" height="200" value="#{applicant.resume}" />
Step 2: Output Submitted Rich Text Open the ApplicantForm.java file in the IDE Add the following line to the submit() method: System.out.println("submit() resume=" + this.applicant.getresume());
Step 3: Run Application Re-publish/deploy the jobapplication project Run the application in the browser Enter First Name: John Enter Last Name: Doe Enter Travel Percentage: 50 Enter Date of Birth: 1/1/1970 Enter Postal Code: 32801 Click Show Resume Enter Rich Text: This is some bold text Click Submit Application Note that the Tomcat console has this HTML fragment as the value for resume: submit() resume=<p>this is some <strong>bold</strong> text</p>
File Upload Component
File Upload Normal HTML forms look like this: <form enctype= application/x-www-form-urlencoded > </form> But when doing file upload, forms look like this: <form enctype= multipart/form-data > </form> The JSF 1.x specification completely ignored the multipart/form-data case additionally, there is no fileupload component provided by the JSF RI Prior to ICEfaces, the only way to intercept these types of postback requests was to implement a PhaseListener
The ice:inputfile Component ICEfaces overcomes the JSF file upload shortcoming by providing an ice:inputfile component The component renders itself as an <iframe> which points to a small HTML fragment that is generated by the ICEfaces servlet The HTML fragment contains markup like this: <input type= file /> This markup will manifest itself in the browser as a text field with a Browse button and an Upload button When the user selects a file and clicks the Upload button, the ICEfaces uploadservlet receives the file data
Progress Indicator The file upload component can be tied to an ice:outputprogress component The progress indicator is updated during the file upload via ICEfaces Ajax Push
Uploaded File After the file upload is complete, the file will exist in the folder specified in the com.icesoft.faces.uploaddirectory init-param in web.xml This can be an absolute or relative folder path If relative, it is relative to the Tomcat working directory for the web application Alternatively, the folder can be specified by the uploaddirectory attribute of the ice:inputfile component See also: uploaddirectoryabsolute and uniquefolder attributes
Exercise: Overview The goal of this exercise is to replace the ice:inputrichtext component with an ice:inputfile component This will allow the user to upload a resume document, rather than typing in a resume in the text area
Step 1: Replace Component Replace the ice:inputrichtext component with the following markup: <ice:inputfile id="resume" actionlistener="#{resumeuploader.actionlistener}" label="#{msgs.uploadresume}" progresslistener="#{resumeuploader.progresslistener}" />
Step 2: Add Progress Indicator and Message Add the following table row markup just above the table row for the ice:inputfile component: <tr> <td> <ice:outputprogress value="#{resumeuploader.fileprogress}" labelcomplete="#{resumeuploader.currentfile.filename}" /> </tr> </td>
Step 3: Modify Model Bean Open the Applicant.java file in the IDE Delete the following line: private String resume; Delete the getresume() and setresume() methods
Step 7: Add FileUpload Utility Bean Create the following utility bean Java class: training.jobapplication.bean.util.fileuploader The size of the source code is too large to copy/paste from slides, so instead, find the file in the solution folder and paste the contents into the IDE This is a general purpose utility bean that can be reused by other ICEfaces web applications
Step 8: Remove Console Output Open the ApplicantForm.java file in the IDE Delete this line: System.out.println("submit() resume=" + this.applicant.getresume());
Step 9: Message Bundle Add the following key+value pair to Msgs_en.properties: uploadresume=upload Resume This will be the label of the upload button
Step 10: Define Managed Beans Paste the following markup into faces-config.xml: <managed-bean> <managed-bean-name>resumeuploader</managedbean-name> <managed-beanclass>training.jobapplication.bean.util.file Uploader</managed-bean-class> <managed-bean-scope>request</managed-beanscope> </managed-bean>
Step 11: Run Application Re-publish/deploy the jobapplication project Run the application in the browser Enter First Name: John Enter Last Name: Doe Enter Travel Percentage: 50 Enter Date of Birth: 1/1/1970 Enter Postal Code: 32801 Click Show Resume Select a file from your local drive