JSF 2 - сохранить все допустимые значения компонентов
У меня есть требование создать функцию javascript, которая при вызове сохранит все допустимые компоненты в форме JSF 2.0. Поскольку полная форма никогда не будет действительной в целом, мне нужно найти способ запустить жизненный цикл для каждого компонента, чтобы в случае успешного завершения этапа проверки модель была обновлена и в конечном итоге сохранена.
В идеале это должен быть один ajax-запрос, поскольку итерации по каждому компоненту с отдельным ajax-запросом были бы крайне неэффективными.
Кто-нибудь решил проблему раньше? Если нет, не могли бы вы дать мне несколько советов о возможных реализациях?
Редактировать:
Вот то, что у меня, похоже, хорошо работает до сих пор:
@ManagedBean(name = "partialAppSaveBean")
@RequestScoped
public class PartialAppSaveBean implements Serializable {
protected static final Logger LOGGER = LoggerFactory.getLogger(PartialAppSaveBean.class);
private static final long serialVersionUID = 1L;
/**
* Save any valid Application values
*
* @param event
*/
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;
}
});
//Save data here
}
/**
* Returns the parent form for this UIComponent
*
* @param component
* @return form
*/
private static UIForm getParentForm(UIComponent component) {
while (component.getParent() != null) {
if (component.getParent() instanceof UIForm) {
return (UIForm) component.getParent();
} else {
return getParentForm(component.getParent());
}
}
return null;
}
}
Вызывается с чем-то вроде:
<h:commandButton
id="saveData">
<f:ajax listener="#{partialAppSaveBean.saveData}" execute="@form" immediate="true" onevent="onPartialSave" />
</h:commandButton>
1 ответ
Вы могли бы использовать UIComponent#visitTree()
на UIForm
,
FacesContext context = FacesContext.getCurrentInstance();
UIForm form = getFormSomehow();
Map<String, Object> validValues = new HashMap<String, Object>();
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;
if (input.isValid()) {
validValues.put(input.getClientId(context.getFacesContext()), input.getValue());
}
}
return VisitResult.ACCEPT;
}
});