JSF: rendered attribute - jsf

I have a panelGroup with a rendered attribute. Why is it that the component values in the panelGroup are even called if the rendered attribute is set to false? Do I missunderstand the rendered attribute here?
What I want to do is: I have a selectManyCheckbox before the panelGroup and everything in the panelGroup should only be executed if the user has chosen values in the selectManyCheckbox and hit a button. This won't work like this because the components in the panelGroup depend on the values the user has to choose in the selectManyCheckbox.
<h:selectManyCheckbox /> // for the user to choose
<h:commandButton /> // to render the panelGroup
<h:panelGroup rendered="#{someBean.render}">
<h:dataTable value="#{someOtherBean.loadSomething(someObject)}" var="item">
// ...
</h:dataTable>
</h:panelGroup>

The rendered attribute simply states if the following component should be rendered on the client side DOM. These components will still follow the JSF lifecycle events and will maintain the value of a managed bean.
EDIT: In response to a request for a workaround:
The simplest way I can see to workaround this, if you do not want the value attribute to invoke the bean method then simply wrap the logic in your bean method with an if check on the render condition.
public void loadSomething(Object someObject) {
if (render()) {
//Do loadSomething logic
}
}

Related

What is the correct way to use RequestScoped Bean and rendered attribute?

does anybody know how to use RequestScoped bean together with rendered attribute in jsf? The rendered attribute is evaluated before applyValues phase and therefore is not correctly evaluated. I don't want to preserve any state. The example could be an outputPanel with a datatable and a button. The datatable gets a list of values. The wrapping outputPanel has the rendered attribute like:
<p:outputPanel rendered="#{not empty requestScopedBean.dataList}">
<p:datatable value="#{requestScopedBean.dataList}">
...
</p:datatable>
<p:commandButton action="#{requestScopedBean.someAction}" />
</p:outputPanel>
After loading the page and clicking on the button, nothing happens, because the view is restored and expressions are evaluated - the bean does have an empty datalist and therefore the panel should not be rendered. This causes that the action method is not even called - because the button doesn't exist.
If you're not interested in having a filled data table at that moment, just add an extra check in rendered attribute if the command button of interest has been invoked. You can do that by checking the presence of button's client ID in request parameter map.
<p:outputPanel rendered="#{not empty requestScopedBean.dataList or not empty param[someButton.clientId]}">
...
<p:commandButton binding="#{someButton}" ... />
</p:outputPanel>
See also:
How to let validation depend on the pressed button?

Cannot call action methods on RequestScoped Bean from tabView [duplicate]

does anybody know how to use RequestScoped bean together with rendered attribute in jsf? The rendered attribute is evaluated before applyValues phase and therefore is not correctly evaluated. I don't want to preserve any state. The example could be an outputPanel with a datatable and a button. The datatable gets a list of values. The wrapping outputPanel has the rendered attribute like:
<p:outputPanel rendered="#{not empty requestScopedBean.dataList}">
<p:datatable value="#{requestScopedBean.dataList}">
...
</p:datatable>
<p:commandButton action="#{requestScopedBean.someAction}" />
</p:outputPanel>
After loading the page and clicking on the button, nothing happens, because the view is restored and expressions are evaluated - the bean does have an empty datalist and therefore the panel should not be rendered. This causes that the action method is not even called - because the button doesn't exist.
If you're not interested in having a filled data table at that moment, just add an extra check in rendered attribute if the command button of interest has been invoked. You can do that by checking the presence of button's client ID in request parameter map.
<p:outputPanel rendered="#{not empty requestScopedBean.dataList or not empty param[someButton.clientId]}">
...
<p:commandButton binding="#{someButton}" ... />
</p:outputPanel>
See also:
How to let validation depend on the pressed button?

Set bean value on click of selectbooleancheckbox

I have a bean class and a selectBooleanCheckbox in xhtml page. I want that on the click of the box the value should be set in the backing bean.
Here is code:
<h:selectBooleanCheckbox id="provisioningTargetCollector"
value="#{targetSource.provisioningTargetCollector}">
</h:selectBooleanCheckbox>
Bean Class:
public boolean isProvisioningTargetCollector() {
return _provisioningTargetCollector;
}
public void setProvisioningTargetCollector(boolean provisioningTargetCollector) {
_provisioningTargetCollector = provisioningTargetCollector;
}
But the getter and setter are called only on page load. How can I set the value in bean method on click of checkbox.
The model with be filled with form data only when submit button will be pressed. If you want to do partial update to the server you need to send an AJAX request. Luckily, starting from JSF 2 it has been quite simple with the introduction of <f:ajax> tag. It adds ajax capabilities to UIComponent instances that implement the ClientBehaviorHolder interface, i.e. components that are capable of triggering ajax requests.
To do partial update of compenets you need to specify their client ids in execute attribute of <f:ajax> tag. As the default value of execute attribute evaluates to #this, or the component to which the tag is attached it. As soon as you want to update only the given <h:selectBooleanCheckbox> you can do it as simple as nesting a pure <f:ajax /> tag within you checkbox, i.e.:
<h:selectBooleanCheckbox id="provisioningTargetCollector" value="#{targetSource.provisioningTargetCollector}">
<f:ajax />
</h:selectBooleanCheckbox>

Conditionally rendering an <ui:include>

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;
}
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.
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.

Modify dynamically JSF snippets by h:commandlink

I have a h:commandlink control in page1. the control uses f:ajax to call to the following h:panelgroup :
I have a h:panelgroup control in page2 (a snippet), which has a ui:include within it.
I have a h:panelgroup control in page3 (a snippet), which has a ui:include within it.
Now according to the choices made on page1, I would like to switch the snippets by clicking on the h:commandlink control.
I have a BIG problem there: it seems that only if I click twice on the commandlink, only then the snippet changes - and not on one click.
I have tried to remove the f:ajax to render the panelgroup, and still it does not work...
There are two potential causes of this problem.
The <f:ajax> is fully re-rendering another <h:form> than where it is sitting in. This way the view state of the other form will get lost which would require invoking the action on the other form twice before it really get executed.
The solution is to not re-render the other <h:form>, but only some container component in that form. E.g.
<h:form id="otherForm">
<h:panelGroup id="content">
...
<h:panelGroup>
</h:form>
with
<f:ajax render=":otherForm:content" />
When there's a rendered attribute on the <h:commandLink> or any of its parent components, then it must evaluate true during the apply request values phase of the postback request in order to get JSF to invoke the bean action associated with the <h:commandLink> during the invoke action phase of that request. Perhaps the bean is request scoped and/or some odd/illogical flow inside the bean caused that the rendered attribute is not properly been preserved.
Best is to maintain those rendered conditions in a #ViewScoped bean and let its action methods return void or null so that the bean lives as long as you're interacting with the same view. Change the rendered conditions during action methods only and not inside setters/getters or something.

Resources