How to let validation depend on the pressed button?
Solution 1
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:
Solution 2
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.
Solution 3
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.
Solution 4
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
Roteke
Updated on January 23, 2020Comments
-
Roteke over 4 years
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.
-
Roteke over 12 yearsThat works to bypass the validation, but the form values arrive as null to the itemsBean. And I can't do the filtering. Thanks for your quick answer.
-
Roteke over 12 yearsCould provide a little more detailed example showing where the
save
element should came from? is it a bean? andclientId
a parameter? Like I said before, I'm very new to Java and JSF, and I've been studying a lot. But still I don't know if I'm asking something too basic. Thank you very much for taking the time to answer. -
BalusC over 12 yearsNo, the example is as-is. The
#{save}
is bound to the view. TheclientId
is just its property. See also docs.oracle.com/javaee/6/api/javax/faces/component/…. It's not necessary to bind it to a bean property, unless you'd like to manipulate the component from inside the bean. But if you don't need to, then there's no need to have an unused property in the bean. See also stackoverflow.com/questions/8168302/… -
Roteke over 12 yearsWow there where many things that I didn't know behind this... thanks for your reply, it pointed me out just what I needed to know.
-
nikagra over 12 yearsDoes this solution work case of more complex validators, for example
f:validateLength
? Could it be applied a couple of times during the time of page life? -
Ondrej Bozek over 11 yearsWhy couldn't we use classic immediate attribute with PrimeFaces as we are used to?
-
BalusC over 11 years@Infragile: because it skips update model values. OP's concrete use case implies that he'd like to have the so far entered values in the model anyway.
-
BalusC over 9 yearsThis can be bypassed. You'd better check for something present in JSF view state instead of an arbitrary and fully client-controlled request parameter. See the currently accepted answer.
-
alexander about 9 years@BalusC You marked my question as a duplicate of this one. I got two
<h:comandbutton>
with<f:ajax execute="@form" render="@none" />
(that is exactly the same as a default<p:commandButton>
isn't it?). It works without<f:ajax>
but not with...you may have a look at this. Maybe I am too blind? -
BalusC about 9 years@Alexander: it will fail that way when you use
prependId="false"
or are nesting forms (which was not visible in your question). Just never useprependId
and don't nest forms. -
alexander about 9 years@BalusC I just put (to make sure) that one to my form. No other result. It just fails. Field is still required on both command buttons. Also there are no nested forms.
-
Björn Landmesser over 6 yearsI am using a non-ajax button. The described mechanism works only almost in this case for me (maybe, because I am using bootsfaces). It works when I change the required-Attribute to
required="#{param[save.clientId] != null}"
. This is because, the parameter is passed, but is an empty string (for some reason). -
djmj over 5 yearsJSF should make this a real feature. In ASP.Net. they provides attribute
validationGroup="foo"
on input and buttons to limit the validation scope. An alternate would bevalidatedBy=":myButton1, :myButton2"
. This feature is important in case of composite components where the parent contains the form and submit button. In some gui frameworks the*
will not be rendered in this solution since required is false on render. -
BalusC over 5 years@djmj: that's achievable with Bean Validation (
@NotNull
and friends) and<f:validateBean validationGroups="...">
. -
djmj over 5 years@BalusC thats true but it requires a boilerplate java functional interface for something the markup is responsible of. Thats not programmer friendly so i still prefer the
param
alternative. Components can be loosely coupled to different java classes and thevalue
attribute may not even have a bean assigned since it could be request scoped and directly passed to the action method. The asp.net approach is very easy to use and would be great for JSF. (irony:asp.net
mixed markup and code behind horrible in the past, thats why JSF and asp.net MVC came up). -
Pixelstix about 3 yearsAlmost a decade later, this is still an awesome answer. It is working fine for me with JSF 2.2 and
h:commandButton
; however, not with PrimeFaces 7.0p:commandButton
. Looking at the posted values in the browser dev tools, the value for the button is "" withp:commandButton
, whereas it is "Save and Close" (the text of thevalue
property) forh:commandButton
. Is there some other magic required? I do have ajax="false" on thep:commandButton
. @BalusC (or others), is this a bug with PrimeFaces, or am I doing it wrong?