Conditionally rendering an <ui:include>

31.2k views Asked by At

I am trying to toggle a page that shows a <rich:dataTable>. Before I just included the <ui:include> template and it would just show the table the whole time.

<ui:include src="../log/viewDlg.xhtml"/>

Now I want to be able to toggle it on/off on the web-page. Showing on the page with maybe a button or link. How can I achieve it?


Update 1: I am unable to get it to show up for some odd reason, Here is what I wrote so far based on feed back

View:

<a4j:commandLink value="View"
    action="#{bean.showview}" render="viewPanel"/>

<h:panelGroup id="viewPanel">
    <h:panelGroup id="tableRenderPanel" rendered="#{bean.showPolicyView}">    
        <ui:include src="../log/viewDlg.xhtml"/>
    </h:panelGroup>                         
</h:panelGroup>

Backing bean:

private boolean showPolicyView = false;

public void showView() {
    showPolicyView = !showPolicyView;
}

public boolean isShowPolicyView(){
    return showPolicyView;
}
2

There are 2 answers

26
Fritz On BEST ANSWER

Wrap your <ui:include> inside two <h:panelGroup> elements. There's a catch here, you can't rerender a conditional component. Why's this? because when the element's rendered attribute resolves to false, it will not be considered while rendering the view so it can't be the target of an operation (in this case, related to renderization).

Jumping to the code, you'll have this:

<h:panelGroup id="wrapperPanel">
    <h:panelGroup id="tableRenderPanel" rendered="#{yourBean.renderTable}">
        <ui:include src="../log/viewDlg.xhtml"/>
    </h:panelGroup>
</h:panelGroup>

yourBean#renderTable is a Boolean property that determines if the component will be rendered. When it evaluates to false, the component is not included in the component tree.


Toggling the view

To toggle the view, simply create a bean method that either refreshes the page

<h:commandLink action="#{yourBean.toggleTableView}"/>

or the particular panel through AJAX. To do this in JSF 1.2, rely on extensions like RichFaces to introduce AJAX, if you can. For example, should you choose RichFaces, you can use <a4j:commandLink/> and its handy render (or reRender in older versions) attribute to achieve what you could do normally with an <f:ajax/> in JSF 2

<a4j:commandLink action="#{yourBean.toggleTableView}" reRender="wrapperPannel"/>

Or, another alternative is

<a4j:commandLink action="#{yourBean.toggleTableView}">
    <a4j:support event="oncomplete" reRender="wrapperPannel"/>
</a4j:commandLink>

Please note that the reRender attribute may vary depending on the structure of your page, but it should always reference the id of the wrapping panel in the end. Also, reRender was renamed to simply render in late RichFaces versions.

So, assuming you have a renderTable property (getter + setter) in yourBean, the toggleTableView must change it, in order to dinamically define if the component is to be rendered or not (renderTable = false).


Introducing RichFaces

Check this link for help in setting up RichFaces in your project.

0
Hannes Schneidermayer On

I like the use of ui:include better than inserting h:panelBoxes like here:

<ui:fragment rendered="#{myBean.yourCondition()}">
    <ui:include src="viewA.xhtml"/>
</ui:fragment>
<ui:fragment rendered="#{not myBean.yourCondition()}">
    <ui:include src="viewB.xhtml"/>
</ui:fragment>

Advantage: Tag handlers do not represent components and never become a part of the component tree once the view has been built. It won't interefere with your CSS - the h:panelBox, in contrary, inserts a div or span.


... Another approach would be c:choose, which works but can cause render phases issues.

<c:choose>
    <c:when test="#{myBean.yourCondition()}">
        <ui:include src="viewA.xhtml"/>
    </c:when>
    <c:otherwise>
        <ui:include src="viewB.xhtml"/>
    </c:otherwise>
</c:choose>

Caution: When fiddling with tag handlers (like any c:xxx), be sure to know the difference between UI Components and Tag Handlers. Namely that UI Components and Tag Handlers are renderend in different phases. That implies that you cannot create a variable in a composite component and use it in a nested tag handler. c:choose and ui:include are both tag handlers, so normally it's not a problem. Read the link, it's a very short example and very insightful.