Validation JSF2——保存所有有效的组件值

Validation JSF2——保存所有有效的组件值,validation,jsf,jsf-2,components,partial,Validation,Jsf,Jsf 2,Components,Partial,我需要创建一个javascript函数,当调用该函数时,它会将所有有效组件保存在JSF2.0表单上。因为完整的表单永远不会作为一个整体有效,所以我需要找出一种方法来运行每个组件的生命周期,这样,如果验证阶段成功,模型将被更新并最终保存 理想情况下,这需要是一个单独的ajax请求,因为使用单独的ajax请求迭代每个组件会非常低效 以前有人解决过这个问题吗?如果没有,你能给我一些关于可能实现的建议吗 编辑: 以下是我所拥有的到目前为止似乎运行良好的产品: @ManagedBean(name = "p

我需要创建一个javascript函数,当调用该函数时,它会将所有有效组件保存在JSF2.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;
    }

}
@ManagedBean(name=“partialAppSaveBean”)
@请求范围
公共类PartialAppSaveBean实现可序列化{
受保护的静态最终记录器Logger=LoggerFactory.getLogger(PartialAppSaveBean.class);
私有静态最终长serialVersionUID=1L;
/**
*保存所有有效的应用程序值
*
*@param事件
*/
公共作废保存数据(AjaxBehaviorEvent事件){
final FacesContext context=FacesContext.getCurrentInstance();
UIForm form=getParentForm(event.getComponent());
设置提示=EnumSet.of(visitint.SKIP\u未指定);
form.visitTree(VisitContext.createVisitContext(context,null,hints),new VisitCallback(){
@凌驾
公共访问结果访问(VisitContext上下文,UIComponent组件){
if(UIInput的组件实例){
UIInput=(UIInput)组件;
验证(context.getFacesContext());
if(input.isValid()&&input.getValue()!=null){
ValueExpression=input.getValueExpression(“值”);
if(valueExpression!=null
&&valueExpression.getExpressionString()!=null){
试一试{
valueExpression.setValue(context.getFacesContext().getELContext(),input.getValue());
}捕获(例外情况除外){
LOGGER.error(“表达式[”+valueExpression.getExpressionString()+
无法使用值[“+input.getValue()+”],ex)设置“]值;
}                            
}
}
}
返回VisitResult.ACCEPT;
}
});
//在此处保存数据
}
/**
*返回此UIComponent的父窗体
* 
*@param组件
*@报税表
*/
专用静态UIForm getParentForm(UIComponent组件){
while(component.getParent()!=null){
if(component.getParent()instanceof UIForm){
返回(UIForm)组件。getParent();
}否则{
返回getParentForm(component.getParent());
}
}
返回null;
}
}
调用类似于:

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

您可以在上使用

FacesContext context=FacesContext.getCurrentInstance();
UIForm form=getForm();
Map validValues=new HashMap();
设置提示=EnumSet.of(visitint.SKIP\u未指定);
form.visitTree(VisitContext.createVisitContext(context,null,hints),new VisitCallback(){
@凌驾
公共访问结果访问(VisitContext上下文,UIComponent组件){
if(UIInput的组件实例){
UIInput=(UIInput)组件;
if(input.isValid()){
validValues.put(input.getClientId(context.getFacesContext()),input.getValue());
}
}
返回VisitResult.ACCEPT;
}
});

不错。如果input.isValid(),是否有一种简单的方法来转换值并更新组件绑定到的模型?这取决于功能需求。表单是否已提前提交/作废,而您仅执行了
?或者您希望提交并处理整个表单并接管JSF验证吗?如果是后者,则在
If(input.isValid())
之前调用
input.validate(context.getFacesContext())
。顺便说一下,这也将执行转换。它不会更新模型值,因此您必须通过
input.getValue()
获取它。要求是,当用户试图退出时,我将使用onbeforeunload方法提示他们是否要保存数据(即使数据不完整),因此我将调用等效的。然后我需要更新有效UIInput元素的模型并保存模型层次结构。顺便说一句,这是一个关于OmniFaces的有趣想法。这将是对一个已经非常优秀的项目的最优秀的补充。我认为你提供的蓝图应该能满足我今天的需要。是时候去写些代码了。
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;
    }
});