How to let validation depend on the pressed button? - validation

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?

Related

Mutually exclusive input fields with JSF and PrimeFaces

I have a PrimeFaces application where I would like to make two input text fields mutually exclusive: the user should fill either field, but not both.
In the following example, the user could search contacts either by phone number or by email.
<h:form>
<h:outputLabel>Phone Number:
<h:inputText id="phoneInput" value="#{contactSearch.phone}"
disabled="#{not empty contactSearch.email}">
<p:ajax event="keyup" update="emailInput"/>
</h:inputText>
</h:outputLabel>
<h:outputLabel>Email Address:
<h:inputText id="emailInput" value="#{contactSearch.email}"
disabled="#{not empty contactSearch.phone}">
<p:ajax event="keyup" update="phoneInput"/>
</h:inputText>
</h:outputLabel>
<!-- Possibly other fields... -->
<h:commandButton value="Search" action="#{contactSearch.search}"/>
</h:form>
Is this the proper way to do it? I am concerned about:
Possible "deadlock" issues, where both fields end up being disabled
The whole form being submitted and/or valdiated in the Ajax request, when I just would like to update the disabled state of the input field
Missing some predefined PrimeFaces control which does all the work :)
This is not trivial in standard JSF. JSF utility library OmniFaces has a validator for exactly this purpose, the <o:validateOne>.
<h:inputText id="email" ... />
<h:inputText id="phone" ... />
<o:validateOne components="email phone" />
However, in UX perspective, you'd better redesign your form to provide a single UISelectOne component to select the type and a single UIInput field to enter the value. E.g.
<h:selectOneRadio ... value="#{bean.type}">
<f:selectItem itemValue="email" />
<f:selectItem itemValue="phone" />
</h:selectOneRadio>
<h:inputText ... value="#{bean.value}" />
Update: as server side validation is not affordable and you'd really like to disable the the other without making much ajax traffic, your only bet is using pure JavaScript/jQuery for the job (if necessary in combination with server side validation as fallback).
Here's a generic jQuery based approach:
<h:inputText styleClass="onlyone" a:data-onlyone="groupName" />
<h:inputText styleClass="onlyone" a:data-onlyone="groupName" />
...
$(document).on("input", ":input.onlyone", function() {
var $this = $(this);
var $others = $("[data-onlyone='" + $this.data("onlyone") + "']").not($this);
$others.val(null).attr("disabled", !!$this.val());
});
The data-onlyone value should represent the group name, so you can have multiple of "only one" inputs throughout the document.

Why are fields reset after ajax update with Primefaces

On a form I have some personal information (name, address etc.) and a changeListener which updates the salutation and letter salutation according to the gender and last name. If the underlying entity was already stored in the database it works fine. If I'm entering data for a new (not saved) entry the form gets reset after the listener has been called. All data entered is lost, only the salutation, lettersalutation which I modify in the listener and gender, name which I use and attached a ajax call on are kept.
This is a part of the form:
<h:form id="person">
<p:panel header="#{msg['prs']}">
<h:panelGrid columns="6" cellpadding="4">
<h:outputText value="#{msg['prs.salutation']}"/>
<p:inputText value="#{personBean.selectedPerson.salutation}"/>
<h:outputText value="#{msg['prs.lettersalutation']}"/>
<p:inputText value="#{personBean.selectedPerson.letterSalutation}"/>
<p:spacer/><p:spacer/>
<h:outputText value="#{msg['prs.name']}: "/>
<p:inputText value="#{personBean.selectedPerson.name}">
<p:ajax event="change" update="person"
listener="#{personBean.selectedPerson.updateSalutation}" />
</p:inputText>
<h:outputText value="#{msg['prs.surname']}: "/>
<p:inputText value="#{personBean.selectedPerson.surname}"/>
<h:outputText value="#{msg['prs.gender']}: "/>
<p:selectOneMenu value="#{personBean.selectedPerson.gender}">
<f:selectItems value="#{enumHelper.getEnum('Gender')}"/>
<p:ajax event="change" update="person"
listener="#{personBean.selectedPerson.updateSalutation}" />
</p:selectOneMenu>
</p:panel>
</h:form>
In the code I do then the updates.
public void updateSalutation() {
// simplified
letterSalutation = "...";
salutation = "...";
// outputs for debug
System.out.println(this.getName()); // --> not null
System.out.println(this.getSurname()); // --> null
}
Already here in this call surname, which is not attached to a ajax call is null even though data was entered there. The same is true for all the other fields. In my application I'm using Primefaces, JavaEE 1.6 with Wildfly.
What is the reason for that behavior? Is there anything I can change on my calls to prevent this?
Why are fields reset after ajax update with Primefaces
This problem has 2 possible causes depending on the concrete functional requirement:
It's because you didn't tell JSF to process the desired input values.
Or, it's because you told JSF to also update the non-desired input values.
The solution depends on the cause:
Add process="person" (or process="#form") to <p:ajax> to process the whole form.
Or, edit update="person" to specify only the components which really need to be updated.
Given your complaint in the end of the question, I believe you're looking for #1.
See also:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
My solution:
Include the content that I want to update in a
<p:panel id="toUpdate">
and make a
update="toUpdate"

All dialogs update the backing bean

I have 2 dialogs on a xhtml page:
<p:dialog width="400" id="dialog1" header="Download" widgetVar="dialog1">
<h:outputText value="Field1"/>
<h:inputText value="#{backingBean.field1}"/>
<br/>
<h:outputText value="Field2"/>
<h:inputText value="#{backingBean.field2}"/>
<br/>
<p:commandButton value="Download" ajax="false" onsuccess="PF('diaglog1').hide();">
<p:fileDownload value="#{backingBean.file}"/>
</p:commandButton>
</p:dialog>
<p:dialog width="400" id="dialog2" header="Send" widgetVar="dialog2">
<h:outputText value="Field1"/>
<p:inputText value="#{backingBean.field1}"/>
<br/>
<h:outputText value="Field2"/>
<h:inputText value="#{backingBean.field2}">
<p:ajax update="somePanel"/>
</h:inputText>
<br/>
<h:outputText value="Recipient"/>
<h:panelGroup id="somePanel">
<p:selectOneMenu style="width: 100%;" var="recipient">
<f:selectItems value="#{backingBean.someList}"/>
</p:selectOneMenu>
</h:panelGroup>
<br/>
<p:commandButton value="Send" actionListener="#{backingBean.sendSomething}" onsuccess="PF('dialog2').hide();">
<f:attribute name="item" value="#{recipient}"/>
</p:commandButton>
</p:dialog>
They have different functionality but are on the same page and using the same backing bean. Only one dialog can appear at a time. The problem is when I input some value into the first dialog and press 'Download', it will update the field1 and field2 of the backing bean to the value that I want, but after that the second dialog also updates it to its value, which causes the first one to download the wrong file. If I remove the second dialog, the first will behave correctly.
How do I stop the second dialog from updating the values?
I guess you are keeping both dialogs in one single h:form component.
Then obviously submit in one dialog will submit fields in both dialogs coz, they are in same form.
Don't keep p:dialog inside a h:form, instead use h:form inside
dialog.
You can use multiple h:form s in a page there is no harm in
that, but should not use one h:form in another.
Decide how many forms you can use, based on your design and functionality, In your case you can use 2 h:forms each one inside both dialogs.

How to validate values instantly, but check for required only on full submit?

I am currently adding validation to a form. There are two things to check: The correctness of the value itself (e.g. if it is a positive integer or valid email) and whether all required fields were filled in.
However, if by some means (f:ajax or IceFaces partialSubmit attribute) I make the validation for type correctness happen at once (e.g. when the field loses focus), it will also check the required attribute in this same step. In most cases this is no problem, as the user already entered a value and is likely to correct it rather than go back to a blank field.
However, in the case where he actually wants to clear the field again, he can no longer do so without getting an error. In consequence, I only want to check the required-ness of fields on finally submitting the page.
At the moment, my only idea to separate the two validation types is by performing all required-checks in the backing beans action method, thus tying it to directly to the final submit via button.
Is there another way?
(For background: The reason why one might want to clear the field again is that requirements can change depending on other selections in the form. So one might decide to not provide this field after all and only after that correct the option that actually makes this field optional.)
Just let the required attribute evaluate true when the submit button has really been pressed.
The answer however depends on the way how your submit button executes its logic (standard, f:ajax, ICEfaces, etc). But it basically boils down to that you could check the request parameter map for a request parameter which indicates that the desired submit button has been pressed.
E.g., if it's a standard command button:
<h:form id="form">
...
<h:commandButton id="submit" value="Submit" action="#{bean.submit}" />
</h:form>
Then you could check for it by checking if the button's client ID is present in the request parameter map:
<c:set var="submitButtonPressed" value="#{not empty param['form:submit']}" />
...
<h:inputText ... required="#{submitButtonPressed}" />
<h:inputText ... required="#{submitButtonPressed}" />
<h:inputText ... required="#{submitButtonPressed}" />
Or, if it's a <f:ajax> button:
<h:form id="form">
...
<h:commandButton id="submit" value="Submit" action="#{bean.submit}">
<f:ajax execute="#form" ... />
</h:commandButton>
</h:form>
Then you could check it by checking if javax.faces.source parameter equals the button's client ID:
<c:set var="submitButtonPressed" value="#{param['javax.faces.source'] == 'form:submit'}" />
...
<h:inputText ... required="#{submitButtonPressed}" />
<h:inputText ... required="#{submitButtonPressed}" />
<h:inputText ... required="#{submitButtonPressed}" />
You could even combine both:
<c:set var="submitButtonPressed" value="#{not empty param['form:submit'] or param['javax.faces.source'] == 'form:submit'}" />
...
<h:inputText ... required="#{submitButtonPressed}" />
<h:inputText ... required="#{submitButtonPressed}" />
<h:inputText ... required="#{submitButtonPressed}" />

How to skip validation on certain fields in JSF 2 when required

I have two p:dialog. Each one contains some input fields which are marked as required. Only one dialog is shown at a time but when I submit on any of the dialog, JSF also validates the input fields of the dialog which is not shown. What is the best approach to skip the validations in JSF 2 for the dialog which is not shown. One approach could be that I set the required="condation". But dont know what that condition could be and is it goin to work.
Each dialog is initially hidden. Each one has its own button to show. When one is active and I click the save button there is a validation error even when the required field has values. The validation error comes from the inactive dialog panel. May be it give some idea what i am trying to do.
UPDATE
<p:dialog header="Edit Group" widgetVar="dialog_groupEdit" resizable="false"
width="300" showEffect="bounce" hideEffect="explode" modal="true" position="center">
<h:panelGrid id="panel_groupEdit" columns="2">
<h:outputText value="Group Name: "/>
<h:inputText id="input_gnameEdit" size="26" value="#{groupBean.selectionGroup.gname}" required="true" requiredMessage="Edit Group: Name is required."/>
<h:outputText value="Description:"/>
<h:inputTextarea rows="6" cols="23" value="#{groupBean.selectionGroup.description}"/>
<div></div>
<p:commandButton value="Save" action="#{groupBean.saveGroupChanges}" oncomplete="#{args.validationFailed ? '':'dialog_groupEdit.hide()'}"
update="panel_groups panel_groupEdit" style="float:right;"/>
<div></div>
<p:message for="input_gnameEdit"/>
</h:panelGrid>
</p:dialog>
<p:dialog header="New Group" widgetVar="dialog_groupCreate" resizable="false"
width="300" showEffect="bounce" hideEffect="explode" modal="true" position="center">
<h:panelGrid id="panel_groupCreate" columns="2">
<h:outputText value="Group Name: "/>
<h:inputText id="input_gnameCreate" size="26" value="#{groupBean.createGroup.gname}" required="true" requiredMessage="New Group: Name is reqired."/>
<h:outputText value="Description:"/>
<h:inputTextarea rows="6" cols="23" value="#{groupBean.createGroup.description}"/>
<div></div>
<p:commandButton value="Save" actionListener="#{groupBean.saveGroupCreate}" oncomplete="#{empty groupBean.createGroup.gname ? ' ':'dialog_groupCreate.hide()'}"
update="panel_groupCreate panel_groups" style="float:right;"/>
<div></div>
<p:message for="input_gnameCreate"/>
</h:panelGrid>
</p:dialog>
One approach could be that I set the required="condation".
This is going to be clumsy. Just put each individual form in its own separate <h:form> component, or use the process attribute of the <p:commandButton> to identify the region you'd like to process.
<p:commandButton process="panel_groupEdit" ... />
...
<p:commandButton process="panel_groupCreate" ... />
Having a "God" form is in any way a poor practice.
See also:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
How to use <h:form> in JSF page? Single form? Multiple forms? Nested forms?
When you are using <p:dialog some of the good practices as advised on the PF forum are -
Never put your <p:dialog inside any other component. Place it somewhere so that it falls right under the <h:body.
Give every <p:dialog it's own form. But, don't place the dialog inside the form, place the form inside the dialog. It's not good to update the dialog itself, only it's content. (I think this should solve your issue also.)
e.g.
<p:dialog widgetVar="dlg" ...
<h:form ...
<h:panelGroup id="dlgContent" ...

Resources