h:outputLink navigation sometimes does not work - jsf

I have a navigation define from one page to another like this.
<h:outputLink id="idLink" value="Page1.seam" >
<f:param name="m" value="n103" />
<f:param name="mss" value="110" />
<h:outputText value="Return to Page 1" />
<a4j:support event="onclick" action="#{beanName.action}" limitToList="true" ignoreDupResponses="true" eventsQueue="que" ajaxSingle="true" immediate="true">
</a4j:support>
</h:outputLink>
The problem is there are sometimes that the view isn't changing to Page1.seam and remain in Page2.seam.
Is there anyone who knows better ?
Help will be greatly appreciated.
Thanks.

This construct makes no sense. Make it a normal link
<h:outputLink value="Page1.seam">
<f:param name="m" value="n103" />
<f:param name="mss" value="110" />
<h:outputText value="Return to Page 1" />
</h:outputLink>
and to invoke an action on opening of the page, use <f:event type="preRenderView"> in the target view instead.
<f:event type="preRenderView" listener="#{beanName.action}" />
See also:
How to execute action on GET request with f:viewParam?
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?

Related

Implementing a return navigation in JSF

I am looking for a JSF coding practice that will allow one page to link to another that, when it completes, will return to the original page. So I have a page viewDoc.xhtml that has this:
<f:metadata>
<f:viewParam name="id" value="#{viewDoc.id}" />
</f:metadata>
( bunch of stuff to show the document indicated by "id" )
<p:button value="Edit Name/Title"
outcome="editnametitle">
<f:param name="id" value="#{param.id}" />
</p:button>
Then I have a page editnametitle.xhtml that has this:
<h:form>
(input fields and stuff)
<p:commandButton value="Save Changes"
action="#{editNameTitle.doSave()}"
/>
<p:commandButton value="Cancel"
action="#{editNameTitle.doCancel()}"
immediate="true"
/>
</h:form>
So how do I implement the backing bean methods doSave() and doCancel() such that when they finish they navigate back to viewDoc.xhtml with the id parameter of the document included?
I haven't found any guidance for a solution and I haven't been happy with any approach I have thought of so far. I have thought of something like adding to the p:button the return path like:
<p:button value="Edit Name/Title"
outcome="editnametitle">
<f:param name="id" value="#{param.id}" />
<f:param name="returnoutcome" value="viewDoc" />
</p:button>
Is this the right approach? Or is there some JSF facility that does this that I missed?
Yes, that's basically it if those requests are idempotent.
One possible improvement is that you can dynamically obtain the current view ID as below:
<f:param name="returnoutcome" value="#{view.viewId}" />
This allows abstracting away it in a reusable custom tag.
Personally I'd use parameter name "from" too as that's more short.

rich:modalPanel reloading page on hide

I have a JSF page using richfaces with a few help buttons like this:
<rich:componentControl for="panelHelp" event="oncomplete" operation="show" />
The panel called is this:
<rich:modalPanel id="panelHelp" minHeight="250" minWidth="500"
keepVisualState="true" resizeable="true" moveable="true">
<f:facet name="header">
<h:outputText value="Help" />
</f:facet>
<f:facet name="controls">
<h:commandLink value="">
<h:graphicImage value="/close2.png" title="Close" />
<rich:componentControl for="panelHelp" event="onclick" operation="hide" />
</h:commandLink>
</f:facet>
<h:panelGrid columns="1" width="100%">
<h:outputText escape="false" id="txtHelp"
value="#{msgHelp}" style="width: 100%; height: 190px" />
</h:panelGrid>
</rich:modalPanel>
However, whenever I press the button to close the panel, it reloads the whole page, instead of simply hiding the panel.
Am I doing something wrong, or is there a better way to do this?
I'm using richfaces version 3.3.3
Use a4j:commandLink instead of h:commandLink and provide an a4j:support as well. This should fix the problem.
It's reloading the entire page because of your use of the <h:commandLink/>, which is going to trigger the entire JSF request processing lifecycle. To get your desired results you don't need the command link component. All you really need is:
<f:facet name="controls">
<h:graphicImage id="closeButton" value="/close2.png" title="Close" />
<rich:componentControl attachTo="closeButton" for="panelHelp" event="onclick" operation="hide" />
</f:facet>
What we're doing here is firing the <rich:componentControl/> on click of the image; there's no need for a link. I'm assuming you're using Richfaces 3.X. (RF 4.X has deprecated the attachTo attribute)
Above answer will work in Richfaces 3.x, If you are using Richfaces 4.x then the given code will work.
<f:facet name="controls">
<h:graphicImage value="/close2.png" >
<rich:componentControl target="closeButton" operation="hide" event="click" />
</h:graphicImage>
</f:facet>
Add disableDefault="true" attribute to your rich:componentControl to disable default behavior of the link on click.

How to call Java method from h:outputlink and pass value

I have this output `h:outputLink' to open a new page and pass a value:
<h:outputLink id="link" value="newpage.jsf" style="text-decoration:none; color:white;">
<f:param name="id" value="#{item.value}" />
</h:outputLink>
I need to add Java method which is called after I click the link. I saw that h:outputLink don't have action listener which I can use for calling Java method. I tested to use `h:commandButton' but the table logic is changed and it's not working properly. How I can solve this problem?
Try using 'h:commandLink' instead of `h:outputLink':
<h:commandLink id="lnkHidden" style="text-decoration:none; color:white;" actionListener="#{bean.pageRedirect}">
<f:setPropertyActionListener target="#{bean.sessionValue}" value="#{item.value}" />
</h:commandLink>

<h:commandButton> is not refreshing page after actioned

hi we are using along with a4j tag.
here we are retrieving data from database after a click of button. even though the data is available in server, it will not display over view. After manual refresh of web page will lead to data diplay.
here is code snippet
.... some code here
<rich:tab id="menu5" label="Recall">
<ui:include src="/pages/mctrans/reCallMcifTrans.xhtml" />
</rich:tab>
reCallMcifTrans.xhtml contains below code
<h:commandButton type="button" id="reCallbutton1" value=" Search "
styleClass="commandExButton">
<a4j:support event="onclick" id="ajsf12"
oncomplete="javascript:alert('Search Completed');javascript:document.body.style.cursor='default';"
action="#{mcifRecallTransBean.reCallSearch}" reRender="reCallgrid1" />
</h:commandButton>
It looks like you're working with RichFaces 3.3. So, you don't need a <h:commandButton with <a4j:support> because you can use <a4j:commandButton> that already does this. You can refactor your code to this:
<a4j:commandButton type="button" id="reCallbutton1" value="Search"
styleClass="commandExButton"
action="#{mcifRecallTransBean.reCallSearch}"
reRender="reCallgrid1"
oncomplete="javascript:alert('Search Completed');javascript:document.body.style.cursor='default';" />
Make sure your reCallgrid1 component is available in the same <h:form> of the <a4j:commandButton>.
Since you also want to add a Wait while searching the data behavior when the button is clicked, you can use <a4j:status> along with the <a4j:commandButton> as shown in the <a4j:status> demo. Here's a basic example:
<a4j:commandButton type="button" id="reCallbutton1" value="Search"
styleClass="commandExButton"
action="#{mcifRecallTransBean.reCallSearch}"
reRender="reCallgrid1" />
<!-- Note that there's no oncomplete in this case -->
<a4j:status for="reCallbutton1">
<f:facet name="start">
<h:graphicImage value="/res/images/wait.gif"/>
</f:facet>
</a4j:status>
At last but not least, you should switch your managed bean to request scope and use RichFaces powerful <a4j:keepAlive> in order to simulate JSF 2 #ViewScoped. You can even use it in form of annotation on your managed bean (no additional configuration):
#KeepAlive
public class McifRecallTransBean {
//managed bean code here...
}
When you are using request parameters inside the bean, you need to pass them again with your action :
<h:commandButton type="button" id="reCallbutton1" value="Search" styleClass="commandExButton">
<a4j:support event="onclick" id="ajsf12" oncomplete="javascript:alert('Search Completed');javascript:document.body.style.cursor='default';" action="#{mcifRecallTransBean.reCallSearch}" reRender="reCallgrid1" />
<f:param name="param1" value="#{param['param1']}" />
<f:param name="param2" value="#{param['param2']}" />
</h:commandButton>

Cancel button doesn't work in case of validation error

i have a form with some inputs that have validation (required=true)
and when i click on the cancel button in case of validation error, the cancel button doesn't navigate to previous page, instead it removes the validation error (i think it goes back one step that was before the validation error ?)
here's my code:
<h:form>
<h:inputText value="#{myBean.nickName}" id="nickname" required="true"
requiredMessage="nickname should be specified" />
<h:commandLink immediate="true" id="cancel_link" onclick="history.back(); return false" style="float: left;margin: 118px 189px 0 0;">
<h:graphicImage width="90" height="28" value="#{resource['images:blu_btnCancel.png']}" />
</h:commandLink>
</h:form>
please advise how to fix that.
The JavaScript history.back() function takes you to the previous synchronous request, not to the previous view as you seemed to expect.
Even though the history.back() is terrible this way (unreliable, hackable, etc), a quick fix would be to send an ajax request on form submit instead of a synchronous request.
<h:form>
...
<h:commandButton value="submit">
<f:ajax execute="#form" render="#form" />
</h:commandButton>
</h:form>
Ajax requests doesn't account as browser history.
A more robust way is to just pass the identifier of the previous view along during navigation and then use <h:link> to link back to it. E.g.
<h:link value="Go to next view" outcome="nextview">
<f:param name="from" value="#{view.viewId}" />
<h:link>
And then in the nextview.xhtml
<f:metadata>
<f:viewParam name="from" />
</f:metadata>
...
<h:link ... outcome="#{from}" rendered="#{not empty from}">
<h:graphicImage ... />
</h:link>
If you're navigating by POST, you might consider using the flash scope to remember the initial view.
Unrelated to the concrete problem, the proper way to use <h:graphicImage> with JSF2 resources is to just use its name attribute instead of its value attribute with a #{resource} which is plain clumsy.
Replace
<h:graphicImage width="90" height="28" value="#{resource['images:blu_btnCancel.png']}" />
by
<h:graphicImage name="images/blu_btnCancel.png" width="90" height="28" />
Note that the library name images is here just replaced by the path name. The usage of the name "images" as library name is highly questionable. See also What is the JSF resource library for and how should it be used?

Resources