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

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.

Related

Primefaces dialog doesn't update when is open [duplicate]

I have created form and I want to show previous existing items on a table while a new one is creating. I'd like to show matching items as form is filling up. But when I try to filter the list without having the form completed, the validation messages appear and the table doesn't get updated.
Don't know if it's possible, but what I want to do something like this:
<h:form id="form">
<h:outputText value="Name: "/>
<p:inputText value="#{itemsBean.name}" id="name" required="true"/>
<br/>
<h:outputText value="Description: "/>
<p:inputText value="#{itemsBean.description}" id="description" required="true"/>
<p:commandButton value="Save" update="form" actionListener="#{itemsBean.save}"/> //validate and save
<p:commandButton value="Filter" update="form" actionListener="#{itemsBean.updateItemsList}"/> //don't validate, and update the table.
<p:dataTable id="list" value="#{itemsBean.itemsList}" var="item">
<p:column>
<h:outputText value="#{item.name}"/>
</p:column>
<p:column>
<h:outputText value="#{item.description}"/>
</p:column>
</p:dataTable>
</h:form>
I'm very new to JSF.
I understand that you want to filter based on the name input field. The <p:commandButton> sends by default an ajax request and has a process attribute wherein you can specify which components you'd like to process during the submit. In your particular case, you should then process only the name input field and the current button (so that its action will be invoked).
<p:commandButton process="#this name" ... />
The process attribute can take a space separated collection of (relative) client IDs of the components, wherein #this refers to the current component. It defaults in case of <p:commandButton> to #form (which covers all input fields of the current form and the pressed button), that's why they were all been validated in your initial attempt. In the above example, all other input fields won't be processed (and thus also not validated).
If you however intend to skip the required validation for all fields whenever the button in question is been pressed, so that you can eventually process multiple fields which doesn't necessarily need to be all filled in, then you need to make the required="true" a conditional instead which checks if the button is been pressed or not. For example, let it evaluate true only when the save button has been pressed:
<p:inputText ... required="#{not empty param[save.clientId]}" />
...
<p:inputText ... required="#{not empty param[save.clientId]}" />
...
<p:commandButton binding="#{save}" value="Save" ... />
This way it won't be validated as required="true" when a different button is pressed. The trick in the above example is that the name of the pressed button (which is essentially the client ID) is been sent as request parameter and that you could just check its presence in the request parameter map.
See also:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
I Have tested this with non-ajax submits:
<p:inputText ... required="#{not empty param.includeInSave1}" />
...
<p:inputText ... required="true" />
...
<p:commandButton value="Save1" ajax="false">
<f:param name="includeInSave1" value="true" />
</p:commandButton>
<p:commandButton value="Save2" ajax="false" />
The first input is required validated only on Save1 button submit.
Additionally to the BalusC answer (very useful and complete) I want to add that when you use a <h:commandButton /> it will validate (required, custom validations) all the fields in the <h:form /> where the command button is located, therefore when you need to use more than one command button you could consider that it is a good practice to use different <h:form /> to different responsibilities to avoid unexpected behavior in submit actions of the command buttons.
It is well explained in a BalusC answer: Multiple h:form in a JSF Page
If your form has validations and you do not update the <h:form /> or you do not show messages, you could get a headache thinking that the <h:commandButton /> is not firing your action, but likely is a validation problem that has not been shown.
Change your filter commandbutton like this to ignore validation:
<p:commandButton value="Filter" update="list" actionListener="#{itemsBean.updateItemsList}" process="#this"/>
EDIT:
The related post on SO, I think this will solve your issue too
JSF 2.0: How to skip JSR-303 bean validation?

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.

JSF 2 - No way to do Required Inputs + Clear (Immediate) Button?

This question is similar to the question here but that solution doesn't work here.
Take this simple-to-the-max example:
<h:form>
<h:inputText required="true" value="#{mrBean.someValue}" />
<h:inputText required="true" value="#{mrBean.someValue2}" />
<h:commandButton value="Submit">
<f:ajax execute="#form" />
</h:commandButton>
<h:commandButton immediate="true" action="#{mrBean.clearAllValues}" value="Clear">
<f:ajax render="#form" />
</h:commandButton>
</h:form>
And the bean Code:
public void clearAllValues() {
setSomeValue(null);
setSomeValue2(null);
}
Take this scenario:
Enter 'X' value in first input
Submit it using the 'Submit' Button. (failed in validation)
Enter 'Y' into the same input.
Click the 'Clear' button.
Result: Inputs don't clear and value of first input returns to 'X'.
I would expect this scenario to clear the input values but it doesn't, instead, it restores 'X' which is the previously submitted value. It actually never really runs mrBean.getSomeValue() on the bean (Which would have returned null and clear the input field)
The problem is related to JSF not working well with required fields and immediate. I wonder if anyone managed to overcome this problem.
Thanks!
Ben.
Your code example is oversimplified. The described problem symptoms will only occur when you have multiple required inputs. Add one more required input field to the example. Fill out only one of them. A validation error will occur for the empty one. Then enter something else in both and press clear. The valid input will indeed retain the previously submitted value.
This problem is described in detail in this question and this blog article. The solution boils down to collecting all to-be-cleared input components and calling EditableValueHolder#resetValue() on each of them. This can be done with a <f:actionListener> as shown in the blog article.
Another way in your particular case since you just want to clear out the entire form is to use a <h:button> which will basically just refresh the page. If your bean is request or view scoped then it will also be recreated with all properties set to default.
<h:form>
<h:inputText required="true" value="#{mrBean.someValue}" />
<h:commandButton value="Submit">
<f:ajax execute="#form" />
</h:commandButton>
<h:button value="Clear" />
</h:form>
Are you sure clearAllValues is executed? Do you get any errors in the logs or console?
Try adding execute
<f:ajax render="#form" execute="#this">

ValueChangeListener problem

While calling the ValueChangeListener in JSF based on value change in dropdown, it is calling all the ValueChangeListner that are on that page.
There are two valueChangeListener in DataTable, while changing value in one dropdwon the 2nd one also executing.
<t:column id="avlId" styleClass="coltextcenteralign">
<f:facet name="header">
<h:panelGroup>
<h:outputText value="#{bundle['travelLocalAccommodation.title.availability']}" />
<h:outputText value="*" style="color:red" />
</h:panelGroup>
</f:facet>
<t:selectOneMenu value="#{accomDtls.availability}" immediate="true"
valueChangeListener="#{TravelProcessingBB.localAccommodationBB.setAvailableFlag}" forceid="true" id="avl"
onchange="return availabilityAlert('#{accomDtls.prepopulatedFlag}','avl[#{table_count}]')"
styleClass="dropDownStyle" style="width:50">
<f:selectItem itemValue="Y" itemLabel="Yes" />
<f:selectItem itemValue="N" itemLabel="No" />
</t:selectOneMenu>
</t:column>
The value change alone won't automatically call the valueChangeListener. You need to submit the form as well. A commonly used "hack" is to call form.submit() using JavaScript during the onchange event. This will however submit the entire form. Truly the valueChangeListener will be triggered for all changed fields of the form.
To fix this in JSF 1.x, you need to hassle somewhat with the immediate attribute to skip all other form components from validating and with component binding so that you can properly get/set the other component's value. Long story short, I ever wrote an article about that: populate child menus in JSF 1.2.
In JSF 2.0, this is however easier to achieve with help of <f:ajax> tag. If you're really using JSF 2.0 (your current question doesn't indicate that), then let me know if you need an example.

Form value not passed to Seam bean after a4j reRender

I'm making a webapp in Seam but ran into a problem I can't seem to fix.
I have a JSF form where the customer can select a reservation type through a combobox. Based on the selected value, other form components gets rendered.
For example: the customer selects Hours as reservation type, a panelGroup gets rendered where the customer can select a start- and an end hour. But if the customer would select 'part of the day' as reservation type, a selectOneMenu gets rendered where the customer can select a part of the day (morning, afternoon, evening)
The rerendering well but the values of the components with a rendered conditional won't get passed to the bean. They stay null values.
This is the code i'm talking about:
<s:div id="spot"
rendered="#{selectedProduct.productType.name eq 'Flex Spot'}">
<h:panelGrid columns="2">
<h:outputText value="Reservation Type" />
<h:selectOneMenu value="#{selectedPeriodPart}">
<s:selectItems
value="#{productManager.getAvailableDayPartsSpot()}"
var="daypart"
label="#{daypart.label}"></s:selectItems>
<s:convertEnum />
<a4j:support ajaxSingle="true"
event="onchange"
action="#"
reRender="spot">
</a4j:support>
</h:selectOneMenu>
<h:outputText id="date_spot" value="Date" />
<a4j:outputPanel id="calendar_spot" layout="block">
<rich:calendar value="#{reservation.reservationPeriod.startDate}"
locale="en" cellWidth="24px"
cellHeight="22px"
style="width:200px" />
</a4j:outputPanel>
<h:outputText rendered="#{selectedPeriodPart eq 'DAY_PART'}"
value="Daypart" />
<h:selectOneMenu value="#{selectedDaypart}"
rendered="#{selectedPeriodPart eq 'DAY_PART'}">
<f:selectItem id="si_morning" itemLabel="Morning (6:00 - 12:00)"
itemValue="morning" />
<f:selectItem id="si_afternoon"
itemLabel="Afternoon (12:00 - 18:00)" itemValue="afternoon" />
<f:selectItem id="si_evening" itemLabel="Evening (18:00 - 00:00)"
itemValue="evening" />
</h:selectOneMenu>
<h:outputText rendered="#{selectedPeriodPart eq 'HOURS'}"
value="Hours" />
<h:panelGroup id="hours_spot"
rendered="#{selectedPeriodPart eq 'HOURS'}">
<ui:include src="/includes/reservation/select_hours.xhtml" />
</h:panelGroup>
</h:panelGrid>
</s:div>
Note: The calendar value do get passed back to the bean but the value of this piece of code doesn't (it does if you remove the rendered conditional):
selectOneMenu value="#{selectedDaypart}" rendered="#{selectedPeriodPart eq 'DAY_PART'}"
You need to ensure that the conditionals responsible for the outcome of the rendered attribute are also the same in the subsequent request of the form submit. Because when a component isn't rendered, JSF won't apply the request values them.
In a nutshell, the property behind #{selectedPeriodPart} needs to be the same in the subsequent request. There are several solutions:
Put bean in session scope. Easiest solution, but bad for server memory and client experience (updates would be reflected in multiple tabs/windows in same session).
Pass it through using <h:inputHidden>. Not sure though how this fits in the Ajax/Richfaces picture. Better use <a4j:keepAlive> here.
Use a conversation scope. Seam offers facilities for this.
I fixed it -.- Nothing was wrong with the code I posted.
Because I wasn't able to solve this issue I continued on an other page in the same conversation. I noticed some more strange behaviour: outjection of a variable didn't work etc.
I figured the mistake was in some other part of the code which, after corrected, fixed the whole problem.
Thx for answering guys!

Resources