Search code examples
jsfprimefacesautocompletecomposite-component

How use primefaces autocomplete into composite with preselected values?


I have a problem using autocomplete primefaces component inside of an UIInput composite. My goal is to init the application with preselected value in autocomplete field, showing a label accordingly. Below I show a test code

Page testPage.xhtml

<f:view id="view" locale="#{webSession.currentLanguage.locale}">
    <h:head>
        <title>...</title>
     </h:head>
    <h:body>       
        <h:form>
            <utils:element/>
            <p:autoComplete 
                value="#{testPage.attr}" 
                completeMethod="#{testPage.completeMethod}"
                var="item" 
                itemLabel="#{item}"
                itemValue="#{item}" />
        </h:form>
    </h:body>
</f:view>

Managed Bean TestPage.xhtml

@ManagedBean(name = "testPage")
@ViewScoped
public class TestPage {

   private String attr;

   @PostConstruct
   public void init(){
       attr = "value 1";
   }

   public String getAttr() {
       return attr;
   }

   public void setAttr(String attr) {
       this.attr = attr;
   }

   public List<String> completeMethod(String query) {
       return Arrays.asList(new String[]{"1111", "2222", "3333"});
   }
}

This approach works fine using the autocomplete directly on testPage.xhtml. However, I want to wrap this autocomplete in a element composite, as showed in following code

element.xhtml composite page

<ui:component xmlns="http://www.w3.org/1999/xhtml"
   xmlns:p="http://primefaces.org/ui"
   xmlns:ui="http://java.sun.com/jsf/facelets"
   xmlns:cc="http://java.sun.com/jsf/composite">
   <cc:interface componentType="elementComponent">
   </cc:interface>
   <cc:implementation>  
       <p:autoComplete 
           value="#{cc.attr}" 
           completeMethod="#{cc.completeMethod}"
           var="item" 
           itemLabel="#{item}"
           itemValue="#{item}" />
   </cc:implementation>
</ui:component>

ElementComponent composite backing

@FacesComponent("elementComponent")
@ViewScoped
public class ElementComponent extends UIInput implements NamingContainer{

   private String attr;

   @Override
   public String getFamily() {
       return UINamingContainer.COMPONENT_FAMILY;
   }

   public List<String> completeMethod(String query) {
       return Arrays.asList(new String[]{"value 1", "value 2", "value 3"});
   }

   @Override
   public void encodeBegin(FacesContext context) throws IOException {
       attr = "value 1";
   }

   public String getAttr() {
       return attr;
   }

   public void setAttr(String attr) {
       this.attr = attr;
   }
}

But when I include the element composite in testPage.xhtml, the autocomplete does not show the preselected value (unlike the direct implementation). Is there any way to solve this? Maybe any method or attribute is missing in the implementation of FacesComponent? I tend to think this is a bug between the implementation of primefaces and the implementation of composite, but I am not sure.


Solution

  • The problem was the method encodeBegin(). This implementation require the encode of the component class, and the encode of the parent (UIInput).

    Incorrect

    @Override
    public void encodeBegin(FacesContext context) throws IOException {
       attr = "value 1";
    }
    

    Correct

    @Override
    public void encodeBegin(FacesContext context) throws IOException {
       attr = "value 1";
       super.encodeBegin();
    }