I have multiple forms, where I have mandatory fields and optional fields.
To submit such a form I require the validation on the required-attribute to be executed, which works fine.
To cancel such a form I use the attribute immediate="true"
on the p:commandbutton
, which makes its action happen during the Apply Request Values-Phase as addressed here: How to skip validation when a specific button is clicked?
However, for large forms I want to provide the user with a Save-Button, so he can proceed later.
For just saving the current state I also want to ignore the validation of the required-attribute. However, using immediate="true"
is not working, because then my save method simple saves nothing, because the JSF lifecycle never hits the "UpdateModelValues"-Phase. (Acording to http://www.javacodegeeks.com/2012/01/jsf-and-immediate-attribute-command.html )
So, how to bypass the required-check but not skip half the lifecycle?
An alternative to what others proposed is to use a custom
BeanValidator
that will validate the form if say, clicked the button with id save. Any other button not implicitly defined to perform validation will not validate but just submit your data available. Find the full nice and clean example hereif you want to skip validation when click on button then easly add parameter to button where you want to skip it. Example:
Then in validator you can read this parameter and if it is true then skip it:
Each Button creates an entry inside the Param-List as long as it's member of the form. So I simple applied a check for the presence of that entry to the "required" parameter:
When I click "Submit" the
param['form:save']
isNULL
, which then turns the expression totrue
so the validation is executed.When I click "Save" the
param['form:save']
isNOT NULL
(but empty!), which resolves tofalse
so the validation is ignored. (Or let's say JSF thinks it is not a required field due to the expression beeing evaluated tofalse
)In my case I didn't find the clientId of the button in the params but I found this
param['javax.faces.source'] = buttonClientId
in the requestmap. The value will be the clientId of the clicked button.This is an excellent question and a very helpful answer. This approach saves a lot of hassle with
immediate="true"
.I'd like to add this info (but am not allowed to comment yet). Your code examples seem to require JSF 2.0 or above (correct me). If you are like me damned to use JSF 1.1/1.2 then consider these changes/additions:
="{true and ...}"
that might be a mistake (no#
)?!empty ...
version when I stumbled upon it.I use skipValidators for such a case (assuming all validations are skipped). Code from omnifaces