Home | | Internet & World Wide Web HOW TO PROGRAM | | Internet Programming | | Web Programming | AutoComplete Text Field and Virtual Forms

Chapter: Internet & World Wide Web HOW TO PROGRAM - Rich Internet Application Server Technologies - Ajax-Enabled JavaServer Faces Web Applications

| Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail |

AutoComplete Text Field and Virtual Forms

We demonstrate the AutoComplete Text Field component from the BluePrints catalog by modifying the form in our AddressBook application.

AutoComplete Text Field and Virtual Forms


We demonstrate the AutoComplete Text Field component from the BluePrints catalog by modifying the form in our AddressBook application. The AutoComplete Text Field pro-vides a list of suggestions as the user types. It obtains the suggestions from a data source, such as a database or web service. Eventually, the new form will allow users to search the address book by last name, then first name. If the user selects a contact, the application will display the contact’s name and address on a map of the neighborhood. We build this form in two stages. First, we’ll add the AutoComplete Text Field that will display sugges-tions as the user types a contact’s last name. Then we’ll add the search functionality and map display in the next step.


Adding Search Components to the AddressBook.jsp Page

Using the AddressBook application from Section 27.2, drop a Static Text component named searchHeader below addressesTable. Change its text to "Search the address book by last name:" and change its font size to 18px. Now drag an AutoComplete Text Field component to the page and name it nameAutoComplete. Set this field’s required property to true. Add a Label named nameSearchLabel containing the text "Last name:"

to the left of the AutoComplete Text Field. Finally, add a button called lookUpButton with the text Look Up to the right of the AutoComplete Text Field.


1. Configuring Virtual Forms


Virtual forms are used when you would like a button to submit a subset of the page’s input fields to the server. Recall that the Table’s internal virtual forms were enabled so that click-ing the pagination buttons would not submit any of the data in the Text Fields used to add a contact to the AddressBook database. Virtual forms are particularly useful for displaying multiple forms on the same page. They allow you to specify a submitter component and one or more participant components for a form. When the virtual form’s submitter com-ponent is clicked, only the values of its participant components will be submitted to the server. We use virtual forms in our AddressBook application to separate the form for add-ing a contact to the AddressBook database from the form for searching the database.


To add virtual forms to the page, right click the Submit button on the upper form and choose Configure Virtual Forms… from the popup menu to display the Configure Virtual Forms dialog. Click New to add a virtual form, then click in the Name column and change the new form’s name to addForm. Double click the Submit column and change the option to Yes to indicate that this button should be used to submit the addForm virtual form. Click OK to exit the dialog. Next, select all the Text Fields used to enter a contact’s infor-mation in the upper form. You can do this by holding the Ctrl key while you click each Text Field. Right click one of the selected Text Fields and choose Configure Virtual Forms…. In the Participate column of the addForm, change the option to Yes to indicate that the values in these Text Fields should be submitted to the server when the form is submitted. Click OK to exit.


Repeat the process described above to create a second virtual form named searchForm for the lower form. Figure 27.10 shows the Configure Virtual Forms dialog after both virtual forms have been added. The Look Up Button should submit the searchForm, and nameAu-toComplete should participate in the searchForm. Next, return to Design mode and click the Show Virtual Forms button (  ) at the top of the Visual Designer panel to display a legend of the virtual forms on the page. Your virtual forms should be configured as in Fig. 27.11. The Text Fields outlined in blue participate in the virtual form addForm. Those outlined in green participate in the virtual form searchForm. The components outlined with a dashed line submit their respective forms. A color key is provided at the bottom right of the Design area so that you know which components belong to each virtual form.


2. JSP File with Virtual Forms and an AutoComplete Text Field


Figure 27.12 presents the JSP file generated by Netbeans for this stage of the AddressBook application. A new tag library is specified in the root element ( xmlns:bp="http://

 java.sun.com/blueprints/ui/14"; line 5). This is the BluePrints catalog library that provides Ajax-enabled components such as the AutoComplete Text Field component. We focus only on the new features of this JSP.


Lines 22–25 configure the virtual forms for this page. Lines 147–151 define the Auto-Complete Text Field component. This component’s completionMethod attribute is bound to the page bean’s nameAutoComplete_complete method (discussed in Section 27.4.3), which provides the list of options the AutoComplete Text Field component should suggest. To create this method, right click the nameAutoComplete component in Design view and select Edit Event Handler > complete. Notice that the Look Up button (lines 155–157) does not specify an action-handler method binding; we’ll add this in Section 27.5.


5     <?xml version="1.0" encoding="UTF-8"?>


6     <!-- Fig. 27.12: AddressBook.jsp -->


7     <!-- AddressBook JSP with an add form and a Table JSF component. -->


8     <jsp:root version="1.2"


9           xmlns:bp="http://java.sun.com/blueprints/ui/14"


10        xmlns:f="http://java.sun.com/jsf/core"


11        xmlns:h="http://java.sun.com/jsf/html"


12        xmlns:jsp="http://java.sun.com/JSP/Page"


13        xmlns:webuijsf="http://www.sun.com/webui/webuijsf">


10        <jsp:directive.page contentType="text/html;charset=UTF-8"


11        pageEncoding="UTF-8"/>


12        <f:view>


13        <webuijsf:page binding="#{AddressBook.page1}" id="page1">


14        <webuijsf:html binding="#{AddressBook.html1}" id="html1">


15        <webuijsf:head binding="#{AddressBook.head1}" id="head1">


16        <webuijsf:link binding="#{AddressBook.link1}" id="link1"

17        url="/resources/stylesheet.css"/>


18        </webuijsf:head>


19        <webuijsf:body binding="#{AddressBook.body1}" id="body1"



20        style="-rave-layout: grid">

21        <webuijsf:form binding="#{AddressBook.form1}" id="form1"

22                    virtualFormsConfig="addForm | zipTextField lnameTextField        

23                    fnameTextField streetTextField cityTextField          

24                    stateTextField | submitButton , searchForm |

25                    nameAutoComplete | lookUpButton">         

26        <webuijsf:staticText binding="#{AddressBook.staticText1}"

27                    id="staticText1" style="font-size: 18px; left: 24px;

28                    top: 24px; position: absolute"

29                    text="Add a contact to the address book:"/>

30        <webuijsf:label binding="#{AddressBook.fnameLabel}"

31                    for="fnameTextField" id="fnameLabel" style="position:

32                    absolute; left: 24px; top: 72px" text="First name:"/>

33        <webuijsf:textField binding="#{AddressBook.fnameTextField}"

34                    id="fnameTextField" maxLength="30" required="true"

35                    style="left: 100px; top: 72px; position: absolute;

36                    width: 192px"/>

37        <webuijsf:label binding="#{AddressBook.lnameLabel}"

38                    for="lnameTextField" id="lnameLabel" style="left: 312px;

39                    top: 72px; position: absolute" text="Last name:"/>

40        <webuijsf:textField binding="#{AddressBook.lnameTextField}"

41                    id="lnameTextField" maxLength="30" required="true"

42                    style="left: 390px; top: 72px; position: absolute;

43                    width: 214px"/>

44        <webuijsf:label binding="#{AddressBook.streetLabel}"

45                    for="streetTextField" id="streetLabel" style="position:

46                    absolute; left: 24px; top: 96px" text="Street:"/>

47        <webuijsf:textField binding=

48                    "#{AddressBook.streetTextField}" id="streetTextField"

49                    maxLength="150" required="true" style="left: 100px;

50                    top: 96px; position: absolute; width: 504px"/>

51        <webuijsf:label binding="#{AddressBook.cityLabel}"

52                    for="cityTextField" id="cityLabel" style="left: 24px;

53                    top: 120px; position: absolute" text="City:"/>

54        <webuijsf:textField binding="#{AddressBook.cityTextField}"

55                    id="cityTextField" maxLength="30" required="true"

56                    style="left: 100px; top: 120px; position: absolute;

57                    width: 240px"/>

58        <webuijsf:label binding="#{AddressBook.stateLabel}"

59                    for="stateTextField" id="stateLabel" style="left: 360px;

60                    top: 120px; position: absolute" text="State:"/>

61        <webuijsf:textField binding="#{AddressBook.stateTextField}"

62        id="stateTextField" maxLength="2" required="true"

63        style="left: 412px; top: 120px; position: absolute;

64        width: 48px"/>

65        <webuijsf:label binding="#{AddressBook.zipLabel}"

66        for="zipTextField" id="zipLabel" style="left: 490px;

67        top: 120px; position: absolute" text="Zip:"/>

68        <webuijsf:textField binding="#{AddressBook.zipTextField}"

69        id="zipTextField" maxLength="5" required="true"

70        style="left: 534px; top: 120px; position: absolute;

71        width: 70px"/>

72        <webuijsf:button actionExpression=

73        "#{AddressBook.submitButton_action}" binding=

74        "#{AddressBook.submitButton}" id="submitButton" primary=

75        "true" style="left: 100px; top: 168px; position:

76        absolute; width: 100px" text="Submit"/>

77        <webuijsf:button binding="#{AddressBook.clearButton}"

78        id="clearButton" reset="true" style="left: 215px; top:

79        168px; position: absolute; width: 100px" text="Clear"/>

80        <webuijsf:messageGroup binding=

81        "#{AddressBook.messageGroup1}" id="messageGroup1"

82        showGlobalOnly="true" style="left: 624px; top: 72px;

83        position: absolute"/>

84        <webuijsf:table augmentTitle="false" binding=

85        "#{AddressBook.addressesTable}" id="addressesTable"

86        paginateButton="true" paginationControls="true"

87        style="left: 24px; top: 216px; position: absolute"

88        title="Contacts" width="816">

89        <webuijsf:tableRowGroup binding=

90        "#{AddressBook.tableRowGroup1}" id="tableRowGroup1"

91        rows="5" sourceData=

92        "#{AddressBook.addressesDataProvider}"

93        sourceVar="currentRow">

94        <webuijsf:tableColumn binding=

95        "#{AddressBook.fnameColumn}" headerText=

96        "First Name" id="fnameColumn"

97        sort="ADDRESSES.FIRSTNAME">

98        <webuijsf:staticText binding=

99        "#{AddressBook.staticText2}" id="staticText2"

100      text="#{currentRow.value[


102      </webuijsf:tableColumn>

103      <webuijsf:tableColumn binding=

104      "#{AddressBook.lnameColumn}"

105      headerText="Last Name" id="lnameColumn"

106      sort="ADDRESSES.LASTNAME">

107      <webuijsf:staticText binding=

108      "#{AddressBook.staticText3}" id="staticText3"

109      text="#{currentRow.value[

110      'ADDRESSES.LASTNAME']}"/>

111      </webuijsf:tableColumn>

112                  <webuijsf:tableColumn binding=                  

113                  "#{AddressBook.streetColumn}" headerText="Street"

114                  id="streetColumn" sort="ADDRESSES.STREET">            

115                  <webuijsf:staticText binding=                       

116                  "#{AddressBook.staticText4}" id="staticText4"

117                  text="#{currentRow.value[               

118                  'ADDRESSES.STREET']}"/>                       

119                  </webuijsf:tableColumn>                  

120                  <webuijsf:tableColumn binding=                  

121                  "#{AddressBook.cityColumn}" headerText="City"

122                  id="cityColumn" sort="ADDRESSES.CITY">                   

123                  <webuijsf:staticText binding=                       

124                  "#{AddressBook.staticText5}" id="staticText5"

125                  text="#{currentRow.value['ADDRESSES.CITY']}"/>

126                  </webuijsf:tableColumn>                  

127                  <webuijsf:tableColumn binding=                  

128                  "#{AddressBook.stateColumn}" headerText="State"

129                  id="stateColumn" sort="ADDRESSES.STATE">               

130                  <webuijsf:staticText binding=                       

131                  "#{AddressBook.staticText6}" id="staticText6"

132                  text="#{currentRow.value['ADDRESSES.STATE']}"/>

133                  </webuijsf:tableColumn>                  

134                  <webuijsf:tableColumn binding=                  

135                  "#{AddressBook.zipColumn}" headerText="Zip"

136                  id="zipColumn" sort="ADDRESSES.ZIP" width="106">

137                  <webuijsf:staticText binding=                       

138                  "#{AddressBook.staticText7}" id="staticText7"

139                  text="#{currentRow.value['ADDRESSES.ZIP']}"/>

140                  </webuijsf:tableColumn>                  

141                  </webuijsf:tableRowGroup>             

142      </webuijsf:table>                   

143      <webuijsf:staticText binding="#{AddressBook.searchHeader}"

144                  id="searchHeader" style="font-size: 18px; left: 24px;

145                  top: 420px; position: absolute"                      

146                  text="Search the address book by last name:"/>                   

147                  <bp:autoComplete binding="#{AddressBook.nameAutoComplete}"         

148                  completionMethod=              

149                  "#{AddressBook.nameAutoComplete_complete}"              

150                  id="nameAutoComplete"                  

151                  style="left: 96px; top: 444px; position: absolute"/>  

152      <webuijsf:label binding="#{AddressBook.label1}"             

153                  for="nameAutoComplete" id="label1" style="left: 24px;

154                  top: 447px; position: absolute" text="Last name:"/>

155      <webuijsf:button binding="#{AddressBook.lookUpButton}"

156                  id="lookUpButton" style="left: 288px; top: 446px;

157                  position: absolute; width: 100px" text="Look Up"/>

158      </webuijsf:form>


159      </webuijsf:body>


160      </webuijsf:html>


161      </webuijsf:page>


162      </f:view>


163      </jsp:root>

Fig. 27.12 | AddressBook JSP with an AutoComplete Text Field component.


3. Providing Suggestions for an AutoComplete Text Field


Figure 27.13 displays the page bean file for the JSP in Fig. 27.12. It includes the method nameAutoComplete_complete, which provides the functionality for the AutoComplete Text Field. Otherwise, this page bean is identical to the one in Fig. 27.8.


24  // Fig. 27.13: AddressBook.java


25  // Page bean for AddressBook.jsp.


26  package addressbook;


31  import com.sun.data.provider.RowKey;


32  import com.sun.data.provider.impl.CachedRowSetDataProvider;


33  import com.sun.j2ee.blueprints.ui.autocomplete.AutoCompleteComponent;


34  import com.sun.j2ee.blueprints.ui.autocomplete.CompletionResult;


35  import com.sun.rave.web.ui.appbase.AbstractPageBean;


36    import com.sun.webui.jsf.component.Body;


37    import com.sun.webui.jsf.component.Button;


38    import com.sun.webui.jsf.component.Form;


39    import com.sun.webui.jsf.component.Head;


40    import com.sun.webui.jsf.component.Html;


41    import com.sun.webui.jsf.component.Label;

38    import com.sun.webui.jsf.component.Link;


39    import com.sun.webui.jsf.component.MessageGroup;


40    import com.sun.webui.jsf.component.Page;


41    import com.sun.webui.jsf.component.StaticText;


42    import com.sun.webui.jsf.component.Table;


43    import com.sun.webui.jsf.component.TableColumn;


44    import com.sun.webui.jsf.component.TableRowGroup;


45    import com.sun.webui.jsf.component.TextField;


46    import com.sun.webui.jsf.model.DefaultTableDataProvider;


47    import javax.faces.FacesException;


48    import javax.faces.context.FacesContext;


45    public class AddressBook extends AbstractPageBean

46    {


47          // To save space, we omitted the code in lines 30-625. The complete


48          // source code is provided with this chapter's examples.


52           // action handler for the autocomplete box that fetches names


53           // from the address book whose prefixes match the letters typed so far


54           // and displays them in a suggestion list.


55           public void nameAutoComplete_complete(


56                  FacesContext context, String prefix, CompletionResult result )

57           {

58                  try

59                  {


60                        boolean hasNext = addressesDataProvider.cursorFirst();


59                        while ( hasNext )

60                        {


61                              // get a name from the database


String name =


(String) addressesDataProvider.getValue(                


641      "ADDRESSES.LASTNAME" ) + ", " +                   

642      (String) addressesDataProvider.getValue(                

643      "ADDRESSES.FIRSTNAME" ) ;                


645      // if the name in the database starts with the prefix,


646      // add it to the list of suggestions


647      if ( name.toLowerCase().startsWith( prefix.toLowerCase() ) )

648      {


result.addItem( name );

650      } // end if

651      else

652      {



653      // terminate the loop if the rest of the names are

654      // alphabetically less than the prefix

655      if ( prefix.compareTo( name ) < 0 )

656      {

657      break;

658      } // end if

659      } // end else


                                                //          move cursor to next row of database             

662                                          hasNext = addressesDataProvider.cursorNext();                  

663                              } // end while 

664                  }          // end   try       

665                  catch ( Exception ex )

666                  {                                                         

667                              result.addItem( "Exception getting matching names." );       

668                  }          // end   catch   

669                  } //       end method nameAutoComplete_complete  

670      } // end class    AddressBook 


Fig. 27.13 | Page bean that suggests names in the AutoComplete Text Field.

Method nameAutoComplete_complete (lines 629–669) is invoked after every key-stroke in the AutoComplete Text Field to update the list of suggestions based on the text the user has typed so far. The method receives a string (prefix) containing the text the user has entered and a CompletionResult object (result) that is used to display sugges-tions to the user. The method loops through the rows of the addressesDataProvider, retrieves the name from each row, checks whether the name begins with the letters typed so far and, if so, adds the name to result. Line 634 sets the cursor to the first row in the data provider. Line 636 determines whether there are more rows in the data provider. If so, lines 639–643 retrieve the last name and first name from the current row and create a String in the format last name, first name. Line 647 compares the lowercase versions of name and prefix to determine whether the name starts with the characters typed so far. If so, the name is a match and line 649 adds it to result.


Recall that the data provider wraps a CachedRowSet object that contains a SQL query which returns the rows in the database sorted by last name, then first name. This allows us to stop iterating through the data provider once we reach a row whose name comes alphabetically after the text entered by the user—names in the rows beyond this will all be alphabetically greater and thus are not potential matches. If the name does not match the text entered so far, line 655 tests whether the current name is alphabetically greater than the prefix. If so, line 657 terminates the loop.

If the name is neither a match nor alphabetically greater than prefix, then line 662 moves the cursor to the next row in the data provider. If there is another row, the loop iterates again, checking whether the name in the next row matches the prefix and should be added to results.


Lines 665–668 catch any exceptions generated while searching the database. Line 667 adds text to the suggestion box indicating the error to the user.

Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail

Copyright © 2018-2020 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.