Combobox with textChange listener does not update item list

Hi,

I want to create an AutoCompleter that loads locations from a database and shows them - based on the first letter(s) a user enters.
My problem is, that items, that are added after keys are entered, will not be shown.
This is my very simplified code:


public class AutoCompleterComponent extends ComboBox implements ValueChangeListener,TextChangeListener 
{

  public static final int MAXLOCS = 3;
  
  //this is a sample
  public static String[] locations = {
	  "Adendorf","Amelinghausen",
	  "Bardowick","Babelin",
	  "Berlin","Berlingen","Dorfen","Erding","Eppendorf",
	  "Essen","Esslingen","Frankfurt","Friedrichshafen","Freiburg",
	  "Flensburg","Flieden","Flintbek","Frechen","Freiberg"}; //...

  private String enteredString;
  
  public AutoCompleterComponent(String caption,String inputPrompt)
  {
    super(caption);
    setInputPrompt(inputPrompt);
    setWidth(350.0f,Unit.PIXELS); 
    setFilteringMode(FilteringMode.STARTSWITH);  
    setImmediate(true);

    //setNullSelectionAllowed(false);
    addValueChangeListener(this); //activated if item is selected
    addListener(TextChangeListener.EVENT_ID, TextChangeEvent.class, this, TextChangeListener.EVENT_METHOD);
  }
  
  @Override
  public void changeVariables(Object source, Map<String, Object> variables) 
  {
      if (variables.containsKey("filter")) 
      {
          final String text = variables.get("filter").toString();
          fireEvent(new FieldEvents.TextChangeEvent(this) {

              @Override
              public String getText() {
                  return text;
              }

              @Override
              public int getCursorPosition() {
                  return text.length();
              }
          });
      }
      super.changeVariables(source, variables);
  }

  /**
   * a key is pressed
   */
  public void textChange(TextChangeEvent event)
  {
    
    final String valueString = event.getText();
	System.out.println("text changed to:"+valueString);
    setLocationsFromSubstring(valueString);
    //the items have changed but it is not noticed by the componenet 
    commit();  //does not help
    markAsDirty(); //does not help
  }
  
  /**
   * is called when item has been chosen
   */
  public void valueChange(ValueChangeEvent event)
  {
    System.out.println("value changed");
  }

  /**
   * Get locations based on the first letter(s) the user has typed. 
   * 
   * This is a simplification. 
   * normally we would do an SQL query to get some suitable locations from a huge table
   * @param valueString first letters of a location
   */
  private void setLocationsFromSubstring(String valueString) 
  {
  
      removeAllItems(); //clear the item list
      commit();
	  enteredString = valueString.toLowerCase().trim();
      
      for (int i=0;i<locations.length;i++)
      {
    	  
    	  if (locations[i]
.toLowerCase().startsWith(enteredString))
    	  {
    		  addItem(new String(locations[i]
));
    		  System.out.println("added location:"+locations[i]
);
    		  if (size()>MAXLOCS) break;
    	  }
    }
    System.out.println("locations size:"+size()); 

  } //getLocationsFromSubstring
  
}

if I enter a first letter, it does work. if I enter a second letter like “fl” the item list is set correctly but no changes (new Items) are displayed.
Any suggestions, why it does not work? Maybe a ComboBox is generally not a good solution to handle this?

You should create a container extending
IndexedContainer
. Below code might help you.


//initialize combobox
combo= new ComboBox();
combo.setFilteringMode(FilteringMode.STARTSWITH);
combo.setTextInputAllowed(true);
combo.setImmediate(true);
combo.setNullSelectionAllowed(true);
combo.setItemCaptionMode(ItemCaptionMode.PROPERTY);
combo.setItemCaptionPropertyId(PropertyId); //should set
combo.setContainerDataSource(new CustomLazyContainer(2, PropertyId));

//initialize container

private final int prefixSize;
private final String setPropertyId;
private String filterString;

public CustomLazyContainer(int prefixSize, String propertyId)
{
....
}

@Override
	public void addContainerFilter(Filter filter) throws UnsupportedFilterException
	{
		if (filter == null)
		{
			removeAllItems();
			filterString = null;
			return;
		}

		removeAllItems();

		if (filter instanceof SimpleStringFilter)
		{
			String newFilterString = ((SimpleStringFilter) filter).getFilterString();

			if (newFilterString == null)
				return;

			if (newFilterString.equals(filterString))
				return;

			filterString = newFilterString;

			if (filterString.length() < prefixSize)
				return;

			doFilter();
			super.addContainerFilter(filter);
		}
	}

private void doFilter()
{
    .....
//fetch from database according filterString and Set PropertyId
// and add items to container by addItem method
}

oh, no need for a textchangelistener…
Thanks a lot, with your help it works now.

You’re welcome