JSF 2 -- 保存所有有效的组件值

Posted

技术标签:

【中文标题】JSF 2 -- 保存所有有效的组件值【英文标题】:JSF 2 -- Save All Valid Component Values 【发布时间】:2012-05-31 08:00:19 【问题描述】:

我需要创建一个 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】:

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

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;
    
);

【讨论】:

不错。如果 input.isValid() 是否有一种简单的方法来转换值并更新组件绑定到的模型? 嗯,这取决于功能要求。表单是否已经预先提交/无效,因此您只做&lt;f:ajax execute="@this"&gt;?还是您想提交并处理整个表单并接管 JSF 验证?如果是后者,在if (input.isValid()) 之前调用input.validate(context.getFacesContext())。顺便说一句,这也将执行转换。它不会更新模型值,因此您必须通过input.getValue() 获取它。 要求是,当用户尝试退出时,我会使用 onbeforeunload 方法提示他们是否要保存数据(即使数据不完整),所以我会调用 。然后我需要更新有效 UIInput 元素的模型并保存模型层次结构。 我明白了。顺便说一下,这对于 OmniFaces 来说是一个有趣的想法。 这将是对已经非常出色的项目的最出色的补充。我认为您提供的蓝图应该可以满足我今天的需要。是时候编写一些代码了。

以上是关于JSF 2 -- 保存所有有效的组件值的主要内容,如果未能解决你的问题,请参考以下文章

JSF教程——生命周期之Apply Request Values Phase

具有渲染属性的jsf组件验证失败

jsf 2.0 自定义组件/标签不复合

JSF 2.0 部分状态保存似乎不起作用

带有 JSF 项目的组件库

为啥 JSF 将 UI 组件的状态保存在服务器上?