35

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.

Elrond_EGLDer
  • 47,430
  • 25
  • 189
  • 180
Roteke
  • 633
  • 2
  • 8
  • 12

4 Answers4

65

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:

Community
  • 1
  • 1
BalusC
  • 992,635
  • 352
  • 3,478
  • 3,452
  • 4
    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. – Roteke Dec 04 '11 at 23:34
  • 2
    No, the example is as-is. The `#{save}` is bound to the view. The `clientId` is just its property. See also http://docs.oracle.com/javaee/6/api/javax/faces/component/UIComponent.html#getClientId%28%29. 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 http://stackoverflow.com/questions/8168302/jsf-component-binding-without-bean-property – BalusC Dec 04 '11 at 23:40
  • 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. – Roteke Dec 05 '11 at 04:27
  • 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? – nikagra Dec 16 '11 at 20:26
  • 1
    Why couldn't we use classic immediate attribute with PrimeFaces as we are used to? – Ondrej Bozek Oct 30 '12 at 09:56
  • @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 Oct 30 '12 at 10:05
  • @BalusC You marked my question as a duplicate of this one. I got two `` with `` (that is exactly the same as a default `` isn't it?). It works without `` but not with...you may have a look at this. Maybe I am too blind? – alexander Apr 27 '15 at 08:29
  • @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. – BalusC Apr 27 '15 at 08:32
  • @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. – alexander Apr 27 '15 at 08:33
  • 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). – Björn Landmesser Jan 05 '18 at 14:28
  • 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. – djmj Nov 15 '18 at 13:22
  • @djmj: that's achievable with Bean Validation (`@NotNull` and friends) and ``. – BalusC Nov 15 '18 at 16:08
  • @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). – djmj Nov 15 '18 at 21:31
  • 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? – Pixelstix Mar 05 '21 at 22:44
9

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.

mnesarco
  • 2,036
  • 16
  • 24
  • 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. – BalusC Aug 09 '14 at 14:41
6

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.

Community
  • 1
  • 1
Cristian Arteaga
  • 193
  • 2
  • 11
2

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?

Community
  • 1
  • 1
mprabhat
  • 19,229
  • 7
  • 42
  • 62
  • 1
    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 Dec 03 '11 at 20:35