How to let validation depend on the pressed button?

39,994

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

JSF 2.0: How to skip JSR-303 bean validation?

Share:
39,994
Roteke
Author by

Roteke

Updated on January 23, 2020

Comments

  • Roteke
    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
    Roteke over 12 years
    That 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
    Roteke over 12 years
    Could provide a little more detailed example showing where the save element should came from? is it a bean? and clientId 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
    BalusC over 12 years
    No, the example is as-is. The #{save} is bound to the view. The clientId 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
    Roteke over 12 years
    Wow 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
    nikagra over 12 years
    Does 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
    Ondrej Bozek over 11 years
    Why couldn't we use classic immediate attribute with PrimeFaces as we are used to?
  • BalusC
    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
    BalusC over 9 years
    This 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
    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
    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 use prependId and don't nest forms.
  • alexander
    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
    Björn Landmesser over 6 years
    I 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
    djmj over 5 years
    JSF 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 be validatedBy=":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
    BalusC over 5 years
    @djmj: that's achievable with Bean Validation (@NotNull and friends) and <f:validateBean validationGroups="...">.
  • djmj
    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 the value 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
    Pixelstix about 3 years
    Almost 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.0 p:commandButton. Looking at the posted values in the browser dev tools, the value for the button is "" with p:commandButton, whereas it is "Save and Close" (the text of the value property) for h:commandButton. Is there some other magic required? I do have ajax="false" on the p:commandButton. @BalusC (or others), is this a bug with PrimeFaces, or am I doing it wrong?