关于验证:JSF 2 —保存所有有效组件值

JSF 2 — Save All Valid Component Values

我需要创建一个JavaScript函数,该函数在被调用时会将所有有效组件保存在JSF 2.0表单上。由于完整的表格将永远不会有效,因此我需要找出一种方法来运行每个组件的生命周期,以便在验证阶段成功后,将更新模型并最终保存模型。

理想情况下,这需要是一个单一的ajax请求,因为使用单独的ajax请求在每个组件上进行迭代将非常低效。

以前有人解决过这个问题吗?如果不能,您能否给我一些可能的实现的指导?

编辑:

这是我目前为止似乎运作良好的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
@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;
    }

}

调用了类似以下内容的内容:

1
2
3
4
<h:commandButton
    id="saveData">
    <f:ajax listener="#{partialAppSaveBean.saveData}" execute="@form" immediate="true" onevent="onPartialSave" />
</h:commandButton>

您可以在UIForm上使用UIComponent#visitTree()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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;
    }
});