3 Replies Latest reply on Aug 29, 2007 12:00 PM by tuxzilla

    SuggestionBox, retrieve selected row

    fabmars

      Hi,
      I'd like to be able to retrieve the object i'm selecting in the dataTable shown by a suggestionbox.

      Basically i'm doing this

      <h:inputText id="myInput">
       <rich:suggestionBox suggestionAction="myBean.myAction" var="myVar">
       <h:column>
       <h:outputText value="myVar.myProperty"/>
       </h:column>
       <a4j:support event="onchange" actionListener="myBean.myListener"/>
       </rich:suggestionBox>
      


      Well, so my listener is actually called when i select one of the box' entries, and in it, i can get the parent UIData of the event (a HtmlSuggestionBox, which I expected), however a getRowData on it throws an IllegalArgumentException because the rowIndex is stuck at -1.

      Please can someone help me ???

        • 1. Re: SuggestionBox, retrieve selected row
          fabmars

          Ok, 2 days, no help. After some searching I found the issue was already discussed there: http://jboss.com/index.html?module=bb&op=viewtopic&t=110215

          About Sergey's answer, I really don't agree.

          First I don't understand why it would be such a pain to manage the underlying UIData properly.

          Second, as the latest poster noted, IceFaces has indeed such a feature.

          Third, just take the example of a music shop: some admon has to add some tracks to a DB everyday and uses some web admin. Sometimes the track's group is already in the DB, so when the user begins the group name typing, he sees it's suggested and selects it. Upon submit, it will be easy to link the new track to the existing group before persisting in the DB. Else, if the user is entering a new group, no row is chosen, and the entered text is used to create a new group transparently. THIS would make the UISuggestionBox#getRowData very helpful !

          • 2. Re: SuggestionBox, retrieve selected row
            fabmars

            Here is a workaround.

            The entity I'm manipulating:

            public class myEntity {
             private Long id;
             private String label;
            
             //getters & setters...
            }
            



            I'm using one managed-bean #{myHandler} which contains the listeners I need, and also another managed-bean #{myForm} which simply maps my form on my page.

            Here is a bit of myForm code:
            public class MyForm
            {
             private Entity entity;
             private String entityLabel;
            
            
             public String getEntityLabel() {
             return entityName;
             }
            
             public void setEntityLabel(String entityLabel) {
             this.entityLabel = entityLabel;
             }
            
             public Entity getEntity() {
             return entity;
             }
            
             public void setEntity(Entity entity) {
             this.entity = entity;
             setEntityName(entity == null ? null : entity.getLabel());
             }
            }
            



            Here is the code used to suggest some entities in myHandler
            (The entityRepository is my Hibernate/Persistence wrapper)
            public List<Entity> onSuggestEntity(Object o) throws PersistenceException
            {
             List<Entity> suggestEntities = new ArrayList<Entity>();
             if(o != null)
             {
             String entry = o.toString();
             suggestEntities = entityRepository.getEntitiesWithLabelBeginingWith(entry);
             }
             return suggestEntities;
            }
            



            Here is the code called when one of the suggestions is selected, also in myHandler:
            public void onSelectEntity(ActionEvent e)
            {
             String s = myForm.getEntityLabel();
             if(s != null)
             {
             Entity entity = null;
             try
             {
             Long id = new Long(s);
             entity = entityRepository.get(id);
             }
             catch(NumberFormatException nfe) {
             log.warn("Parsed bad Entity id: " + s);
             }
             catch(PersistenceException pe) {
             log.warn("get Entity Failed: " + s, pe);
             }
            
             if(entity != null) {
             myForm.setEntity(entity);
             myForm.setEntityLabel(entity.getLabel());
             }
             else { //just in case
             myForm.setEntity(null);
             myForm.setEntityLabel("");
             }
             }
             else {
             log.debug("Entity label to parse is null");
             }
            }
            



            And finally here is my view code:
            <a4j:region>
             <h:inputText id="inputEntity" value="#{myForm.myEntityLabel}"/>
             <rich:suggestionbox id="suggestEntity" for="inputEntity" suggestionAction="#{myHandler.onSuggestEntity}" var="myEntity" rows="6" fetchValue="#{myEntity.id}">
             <a4j:support event="onselect" actionListener="#{myHandler.onSelectEntity}" reRender="inputEntity, suggestEntity"/>
             <h:column>
             <h:outputText value="#{myEntity.label}" />
             </h:column>
             </rich:suggestionbox>
            </a4j:region>
            



            The point of all this is to
            - set the selected entity id in the fetchValue
            >> fetchValue="#{myEntity.id}"

            - use this id to retrieve the actual entity instance related to it
            >> myForm.getEntityLabel(), then entityRepository.get(id)

            - RE-set the input content from this instance
            >> myForm.setEntity(entity);
            >> myForm.setEntityLabel(entity.getLabel());

            - reRender the input and the suggestionBox
            reRender="inputEntity, suggestEntity"
            (rerendering the whole region doesn't work)

            Of course it works with the managed beans in request or session scopes.


            Also it's easy to put the page code in some facelet tag so that you can only write this in your page to get both the inputText and the suggestionBox: <pfx:entitySuggest id="entity" rendered="true" required="false" value="#{myForm.entityLabel}" rows="6" backingBean="#{myHandler}" suggestionAction="onSuggestEntity" selectionListener="onSelectEntity"/>
            (NB : the backingBean here is specified so that the facelets machinery can bind the methods backingBean[onSuggestEntity] and backingBean[onSelectEntity], as explained in the facelets FAQ).


            Nevertheless, it would be greater to have one component to manage this all. The point would be to keep alive the suggestion list in the underlying UIData so that the developer can getRowData on it after the actual Ajax request.

            • 3. Re: SuggestionBox, retrieve selected row
              tuxzilla

              I have to second that suggestion because it is a very common use case.