Search code examples
jsfjsf-2autocompleterichfaces

JSF richfaces autocomplete not working


I'm using richfaces to get autocomplete but it doesn't work. I studied the richfaces showcases and QA's here but I can't get it to work. I get no error message on the console, the Horse list is not empty, richfaces with AutocompleteBase.js are loaded,

My xhtml:

...
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
...
<h:form>
   <rich:autocomplete mode="cachedAjax" minChars="1" 
         autocomopleteMethod="#{autoCompleteBean.autocomplete}"/>           
</h:form>
...

My autocomplete Bean:

@Named
@RequestScoped
public class AutoCompleteBean {

private List<String> autocompleteList;
private List<Horse> horses;

    @PostConstruct
    private void init() {
        autocompleteList = new ArrayList<String>();
        for (Hors horse : horses) {
            autocompleteList.add(horse.getName());
        }
    }

    public List<String> autocomplete(String prefix) {
        ArrayList<String> result = new ArrayList<>();
        for (Iterator<Horse> it = autocompleteList.iterator(); it.hasNext();) {
            if (it.next().getName().startsWith(prefix)) {
                result.add(it.next());
            }   
        }
        return result;
    }
}  

HTML output img


Solution

  • It should be autocompleteMethod not autocom**o**pleteMethod, so:

    <h:form>
        <rich:autocomplete mode="cachedAjax" minChars="1"
            autocompleteMethod="#{autoCompleteBean.autocomplete}" />
    </h:form>
    

    Also, check the difference between @Named and @ManagedBean annotations in JSF2.0 here.

    Whole modified code:

    @ManagedBean // instead of @Named
    @RequestScoped
    public class AutoCompleteBean {
    
        // sample initialization, ensure that the list has some values
        @ManagedProperty(value = "#{someOtherBean.myHorses}")
        private List<Horse> horses;
        private List<String> autocompleteList;
    
        public List<String> autocomplete(String prefix) {
            ArrayList<String> result = new ArrayList<>();
    
            // don't use iterators unless you really need it
            // also, you had errors in this part (it.next)
            for (String s : autocompleteList) {
                if (s.startsWith(prefix)) {
                    result.add(s);
                }
            }
            return result;
        }
    
        @PostConstruct
        public void init() {
            for (Horse horse : horses) {
                autocompleteList.add(horse.getName());
            }
        }
    
        public void setHorses(List<Horse> horses) {
            this.horses = horses;
        }
    }
    

    If you are using faces-config.xml instead of annotations, then it should be:

    <managed-bean>
        <managed-bean-name>autoCompleteBean</managed-bean-name>
        <managed-bean-class>sample.package.AutoCompleteBean</managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>
        <managed-property>
            <property-name>horses</property-name>
            <value>#{someOtherBean.myHorses}</value>
        </managed-property>
    </managed-bean>