Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PrimeFaces autoComplete instantiated by custom component does not display suggestions

I have a problem when dynamically instantiating a PF 3.4.2 AutoComplete component. The component intially renders ok, its value is refreshed on partial processing but the suggestions are never displayed.

I am instantiating this control the following way :

    AutoComplete ac = (AutoComplete) context.getApplication().createComponent(AutoComplete.COMPONENT_TYPE);
    final String varName = "p";

    ValueExpression ve = JSFUtils.createValueExpression("#{minContext.selected.sen}"), Sen.Type);
    ac.setValueExpression("value", ve);

    ac.setForceSelection(true);

    ac.setVar(varName);

    ValueExpression itemLabel = JSFUtils.createValueExpression("#{sc:senLibelle(p)}"), String.class);
    ac.setValueExpression("itemLabel", itemLabel);

    ValueExpression itemValue = JSFUtils.createValueExpression("#{" + varName + "}");
    ac.setValueExpression("itemValue", itemValue);

    MethodExpression completeMethod = JSFUtils.createMethodExpression("#{senUtils.completeAllSens}", List.class,new Class[]{String.class});
    ac.setCompleteMethod(completeMethod);

then adding it to parent control using

    getChildrens().add(ac);

The parent component is a derivation of PF PanelGrid. I use this approach successfully to generate various edition panels and it works like a charm. But I can not figure why it does not with autoComplete.

The parent control looks like :

@FacesComponent(SenatDataTableEntryDetail.SENAT_COMPONENT_TYPE)
public class SenatDataTableEntryDetail extends PanelGrid {

    /** Leaving renderer unchanged, so that PF renderer for PanelGrid is used.
     */
    public static final String SENAT_COMPONENT_FAMILY = "fr.senat.faces.components";
    public static final String SENAT_COMPONENT_TYPE = SENAT_COMPONENT_FAMILY + ".SenatDataTableEntryDetail";

    private enum PropertyKeys { mapper, bean; }

    @Override
    public void encodeBegin(FacesContext context) throws IOException {
        super.encodeBegin(context);
        addDynamicChildren(context);
    }

    @Override
    public boolean getRendersChildren()
    {
        return true;
    }

    ...

    private Boolean isInitialized() {
        return (Boolean)getStateHelper().eval(SENAT_INITIALIZED,false);
    }

    private void setInitialized(Boolean param) {
        getStateHelper().put(SENAT_INITIALIZED, param);
    }

    private void addDynamicChildren(FacesContext context)  throws IOException {
        if(isInitialized()) {
            return;
        }
        setInitialized(true);
        /* components are instiated and added as children only once */
    }    
}

It just adds children to the panel grid.

The other aspects of custom component declaration (in taglib and so on) are ok.

The problem doest not seem to be in EL expressions, completeMethod definition, etc. If I include in my test xhtml page an instanciation of the p:autoComplete with the very same parameters, it just works as expected :

    <p:autoComplete value="#{minContext.selected.sen}" forceSelection="true" 
                        var="p" itemLabel="#{sc:senLibelle(p)}" itemValue="#{p}"
                        completeMethod="#{senUtils.completeAllSens}"/>

I noticed that the PF AutoComplete component is a bit special as it renders differently when a query is detected. See AutoCompleteRenderer source code in http://primefaces.googlecode.com/files/primefaces-3.4.2.zip .

In the "dynamically instantiated" case, the decode method of this component is not called. I failed to find why those last days, but did not succeed.

I look forward for your suggestions on what to check to correct this annoying "bug".

like image 422
Ludovic Pénet Avatar asked Dec 15 '25 19:12

Ludovic Pénet


1 Answers

So, the problem was in id generation (see the two comments).

The beginning of component instantiation becomes :

AutoComplete ac = (AutoComplete) context.getApplication().createComponent(AutoComplete.COMPONENT_TYPE);
ac.setParent(this);
ac.setId(...some application specific unique id generation...);

final String varName = "p";

This way, the naming container is properly taken in account on client id generation.

like image 190
Ludovic Pénet Avatar answered Dec 18 '25 22:12

Ludovic Pénet



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!