Auto instance of PrimeFaces created by custom component does not display offers
I have a problem dynamically creating a PF 3.4.2 AutoComplete component. The component renders ok completely, its value is updated on partial processing , but suggestions are never shown.
I create this control like this:
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 the parent control using
getChildrens().add(ac);
The parent component is the PF PanelGrid output. I have successfully used this approach to create various edition panels and it works like a charm. But I can't figure out why it's not with autocomplete.
The parent control looks like this:
@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.
Other aspects of declaring custom components (in taglib, etc.) are ok.
The problem doesn't seem to be with EL expressions, completeMethod definition, etc. If I include p: autoComplete initialization with the same parameters in my xhtml test page, it 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 request is detected. See the autocomputer source code at http://primefaces.googlecode.com/files/primefaces-3.4.2.zip .
In the "dynamically generated" case, the decode method of this component is not called. I could not find the reason for the last days, but failed.
I look forward to your suggestions on what to check to fix this annoying "error".
source to share
So, the problem was generating the id (see two comments).
Starting component instantiation:
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 considered when generating the client ID.
source to share