Jsf 为什么要调用未更改组件的验证器?

Jsf 为什么要调用未更改组件的验证器?,jsf,validation,icefaces,Jsf,Validation,Icefaces,我有一个IceFaces表单和几个输入字段 假设我有这个: <ice:selectOneMenu id="accountMenu" value="#{accountController.account.aId}" validator="#{accountController.validateAccount}"> <f:selectItems id="accountItems" value="#{accountController.

我有一个IceFaces表单和几个输入字段

假设我有这个:

<ice:selectOneMenu id="accountMenu"
    value="#{accountController.account.aId}"
    validator="#{accountController.validateAccount}">
    <f:selectItems id="accountItems"
            value="#{accountController.accountItems}" />
</ice:selectOneMenu>
这是:

<ice:selectOneMenu id="costumerMenu"
    value="#{customerController.customer.cId}"
    validator="#{customerController.validateCustomer">
    <f:selectItems id="customerItems"
            value="#{customerController.customerItems}" />
</ice:selectOneMenu>
如果我更改一个值,则调用相应的验证器,这很好。但是也调用了另一个验证器,这是不好的,因为用户收到了一条令人恼火的消息,要在一个他可能会注意的字段中插入一个值。这就像用棍子捅用户一样,让用户快点!。糟糕

我认为属性partialSubmit控制着这种行为,因此只提交一个DOM部分,这会受到用户交互的影响,但是如果我声明两个组件都是部分提交的,则不会发生任何变化。但是,如果一个组件值发生更改,则会调用两个验证器


如何防止整个表单在完全提交之前被验证?

尝试在onblur事件上执行ajax验证我不知道如何使用icefaces进行验证,但对于richfaces来说,它只是一个

当执行部分提交时,整个JSF生命周期仍在执行。因此,仍然会处理验证阶段,并且验证组件层次结构中的所有组件

这是有充分理由的。一个组件中的更改可能会导致另一个组件中的潜在无效更改。例如,SelectOne菜单中的选择可以在inputText中设置值

ICEfaces以一种重要的方式改变处理:在部分提交期间,ICEfaces临时将触发sumbit的组件以外的所有组件标记为optional required=false。因此,将跳过所需的验证。但是,ICEfaces不会禁用其他验证

此问题有两种可能的解决方案:

除partialSubmit外,还设置immediate=true。当在应用请求值阶段执行部分提交以执行验证时,这会稍微改变组件的生命周期。这可能会导致跳过其他验证

检测自定义验证器中是否发生了部分提交。如果触发部分提交的不是组件,则跳过验证。不幸的是,没有任何关于如何检测部分提交的文档,但我在com.icesoft.faces.application.PartialSubmitPhaseListener类的源代码中找到了解决方案

事实证明,当执行部分提交时,ICEfaces会添加两个请求参数:

ice.submit.partial-设置为true表示已完成部分提交。 ice.event.captured-包含生成部分提交的组件的组件ID。 您可以在验证方法中利用这两个参数。下面是一个例子:

public void validateAccount(FacesContext context, 
  UIComponent component, Object value) 
{
  if(!partiallySubmitted(context) || 
     componentWasPartiallySubmitted(context, component)
    // Perform validation
  }

}

public boolean partiallySubmitted(FacesContext context) {
    ExternalContext externalContext = context.getExternalContext();
    Map parameterMap = externalContext.getRequestParameterMap();   

    return "true".equals(parameterMap.get("ice.submit.partial"));
}

public boolean componentWasPartiallySubmitted(FacesContext context, 
  UIComponent component) {
    ExternalContext externalContext = context.getExternalContext();
    Map parameterMap = externalContext.getRequestParameterMap();   

    String componentId = (String) parameterMap.get("ice.event.captured");

    return component.getClientId(context).equals(componentId);
}

当然,可能不支持直接访问这两个请求参数。但是,在ICEfaces团队提供受支持的检测部分提交的方法之前,这可能是您唯一的选择。

您使用的是什么版本的ICEfaces?出于好奇,这两个选项中哪一个适合您?immediate=true,或者在验证器中检测到部分提交?以上都没有,我在这一点上重新设计了我的应用程序,但是您的回答帮助我对请求处理的内部过程有了更多的了解。@JimHurne,我正在编写一些selenium脚本来自动化IceFace应用程序。我面临着许多问题,因为这项ICE的第三方活动。有什么方法可以让我等到IceSubmitPartial使用javascript完成后再问吗?@Vimal我建议你把这个问题作为一个新的堆栈溢出问题来问。