【问题标题】:Why are validators of unchanged components called?为什么调用未更改组件的验证器?
【发布时间】:2011-02-18 05:48:22
【问题描述】:

我有一个 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 部分,这受用户交互的影响,但如果我声明两个组件都部分提交,则没有任何变化。如果一个组件值发生更改,仍然会调用两个验证器。

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

【问题讨论】:

  • 您使用的是什么版本的 ICEfaces?

标签: jsf validation icefaces


【解决方案1】:

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

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

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

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

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

  2. 检测您的自定义验证器中是否发生了部分提交。如果不是触发部分提交的组件,则跳过验证。不幸的是,没有任何关于如何检测部分提交的文档,但我在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 团队提供支持的方式来“检测”部分提交之前,这可能是您唯一的选择。

【讨论】:

  • 出于好奇,这两个选项中的哪一个对您有用? immediate=true,或者在验证器中检测到部分提交?
  • 以上都不是,此时我重新设计了我的应用程序,但您的回答帮助我更深入地了解了请求处理的内部过程。
  • @JimHurne,我正在编写一些 selenium 脚本来自动化 IceFace 应用程序。由于这个 IceSubmitPartial 事件,我面临很多问题。有什么方法可以等到 IceSubmitPartial 使用 javascript 完成?
  • @Vimal 我建议您将您的问题作为一个新的 Stack Overflow 问题提出。
【解决方案2】:

尝试对 onblur 事件执行 ajax 验证(不知道如何使用 icefaces,但对于 Richfaces,它只是一个 &lt;a4j:support event="onblur" /&gt;)

【讨论】:

    猜你喜欢
    • 2011-12-09
    • 2017-03-20
    • 2023-03-23
    • 2014-03-11
    • 1970-01-01
    • 2015-06-08
    • 1970-01-01
    • 1970-01-01
    • 2019-12-06
    相关资源
    最近更新 更多