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
private void toggleValidators(UIComponent parent, boolean toggle) {
List<UIComponent> children = parent.getChildren();
Iterator<UIComponent> iterator = children.iterator();
while (iterator.hasNext()) {
UIComponent child = iterator.next();
if (child instanceof javax.faces.component.UIInput) {
if (child instanceof com.ibm.xsp.component.UIInputEx) {
UIInputEx input = (UIInputEx) child;
input.setDisableValidators(toggle);
if (0 < child.getChildCount()) {
toggleValidators(child, toggle);
}
} else if (child instanceof com.ibm.xsp.component.UISelectOneEx) {
// radio/checkbox/combobox etc.
UISelectOneEx input = (UISelectOneEx) child;
input.setDisableValidators(toggle);
if (0 < child.getChildCount()) {
toggleValidators(child, toggle);
}
}
} else {
if (0 < child.getChildCount()) {
toggleValidators(child, toggle);
}
}
}
}
- add an event parameter to all your buttons where you do want to trigger the validation
et voilà.. you have a nice working form where validators are only triggered when really required (ie. upon save)!
no more stupid validations kicking-in when switching tabs, clicking buttons, refreshing via combo boxes panels etc…
as for the “Save as draft” button: I would recommend that you add a field on the form “flagIsDraft” so that you can take care of not postprocessing such documents
Kudos go to Tommy Valand and weihang chen, their “blogs” helped me get my way through!