Creating autocomplete entry field with Woodstock


Overview

Woodstock components (https://woodstock.dev.java.net/index.html) provide powerful and flexible set of client side Web components. Like living cells, not only components represent complete functional units by themselves, they can also be connected together to create new forms of functionality.

This document shows how a textField and listBox can be connected together to build a so-called autocomplete entry field – the one that presents to the user dynamic set of completing entered data or suggestions based on what information user is typing.


All sources and Netbeans ( NB 6 Beta 2) project are attached at the end of this document.


For this exercise, we will build an autocomplete entry field that is drawing data from the list of New York Times' “The Best 1,000 Movies Ever Made” that will look like this:



The intended behavior is to change the content of the list box to present only titles that contain typed in string.


Steps:

  1. Think through the intended interactions

  2. Design the entry field by placing textField and listBox next to each other

  3. Code the back-end

  4. Connect textField and listBox



Think through the intended interactions

The following diagram illustrates the simplified interactions/dataflow that we want to accomplish:




  1. When user types into the textField, we want listBox to be refreshed with relevant filtered data. We want server to perform some data processing for that as well.

  2. When user selects data in the listbox, we want this selection to be reflected in the textField so it can be used for submission



Design the entry field


We used Netbeans 6 to place textField and listBox next to each other ( see Page1.jsp):


  • Note that when grid placement is used on the Netbeans design surface, it automatically creates a space between any two components, so we modified styles “top” position of the list box to 'attach' it to the textField.


<webuijsf:textField binding="#{Page1.tf}"

columns="60" id="tf"

style="position: absolute; left: 144px; top: 93px; width: 120px; height: 24px" text="#{Page1.filter}"/>

<webuijsf:listbox binding="#{Page1.listbox1}" id="listbox1" items="#{Page1.listbox1DefaultOptions.options}"

rows="10" style="position: absolute; left: 144px; top: 112px; width: 120px; height: 48px"/>



Code the back-end

When components are placed on the design surface, Netbeans automatically creates JSF server binding for the component. By default, it uses DefaultOptionsList as a data binding for the listBox. DefaultOptionsList provides simple data set, and we will be replacing it with custom class FilteredOptions.

Responsibilities of FilteredOptions class are:

  • load data from persistence ( in this example, we load data from bundle movies.properties)

  • filter data according to the filter provided

  • sort data

  • provide data in suitable to listBox form of Option[]

See FilteredOptions.java for details. Note that we isolated filtering of the data from getOptions(). The reason is that during miscellaneous JSF lifecycles method getOptions() may be called several times for the same request. Since filtering data can potentially be a resource-intensive procedure, it would be undesirable to perform it when unnecessary. Thus data filtering is done once(when committing data from textField) in Page1.java :


public void setFilter(String value) {

this.filter = value;

listbox1DefaultOptions.filter(filter);

}



Connect textField and listBox

And finally we need to wire together the communication on the client side ( browser)

First, we will make keyUp event of the text field to commit textField data and update the listbox:


<webuijsf:textField binding="#{Page1.tf}"

onKeyUp="document.getElementById('form1:listbox1').refresh('form1:tf'); "

columns="60" id="tf"

style="position: absolute; left: 144px; top: 93px; width: 120px; height: 24px" text="#{Page1.filter}"/>


Note that refresh(id1, id2,..) function does 2 things:

  1. it submits ( by Ajax call) fields with id1, id2. In our case we supply id of the textField, which means that textField value will be submitted first.

  2. It refreshes ( by Ajax call) the field upon which it was called. In our case document.getElementById('form1:listbox1') represents the listBox.


That is it for this part. Now any character typed will cause TextField to submit and ListBox to refresh from the server data!


Next, we want textField to be updated with the full title when the title is clicked upon within the lisbox.


<webuijsf:listbox binding="#{Page1.listbox1}" id="listbox1" items="#{Page1.listbox1DefaultOptions.options}"

onChange="document.getElementById('form1:tf').setProps( {value: document.getElementById('form1:listbox1').getSelectedValue() } ); "

rows="10" style="position: absolute; left: 144px; top: 112px; width: 120px; height: 48px"/>

In the above javascript, we are using 2 functions :

  • setProps() - this function is common across all of the client side components, and is to be used to set 1 or more properties on the component. In this case, we are setting value of the textField

  • getSelectedValue() - function exposed by listBox ( see TLD documentation)



Resources

Complete Netbeans 6 Beta 2 project
Complete Netbeans 6 Beta 2 project for Woodstock 4.1.1
Make sure to compile the project before opening pages in the NB visual designer

The End

Comments:

Thanks for providing this. This is a really useful example as examples of the Ajax and client side support are few and the documentation is a little hard to follow. A full working example really pulls it all together.

Posted by Brett Bergquist on October 30, 2007 at 01:09 PM MDT #

Dmitry, from running the attached project and sprinkling some debug statements, I see that the whole lifecycle of the page is performed (construction, init, preprocess, prerender, destroy).

In a complicated page with many UI components, there might be things that are time consuming to perform that one might not want to perform on an ajax postback such as this. Is this a valid concern and if so, is there anyway to detect that the postback is ajax related?

Posted by Brett Bergquist on October 30, 2007 at 10:43 PM MDT #

Brett,
In the case of JSF backend, Ajax submission does not eliminate all the lifecycles, but allows to perform them only for specified element. Thus only one element will be processed through all these cycles - and logically that makes perfect sense.

It is certainly a valid concern to be cognizant of extra load on that type of Ajax calls, and developer can control that. For example, if you take a look at woodstock's com.sun.webui.jsf.util.ComponentUtilities, we provide easy util functions isAjaxRequest(..) to detect Ajax call, so that special processing can be provided when needed. For instance, here is how com.sun.webui.jsf.component.TextField component skips update lifecycle ( processUpdates) in case of validation Ajax call:

// Skip processing in case of "validate" ajax request.
if (ComponentUtilities.isAjaxRequest(getFacesContext(), this, "validate")) {
return;
}

Posted by dmitry on October 31, 2007 at 05:37 AM MDT #

Dmitry, thanks for pointing out the ComponentUtilities. I don't think I would have found that.

Last night when testing with my own application and trying to migrate over from using the Blueprints ProgressBar to the Woodstock ProgressBar, I was seeing some strange things. I was seeing DropDown components have their ValueChange method invoked during the Ajax call of the ProgressBar. This led me down the path of looking at what was going on with the lifecycle of these calls. This is definitely different, but better. What I did find, and based on an email that you wrote on another list (maybe the Woodstock list), I saw that I was missing the:

javax.faces.LIFECYCLE_ID
com.sun.faces.lifecycle.PARTIAL

init-param's in my web.xml (this is an application that is about 9 months old) and this may be related to the strange behavior that I was seeing.

One of the things that we do is to do cross checking and updating of Component state (rendered, disabled, etc.), in the prerender method of a VWP. This is convenient because at this point, the model has been updated and all of the values can be checked simultaneously. Previously we had done some of these things in value change handlers but ran into problems where we were testing against model values that had not been updated.

So in prerender, there may things that I don't want to do if this is an Ajax postback from a ProgressBar for example. This should give me a way to not do these things.

Thanks again and thanks for taking the time to write back.

Brett

Posted by Brett Bergquist on October 31, 2007 at 11:41 AM MDT #

Is it possible to obtain the same result using a table component instead of a listbox component ?
Thank you

Posted by luke on November 19, 2007 at 11:34 PM MST #

How would you use this technique to refresh several labels or text fields when the selected item of a listbox changes?

Posted by Glenn Holmer on December 15, 2007 at 12:22 PM MST #

seems that this only work with woodstock 4.1 but not 4.1.1

Posted by gary ng on December 30, 2007 at 10:03 AM MST #

Same problem here - it isn't working with Woodstock 4.1.1 (from the current Netbeans update).

Posted by jiai on January 10, 2008 at 05:36 AM MST #

i will update the src code to work with Woodstock 4.1.1 and post the update when ready

Posted by dmitry on January 23, 2008 at 08:38 AM MST #

I have added the NB project that work for Woodstock 4.1.1 - please let me know if you have any problems

Posted by guest on January 28, 2008 at 01:52 PM MST #

good one

Posted by guest on February 04, 2008 at 12:22 AM MST #

Dmitry
The code is quite clear and it works with Woodstock 4.1.1 and NB 6.0.1. I've been trying to implement the Blueprints' autocomplete behaviour: when the mouse is over the textfield of it has the focus, the list be visible and after selection or after some time get it hidden. I am using these functions:

function ref(){ // onKeyUp
showList(3000);
document.getElementById('form1:ps1:s1:p1:listbox1').refresh('form1:ps1:s1:p1:tf');
}

function showList(delay){
document.getElementById('form1:ps1:s1:p1:listbox1').setProps({visible: true});
if(temporizador!=null){
clearTimeout(temporizador);
temporizador=null;
}
temporizador=window.setTimeout('hideList();',delay);
}

function hideList(){
document.getElementById('form1:ps1:s1:p1:listbox1').setProps({visible: false});
}

function selectedFromList(){//when list value clicked
document.getElementById('form1:ps1:s1:p1:tf').setProps( {value: document.getElementById('form1:ps1:s1:p1:listbox1').getSelectedValue() } );
showList(3000);
}

There is one problem with the visible property of listbox: if checked at design time, the first time the page is rendered, the list is shown, and it shouldn't; if not checked at design time, after typing some characters the list becames hidden after receiving the asynch response.

Previous code show components inside a PropertySheet. There is a little problem related to the component ids: you have to read the rendered page source code or use a tool like firebug to know the assigned id to each component.

Best regards

Posted by Aperezymadrid on February 09, 2008 at 01:41 AM MST #

tete

Posted by guest on February 20, 2008 at 08:47 PM MST #

Hello, first pardon by my English.
It had a problem when String i set in optinos had characters like ' ñ' or ' á', the solution was to codify strings with URLEncoder.encode(). The problem is that in listbox it appears to me the codified text like "Hola+Mundo" or like "Juan+Ram%F31n". How I can decode ajax response after resfresh() to obtain "Juan Ramón" or "Hola Mundo".

thanks.

Posted by Juan Ramón on February 24, 2008 at 10:18 PM MST #

okkkkkkkkkkkkkk

Posted by guest on March 03, 2008 at 03:40 AM MST #

I am working with NetBeans 6 Woodstock 4.2 and could not get the above projects to run properly. What I learned from having a look at the content of the project files is that the ApplicationBean1.java, SessionBean1.java and RequestBean1.java classes have not been edited. Am I right when I conclude that the entire autocomplete functionality is implemented in the FilteredOptions.java and Page1.java classes? What kind of files are the Bundle.properties and movies.properties? I suppose they only provide the data? I would like to populate the listbox1DefaultOptions with data from a database tabel, however I cannot quite figure out how to do so. Could someone provide me with a working example, or at least point me in the right direction.

Kind regards,
Annet.

Posted by Annet Vermeer on March 13, 2008 at 05:30 AM MDT #

Hello all,

Please use mailing lists for questions :https://woodstock.dev.java.net/servlets/ProjectMailingListList

I do not monitor this page, so mailing list will probably get you an answer faster...

Secondly, please keep in mind that source code provided here is just an example, intended for sharing experience. It may have bugs ( or may not). Similar communication between widgets can be accomplished for any set of Woodstock widgets - such as table, hyperlink etc. All of the server business logic is in FilteredOptions and Page1.java

Finally, Woodstock 4.3 release has autocomplete functionality embedded into textField.

Posted by dmitry on April 17, 2008 at 02:59 PM MDT #

Great post and draw. Thank you for sharing.

Posted by links of london jewellery on November 23, 2009 at 11:40 AM MST #

<a
href="http://www.linksoflondonhut.co.uk/"><strong>links of london jewellery</strong></a> is loved by most fashionable ladies all over the world, they all choose some other <a
href="http://www.linksoflondonhut.co.uk/Linksoflondon_Category_5.html"><strong>links
of london bangles</strong></a> also with some <a
href="http://www.linksoflondonhut.co.uk/Linksoflondon_Category_2.html"><strong>links
of london charms</strong></a>.

Posted by links of london jewellery on February 05, 2010 at 04:44 PM MST #

She has found that single motherhood "can be okay. I feel like I've learned so much. The routine [of marriage] can kill me. That becomes a difficult balance, too, because I feel like my son needs his routine, but for me I need to step out of my routine. I haven't figured it all out yet." christian louboutin
A close-knit circle of girlfriends, including 90210 star Sara Foster and video producer Juliana Roberts, helps keep Kate grounded. "I don't know what I'd do without my girlfriends," she says. "Let's be honest, I don't care how much you're in love with any man, you need to have your girlfriends to talk to. Without them, we're alone. I don't want to talk to a man about some of the things I feel." christian louboutin shoes
Her thoughts on plastic surgery likely fall into that girls-only category. "If I need to go under the knife," Kate says, "I'm the first one to say I should. But nowadays when you go into a dermatologist's office, they have so many things. What else are they going to come up with? We're gonna end up going into a tank one day and coming out with, like, the perfect face," she says, laughing. christian shoes
Meanwhile, her career has continued to flourish. And now Nine (which stars a powerhouse of talents, including Daniel Day-Lewis, Penélope Cruz, Nicole Kidman, Sophia Loren, and Judi Dench), which casts Kate as Stephanie Necrophuros, a magazine editor and sexpot, promises to show audiences a whole new side to her. "Kate's a life force," Kidman says. "I think what's compelling about her is that she truly sparkles." louboutin shoes
Kate sings and dances in the film -- a first for her. "I love it," she says. Asked to show off her skills, she laughs and then breaks out into a few bars of the Aretha Franklin classic "Ain't No Way." Her voice is melodic and sure. "I'd like to do more musical theater," she says.

Posted by christian louboutin on March 11, 2010 at 06:17 PM MST #

Dear Sir,

If time permits, Please advise in setting multiple items(for example 1st, 3rd and 5th items) selected of a webuijsf:listbox from the backing bean page’s pre-render method.

I am using Netbeans 6.5 IDE.

I Congratulate for your significant contributions for NetBeans Community.

Thanks & Regards,

ARUMUGAM A.V

Posted by ARUMUGAM A.V on January 18, 2011 at 04:16 PM MST #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Dmitry Kushner

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today