Search code examples
jsfjsf-2selectonemenurendered-attribute

conditional rendered f:selectItem possible problems


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?


Solution

  • 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" />