How to parameterize an a4j:commandLink properly? - jsf

I have the following problem: I need to redirect from a "list page" to a details page, but I need the id from the list. "record" in this example is the var attribute of a rich:dataTable. First of all I thought about this:
<a4j:commandLink id="detailsLink" value="show details" execute="#this" action="/customerDetails?faces-redirect=true&cusid=#{record.id}" />
But this is invalid syntax, so I tried something like this:
<a4j:commandLink id="detailsLink" value="show details" execute="#this" action="/customerDetails?faces-redirect=true">
<f:attribute name="cusid" value="#{record.id}"/>
</a4j:commandLink>
(I even tried f:param)
On the target page I tried to receive the value with...
<f:metadata>
<f:viewParam required="false" name="cusid" value="#{customerBean.editCustomer}"/>
</f:metadata>
Basically f:metadata works, because when I try it with the following hard coded parameter, I receive its value:
<a4j:commandLink id="detailsLink" value="show details" execute="#this" action="/customerDetails?faces-redirect=true&cusid=120" />
I found a solution, but I'm not sure if this is the right way:
In customerBean I make the following:
public String editCustomer(long customerId)
{
edit(customerId);
return "/customerDetails?faces-redirect=true";
}
But I don't think that this is the usual way to send and receive parameters with Rich Faces. Is there maybe a better solution?

The <a4j:commandLink> sends an ajax POST request while you need a normal GET request. Use <h:link> instead.
<h:link value="show details" outcome="/customerDetails?cusid=120" />

Here's the best way to do it. The example provided passes 2 parameters. You can have more than one. Just use the assignTo attribute and the value attribute. Hope this answers your question.
<a4j:commandLink action="#{myBackingBean.myAction}">
<a4j:param name="jobIdParam" value="#{job.jobNumber}"
assignTo="#{myBackingBean.jobId}" />
<a4j:param name="isDisplayedParam" value="true"
assignTo="#{myBackingBean.displayed}"/>
</a4j:commandLink>

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.

JSF action not called OR selectbox value is null

i have another strange JSF problem here... I don´t really know why, but what ever i try to do, i have one out of two problems. Either the action method inside my popupPanel is not (means never) called or it is called, but the value from my selectBox is (always) null. Can´t figure out, what the problem is, but it seems to me, like it´s a XHTML property problem.
Already tried to put the popupPanel outside my h:form (helped me at some other locations...), i also tried to put it outside and put another form into my popup. Beyond that i was trying to change the attachment to parent/form and i changed the execute of the commandButton inside my popup to form/form-id/popuppanel-id and i guess there were some more things i did... but nothing helped.
The Bean is session scoped and i am using Richface 4.0 Final if it does matter at all.
What ever, the XHTML looks like this:
<rich:popupPanel
header="#{label['edit.title']} #{mandateAction.ccService.mandateList[mandateAction.currentIndex].id}"
id="addExternalSystem"
onmaskclick="#{rich:component('addExternalSystem')}.hide()"
domElementAttachment="form" autosized="true" layout="block">
<h:panelGrid columns="2">
<h:outputText value="#{label['login.username']}" />
<h:inputText
value="#{mandateAction.newExternalSystem.username}" />
<h:outputText value="#{label['login.password']}" />
<h:inputSecret
value="#{mandateAction.newExternalSystem.password}" />
<h:outputText value="#{label['mandate.externalSystem']}" />
<h:selectOneMenu
value="#{mandateAction.newExternalSystem.externalSystem}">
<f:selectItems
value="#{creditcardConfigurationService.externalSystems}"
itemLabel="#{system.name}" itemValue="#{system}"
var="system" />
<f:converter binding="#{externalSystemConverter}" />
</h:selectOneMenu>
....
<a4j:commandButton value="#{label['insert.save']}"
action="#{mandateAction.insertNewSystem}"
render="mandate_table" execute="#form"
oncomplete="if (#{facesContext.maximumSeverity==null}) {#{rich:component('addExternalSystem')}.hide();}" />
If your page have any of the required fields kept as empty the submit from the popup panel will not work. In that case include the popup panel inside a form and domElementAttachment="form" , and perform the submit.

How to implement the image redirect with parameters?

This is the way how a commandButton realizes the redirect with parameters.
<h:commandButton value="Check" action="#{GetInfoBean.getInfo}">
<f:param name="ID" value="4"></f:param>
</h:commandButton>
When this commandButton get clicked, it will pass the parameter named ID with value 4. The managed bean GetInfoBean's method getInfo() will return the new url.
But now, my question is how can I implement this redirect process using image or graphicImage since it doesn't have the action attribute?
Wrap the image using a <h:commandLink>:
<h:commandLink value="Check" action="#{GetInfoBean.getInfo}">
<f:param name="ID" value="4"></f:param>
<h:graphicImage value="/your/image.png" />
</h:commandLink>

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?

Trying to understand why h:commandLink submits through validation and a4j:commandLink doesn't

First of all, i'm using Jsf 1.2...
I have a problem with submitting some values in a form to validation.
Specifically this code segement:
<h:panelGrid columns="4" id="StatusPanel">
<h:outputText value="#{msg.Phone_number_to_send_SMS_to}" />
<h:inputText id="phoneNumber" value="#{general.smsPhoneNumber}" required="true"
requiredMessage="Please enter a valid phone number." />
<a4j:commandLink value="#{msg.Submit_Button}"
reRender="pinCodeDeliveryMsgText, pinCodeDeliveryMsg, pinCodeDeliveryFailedMsg, pinCodeDeliveryMainPanel, LastPinCodeMsg, SendingSMSMSG"
action="#{general.submit}" />
<h:message for="phoneNumber" fatalClass="mandatoryFieldMissing" errorClass="mandatoryFieldMissing" tooltip="true" />
</h:panelGrid>
Which looks like this in the html page:
Whenever I press the submit link, the page doesn't really go through validation, it seems to go with the last successull values instead. The result being that, if the phone number field is left empty, it does nothing and doesn't even render the <h:message> tag.
Actually, I have a workaround fix that looks like this:
<h:commandLink value="#{msg.Submit_Button}">
<a4j:support event="onclick" reRender="pinCodeDeliveryMsgText, pinCodeDeliveryMsg, pinCodeDeliveryFailedMsg, pinCodeDeliveryMainPanel, LastPinCodeMsg, SendingSMSMSG"
action="#{general.submit}"/>
</h:commandLink>
But i'm really curious to know what's the difference between a4j:commandLink and h:commandLink that makes one woirk and the other not.
TnX
Have you tried to set the process attribute of a4j:commandLink to the id of the inputText? Looks like you are just triggering rerendering of some components, so no model update is performed at all.

Resources