views:

56

answers:

0

I have multiple selectInputText controls inside a datatable, something like this:

<ice:dataTable id="attributesList" value="#{myForm.myAttributes}" var="entry" cellpadding="0" rows="9999" columnClasses="myColumn,myColumn">
  <ice:column>
    <!-- auto-complete -->
    <ice:panelGroup>
      <ice:selectInputText rows="15" width="120" maxlength="255" value="#{entry.attribute.stringValue}" valueChangeListener="#{myFieldAutocomplete.updateList}" immediate="true">
        <f:selectItems value="#{myFieldAutocomplete.list}" />
        <f:attribute name="fieldName" value="#{entry.name}" />
      </ice:selectInputText>
    </ice:panelGroup>
  </ice:column>
</ice:dataTable>

My backing bean code is this:

public class myFieldAutocomplete {

   // default value, empty string
   private String currentFieldValue = "";

   // list of possible matches.
   private List<SelectItem> matchesSIList = new ArrayList<SelectItem>();

   public void updateList(ValueChangeEvent event) {
      currentFieldValue = "";
      // get a new list of matches.
      setMatches(event);

      if (event.getComponent() instanceof SelectInputText) {
         SelectInputText autoComplete = (SelectInputText) event.getComponent();
         if (autoComplete.getSelectedItem() != null) {
            currentFieldValue = (String) autoComplete.getSelectedItem().getValue();
         }
         else {
            String tempValue = getMatch(autoComplete.getValue().toString());
            if(tempValue != null) {
               currentFieldValue = tempValue;
            }
         }
      }
   }

   public String getCurrentFieldValue() {
      return currentFieldValue;
   }

   public List<SelectItem> getList() {
       return matchesSIList;
   }

   private String getMatch(String value) {
      String result = null;
      if (matchesSIList != null) {
          String str;
          Iterator<SelectItem> itr = matchesSIList.iterator();
          while (itr.hasNext()) {
              SelectItem si = (SelectItem) itr.next();
              str = (String) si.getValue();
              if (str.startsWith(value)) {
                  result = str;
                  break;
              }
          }
      }
      return result;
   }

   public void setMatches(ValueChangeEvent event) {
      List<String> newMatchesStrList = new ArrayList<String>();
      if (event.getComponent() instanceof SelectInputText) {
         SelectInputText autoComplete = (SelectInputText) event.getComponent();
         myClassDAO myDao = (myClassDAO) Context.getInstance().getBean(myClassDAO.class);
         String fieldName = (String) autoComplete.getAttributes().get("fieldName");
         newMatchesStrList = myDao.findTemplateFieldValues((String)autoComplete.getValue(), fieldName);
      }
      // assign new matchList
      if (this.matchesSIList != null) {
          this.matchesSIList.clear();
      }
      Iterator<String> itr = newMatchesStrList.iterator();
      while(itr.hasNext()) {
         String str = (String) itr.next();
         matchesSIList.add(new SelectItem(str, str));
      }
   }
}

The bean is in request scope (although I also tried with session scope). I am using ICEfaces community edition 1.8.2.

The problem is, these auto-complete controls are created dynamically based on certain attributes of each entry in the datatable. So, you can have, for example 2 or more such auto-complete controls in the same panelGroup. When this is the case, when you start typing something the first control, it seems to be triggering the event for all sibling auto-complete controls, and in the end returns the list for the last in order. In general, I noticed erratic behavior caused by the fact that the event is triggered for all auto-complete controls at once, and values/lists get confused.

What am I doing wrong?

Thanks in advance!