I have a requirement to create a javascript function that, when called, will save all valid components in the form of JSF 2.0. Since the full form will never be valid in general, I need to figure out a way to start the life cycle for each component, so that if the validation phase is successful, the model will be updated and ultimately saved.
Ideally, this should be the only ajax request, since iterating over each component using a separate ajax request will be painfully inefficient.
Has anyone solved the problem before? If you could not give me some pointers on possible implementations?
Edit:
Here is what seems to work for me so far:
@ManagedBean(name = "partialAppSaveBean") @RequestScoped public class PartialAppSaveBean implements Serializable { protected static final Logger LOGGER = LoggerFactory.getLogger(PartialAppSaveBean.class); private static final long serialVersionUID = 1L; public void saveData(AjaxBehaviorEvent event) { final FacesContext context = FacesContext.getCurrentInstance(); UIForm form = getParentForm(event.getComponent()); Set<VisitHint> hints = EnumSet.of(VisitHint.SKIP_UNRENDERED); form.visitTree(VisitContext.createVisitContext(context, null, hints), new VisitCallback() { @Override public VisitResult visit(VisitContext context, UIComponent component) { if (component instanceof UIInput) { UIInput input = (UIInput) component; input.validate(context.getFacesContext()); if (input.isValid() && input.getValue() != null) { ValueExpression valueExpression = input.getValueExpression("value"); if (valueExpression != null && valueExpression.getExpressionString() != null) { try { valueExpression.setValue(context.getFacesContext().getELContext(), input.getValue()); } catch (Exception ex) { LOGGER.error("Expression [ " + valueExpression.getExpressionString() + "] value could not be set with value [" + input.getValue() + "]", ex); } } } } return VisitResult.ACCEPT; } });
Called with something like:
<h:commandButton id="saveData"> <f:ajax listener="#{partialAppSaveBean.saveData}" execute="@form" immediate="true" onevent="onPartialSave" /> </h:commandButton>
source share