How to change OneMenu element to outputText in JSF - 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.

Related

How to get value in JSF xhtml page from f:selectItems

I have select menu in JSF xhtml page. The select menu contains a
<h:selectOneMenu value="#{bean.statusFlag}">
<f:selectItems value="#{bean.statusList}"/>
</h:selectOneMenu>
The value is be being stored in status.
This works fine. I have to print the value in h:outputText in next column.
<h:outputText value="#{bean.statusFlag}" />
prints code rather value corresponding value of code, since the value is in statusList.
Is there any way to achieve this without having to modify the backing bean.
You could perhaps implement some sort of <f:ajax> within your <h:selectOneMenu>.
You could also use jquery with an onchange() event.
$('#select').change(function() {
$('#outText').val($('#select').val());
});
Hope that helps!

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.

render richfaces popupPanel after bean method is finished

I have a simple problem where I want to display a popup if something went wrong in my managed bean.
The bean holds a list of exceptions that can be raised, with getter/setter methods.
The xhtml looks like this
<rich:panel>
<h:form>
<a4j:commandButton value="Compute Mission"
action="#{missionHandler.generateMissionFeasability}"
render="popupPanel">
</a4j:commandButton>
</h:form>
</rich:panel>
<rich:popupPanel id="popupPanel" modal="true" autosized="true"
resizeable="false" moveable="false" rendered="#{not empty missionHandler.exceptions}">
<f:facet name="header">
<h:outputText value="Exceptions raised during the processing " />
</f:facet>
<f:facet name="controls">
<h:outputLink value="#"
onclick="#{rich:component('popupPanel')}.hide();return false;">
</h:outputLink>
</f:facet>
</rich:popupPanel>
As you see I have a command button that should call generateMissionFeasibility method in the bean.
The method will (among other things) add exception in the exceptions list.
I would like to check the list (if it's empty or not) to display the popup
The code above doesn't work because I think the popup is rendered before the end of the method in the bean, and the list is empty at the beginning.
One way to make popup panel be shown once rendered is to change
rendered="#{not empty missionHandler.exceptions}"
to
show="#{not empty missionHandler.exceptions}"
The code doesn't work because the first time the view is about to be rendered, missionHandler.exceptions will be empty, which means popupPanel never makes it to the browser. Subsequent requests to reRender popupPanel will fail as the component is nowhere to be found in the DOM.
For a component to be ajax-updated, it must already be in the DOM in the browser, this is the way ajax works. So the solution is to wrap the content of the popup panel in a component that will always be rendered.
That aside, even if you got the rendering correct, your popup will only be placed in the DOM. You actually need to call show() on the popup to get it to showup
To achieve what you want however, a better alternative will be to
Conditionally display the popup using javascript. If the condition is met, the show() function is called for the popup. Otherwise, an empty, do-nothing javascript function will be called.
<a4j:commandButton value="Compute Mission" action="#missionHandler.generateMissionFeasability}"
oncomplete="#{not empty missionHandler.exceptions ? #{rich:component('popupPanel')}.show()" : doNothing()}" render="popupPanel">
</a4j:commandButton>
For the doNothing js:
<script> function doNothing(){} <script/>
Take the rendering condition out of the modal panel
EDIT: Additionally, the show attribute on the popup component can be based on the same EL condition as the oncomplete attribute

Displaying read-only forms (values are shown as text instead of disabled input controls) with JSF?

I have a data entry form where user enters lots of data. When user comes to the page to view existing data, the page should be displayed in read-only mode (all values shown as text), when he clicks 'Edit' button, normal form with all input controls should be shown so that user can change and save data.
We are using JSF 2.0 with PrimeFaces library. It is easy to achieve above behavior for text box and text area but not for Checkbox, multi-select, radio,..... controls. Is there any easy way available to achieve above behavior rather than writing our own code (which may run into lot of lines thus making backing bean code ugly)
Thanks for your help...
I'm not sure why you think that you need additional backing bean code for this. You've all the needed values in the backing bean already. Your problem is more in the presentation of those values. Just display them in the desired format by writing the view code accordingly. Perhaps you were thinking it too the hard way.
Instead of a select boolean checkbox, you could display for example a "Yes" or "No" value.
<h:selectBooleanCheckbox value="#{bean.checked}" rendered="#{bean.edit}" />
<h:outputText value="#{bean.checked ? 'Yes' : 'No'}" rendered="#{not bean.edit}" />
Instead of a select one menu/radio, you could just display the value in an output text.
<h:selectOneMenu value="#{bean.selectedItem}" rendered="#{bean.edit}">
<f:selectItems value="#{data.availableItems}" />
</h:selectOneMenu>
<h:outputText value="#{bean.selectedItem}" rendered="#{not bean.edit}" />
Instead of a select many listbox/checkbox, you could just display for example all values comma separated in a loop.
<h:selectManyListbox value="#{bean.selectedItems}" rendered="#{bean.edit}">
<f:selectItems value="#{data.availableItems}" />
</h:selectManyListbox>
<h:panelGroup rendered="#{not bean.edit}">
<ui:repeat value="#{bean.selectedItems}" var="selectedItem" varStatus="loop">
#{selectedItem}#{not loop.last ? ', ' : ''}
</ui:repeat>
</h:panelGroup>
You could wrap it all in a tag file or a composite to minimize boilerplate and code repetition.
I've done this in my last project using composite components which has a "preview" attribute and in the implementation I render a text when this attribute is true and the real (editing) when the attribute is false. For checkbox in preview mode you could show the checkbox itself but disabled, for radio - show the selected item.
MyFaces Tomahawk library [1] contains an extended version of the standard components that adds displayValueOnly attribute for this purpose. This might help you (I haven't used them).
[1] - http://myfaces.apache.org/tomahawk-project/tomahawk20/index.html

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