remember? it was first days, then hours, okay, today hours as well.. but I think with some help of you guys out there blogging also I found the final solution, and the times do get better and better, as I get more and more knowledge about the whole thing.
summary:
- use the PhaseListener to catch the phase: PROCESS_VALIDATIONS
- add some code to the beforePhase event (to disable the validators for all but the required events)
- add some code to the afterPhase event (to enable the validators again)
- add a recursive method which will enable/disable (ie toggle) all available validators
- add event parameters to your buttons where you DO WANT TO trigger the validators
PhaseListener updates:
- add this code in the beforePhase method, it will disable the validators if no event parameters (name=requireValidation, value=true) are present
FacesContext facesContext = event.getFacesContext();
try {
// handle validators
if (event.getPhaseId().equals(PhaseId.PROCESS_VALIDATIONS)) {
// add validators if required
// i use:
//CustomValidator v = new CustomValidator();
//v.handleValidators();
// if not submitted via save button disable validators
// get eventHandlerClientId
String eventHandlerClientId = (String) facesContext
.getExternalContext().getRequestParameterMap().get(
“$$xspsubmitid”);
// extract eventHandlerId
String eventHandlerId = eventHandlerClientId.substring(
eventHandlerClientId.lastIndexOf(“:”) + 1,
eventHandlerClientId.length());
// get eventHandler “component”
UIEventHandler eventHandler = (UIEventHandler) Util
.findComponent(facesContext.getViewRoot(),
eventHandlerId);
// find the parameters set via Edit Event parameters on the
// Events page
boolean skipValidation = true;
List<Parameter> parameters = eventHandler.getParameters();
if (null != parameters) {
Iterator<Parameter> iterator = parameters.iterator();
while (iterator.hasNext()) {
Parameter par = iterator.next();
if (par.getName().equals(“requireValidation”)
&& par.getValue().equals(“true”)) {
skipValidation = false;
break;
}
}
}
if (skipValidation) {
toggleValidators(facesContext.getViewRoot(), true);
}
}
} catch (Exception e) {
// default disable validations for all other events which are not
// “requireValidation=true” and which might throw an error while trying to get their event handler
toggleValidators(facesContext.getViewRoot(), true);
}
- add this code to the afterPhase, it will enable the validators again:
if (event.getPhaseId().equals(PhaseId.PROCESS_VALIDATIONS)) {
FacesContext facesContext = event.getFacesContext();
toggleValidators(facesContext.getViewRoot(), false);
}
- add this method, it will recursively find all components where validators might be existing and enables/disables them. This method is most likely candidate for speed improvements: You could use as parent component the actual tab (for tabbed panels) being displayed, but then you would have to track which one is selected, I prefer to just run it on the whole tree to make it simple for now
- add an event parameter to all your buttons where you do want to trigger the validation
Why not simply set disableValidators="true" on the button?
because I wanted it the other way around: instead of having to "disable" the validators I wanted to "enable" them specifically only on the 2 save buttons
Ulrich, there are also other use cases, like the download control triggering validation when you delete a file. No way around it.
Great stuff!