Code picks up value from selectOneMenu and selectBooleanCheckbox, even though it is not rendered - jsf

I've got code the following code in my .xhtml
<t:panelGroup rendered="false">
<t:selectOneMenu id="id" value="#{row.someValue}" displayValueOnly="#{form.readState}">
<f:selectItems value="#{row.listOfValues}"/>
</t:selectOneMenu>
</t:panelGroup>
The listOfValues is set in a form populator, and is thus present in the form object. Also, as expected, the portion outlined above is not rendered in the output HTML.
But, when clicking the save button in the page the following code tries to get the value from the XHTML, even though it is not rendered. It will thus not copy the value present in the form, but set it to null (as it is not set in the XHTML).
object1.setSomeValue(form.getSomeValue());
As far as I can see this only happens with selectBooleanCheckbox and selectOneMenu. E.g. inputText works fine.
Any idea on how to fix it?

Try this:
<t:panelGroup>
<t:selectOneMenu id="id" value="#{row.someValue}" displayValueOnly="#{form.readState}">
<f:selectItems value="#{row.listOfValues}" rendered="false"/>
</t:selectOneMenu>
</t:panelGroup>

Related

p:input will not render value attribute

I have a problem rendering p:inputText from primefaces.
Their Demo at http://www.primefaces.org/showcase/ui/input/inplace.xhtml is working. If I change it to my requirements it fail.
In my .xhtml I've the following code. The first part will print out the given ipaddress as plain text,
#{hostEntryManaged.selectedEntry.ipAddress}
but the value attribute of the p:inputText keeps blank. Nothing to see in the final html.
<h:outputLabel for="ipaddr" value="IP: " />
<p:inplace id="ipaddr" editor="true" >
<p:inputText value="#{hostEntryManaged.selectedEntry.ipAddress}" required="true" label="text" />
</p:inplace>
I can add
value="#{hostEntryManaged.selectedEntry.ipAddress}" also to the p:inplace. There it works fine, till I click the field and it turns to the (desired) input field.
It feels that the <p:inputText..../> is out of scope, so it can't access my bean.
But there are no errors.

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?

SelectBooleanCheckbox rendered unchecked after ajax even if value is true

I am using a SelectBooleanCheckbox in a Composite Component which is rendered repeatetly with ui:repeat on the page. After pressing the Save button the page gets updated but the checkbox is unchecked even if the bean value is true.
<p:selectBooleanCheckbox id="someId" value="#{cc.attrs.item.property}"/>
#{cc.attrs.item.property}
And this is what is displayed on the page:
When i navigate to the page initialiy or after reloading the page in the Browser everything is rendered ok.
I also tried to change the submit to non-ajax and also using h:selectBooleanCheckbox but that did not change much.
========================== more code =================
page.xhtml
...
<ui:repeat id="listID" value="#{itemList}" var="listElement">
<cc:componentWithCheckbox id="theComponent" item="#{listElement}"/>
</ui:repeat>
...
componentWithCheckbox.xhtml
<cc:interface>
<cc:attribute name="item" required="true" />
</cc:interface>
<cc:implementation>
<div id="#{cc.clientId}">
<p:inputText value="#{cc.attrs.item.someTextProperty}"/>
<p:selectBooleanCheckbox id="someId" value="#{cc.attrs.item.property}"/>
#{cc.attrs.item.property}
</div>
</cc:implementation>
Bean
The Bean does nothing to the field. Just saves it in the DB. The value is correct in the bean and in the DB after pressing save. Just not rendered on the page.
====================== SOLUTION FROM MROD =====================
I just switched the ui:repeat in the view for c:forEach and everything was fine. :) I just needed to alter the id of the repeated element becouse with forEach every element got the same. I just added the status.index to the id to fix that.
Try using c:forEach instead of ui:repeat :)

How to change OneMenu element to outputText in JSF

I would like my page to be user friendly as much as possible and I have an idea but its a little bit harder in the way I want to solve it.
I'm using primefaces and I would like to have a selectOneMenu element which changes to just an outputText with the value of the selected variable in the selectOneMenu. Anyone have some nifty ideas?
This can be done with ajax and partial rendering. Here is a sketch of my idea (untested and in plain JSF):
<h:panelGroup id="wrapper">
<h:selectOneMenu value="#{myBean.myValue}"
rendered="#{myBean.myValue == someInitialValue}" ...>
<f:ajax render="wrapper"/>
... (your select items here)
</h:selectOneMenu>
<h:outputText value="#{myBean.myValue}"
rendered="#{myBean.myValue != someInitialValue}" .../>
</h:panelGroup>
And that's what it does:
The value of h:selectOneMenu will be initialized and the menu will be rendered only if it is the initial value.
On change of the value, the surrounding panelgroup will be re-rendered, hides the menu and lets the h:outputText appear.
You need a wrapping panelGroup for this because the outputText is not there at page load. If your form is small you could also render=#form or any other surrounding container instead. Then you wouldn't need the wrapper.

JSF ReRender support with selectBooleanCheckbox

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 && 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?
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 && 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" .
Don't forget to set ajaxRendered="true" on the a4j:outputPanel

Resources