conditional rendered f:selectItem possible problems

Ray picture Ray · Jan 25, 2013 · Viewed 6.9k times · Source

I have a page with several h:selectOneMenu or p:selectOneMenu and I want to use the same page for editing and adding data. When I will edit data I need f:selectItem. I know that this component doesn't have attribute rendered. And I read that I can use <c:if>.

Ok. For example, if I write

<p:selectOneMenu rendered="#{not empty bean.id}"
    value="#{bean.selectedId}">
    <c:if test="${editableBean != null}">
        <f:selectItem itemLable="#{editableBean.name} itemValue=#{editableBean.id} />
    </c:if>
    <f:selectItems value="#{bean.listItems}" var="item"
        itemLabel="#{item.name}" itemValue="#{item.id}"/>
</p:selectOneMenu>

Will it works without any problems in primefaces and with ajax listeners?

Answer

Luiggi Mendoza picture Luiggi Mendoza · Jan 25, 2013

The easy solution (but with poor performance) will be to have a boolean editMode attribute in your managed bean to enable/disable the components. Basic example:

<p:selectOneMenu rendered="#{not empty bean.id}" disabled="#{bean.editMode}"
    value="#{bean.selectedId}">
    <f:selectItems value="#{bean.listItems}" var="item"
        itemLabel="#{item.name}" itemValue="#{item.id}"/>
</p:selectOneMenu>

In your bean

@ManagedBean
@ViewScoped
public class Bean {

    private int id;
    private boolean editMode;
    //other attributes...
    //getters and setters...

    @PostConstruct
    public void init() {
        //a way to know if the bean it's in edit mode
        editMode = (id != 0);
    }
}

This solution will have poor performance because every <p:selectOneMenu> will have to load all the data and then select the actual value, but it will do what you want. Another option will be to use this attribute for the rendered property of <p:selectOneMenu> and for an <h:inputText disabled="true" readonly="true" /> (or maybe <h:outputText />). Another basic sample:

<p:selectOneMenu rendered="#{not empty bean.id && not bean.editMode}"
    value="#{bean.selectedId}">
    <f:selectItems value="#{bean.listItems}" var="item"
        itemLabel="#{item.name}" itemValue="#{item.id}"/>
</p:selectOneMenu>

<h:inputText rendered="#{bean.editMode}" value="{bean.selectedText}"
    disabled="true" readonly="true" />