views:

2164

answers:

3

I have a JSF page on which I want to have a checkbox that, when clicked, will add/remove certain other form fields from the page. Here is the (simplified) code I currently have for the checkbox:

<h:selectBooleanCheckbox title="showComponentToReRender" value="#{backingBean.showComponentToReRender}">
    <a4j:support event="onsubmit" reRender="componentToReRender" />
</h:selectBooleanCheckbox>

Here is the code for the component I want to hide:

<h:selectOneMenu id="componentToReRender" value="#{backingBean.value}" rendered="#{valuesList.rowCount>1 &amp;&amp; backingBean.showComponentToReRender}">
   <s:selectItems value="#{valuesList}" var="value"/>
</h:selectOneMenu>

Currently, clicking the checkbox does nothing; that "selectOneMenu" will not go away. What am I doing wrong?

+1  A: 

The onsubmit event only get fired when you submit the parent form containing the checkbox.

You rather need to hook on the onclick event, it will get fired when you click the checkbox.

BalusC
Unfortunately, this did not change the behavior. To test, I added onsubmit="alert('Tada!')" to the a4j:support tag... when I clicked the checkbox I got the javascript alert, so it does seem to be firing the onsubmit event when it's clicked.
iandisme
Oh, I didn't expect that a4j would submit the **entire** form when a checkbox with a4j:support is clicked.
BalusC
+3  A: 

You need to wrap the componentToReRender in either:

<h:panelGroup id="componentToReRenderWrapper">

or

<a4j:outputPanel id="componentToReRenderWrapper">

So, effectively you will have:

<h:panelGroup id="componentToReRenderWrapper">
    <h:selectOneMenu id="componentToReRender" value="#{backingBean.value}" rendered="#{valuesList.rowCount>1 &amp;&amp; backingBean.showComponentToReRender}">
       <s:selectItems value="#{valuesList}" var="value"/>
    </h:selectOneMenu>
</h:panelGroup>

and change the reRender="componentToReRenderWrapper" in case you use panelGroup, or remove that attribute, in case you use outputPanel.

Found the exact explanation in the RichFaces docs:

Most common problem with using reRender is pointing it to the component that has a "rendered" attribute. Note, that JSF does not mark the place in the browser DOM where the outcome of the component should be placed in case the "rendered" condition returns false. Therefore, after the component becomes rendered during the Ajax request, RichFaces delivers the rendered code to the client, but does not update a page, because the place for update is unknown. You need to point to one of the parent components that has no "rendered" attribute. As an alternative, you can wrap the component with layout="none" .

Bozho
Makes sense. But why does it eventually not evaluate its own `rendered` attribute?
BalusC
it seems it does actually, but the rendering is a bit tricky. I updated my answer with details from the docs
Bozho
Interesting... I'll try this on Monday morning.
iandisme
Wrapping the components to be rerendered in a h:panelGroup worked as you expected. The only problem I'm having now is that the boxes take a few seconds to appear/disappear and I'm not sure how to let the user know their change is being affected. Thanks!!
iandisme
A: 

Don't forget to set ajaxRendered="true" on the a4j:outputPanel

janner