【问题标题】:Validation on page refresh页面刷新验证
【发布时间】:2014-07-12 23:01:48
【问题描述】:

我的输入字段附加了一个 <f:ajax> 对象,以便通过按 TAB 进行验证:

<h:inputText id="input2" value="#{bean.property}">
    <f:validator validatorId="customValidator" />
    <f:ajax execute="@form" render="@this" />
</h:inputText>

如果有任何验证错误,它们将通过类似于&lt;h:messages&gt; 的自定义组件显示,输入框将通过自定义PhaseListener 设置样式。

我已经实现了一个自定义 Faces Validator 来跳过验证:

public class CustomValidator {

public void validate(FacesContext context, UIComponent component,
        Object value) throws ValidatorException {
    if (skipValidation(context)) {
        return;
    }
    //Validation code goes here
}

这使我可以选择根据某些条件跳过 bean 验证,例如切换到另一个编辑器视图并将(可能是错误的)数据保存在支持 bean 中。

现在,刷新当前页面时出现我的问题(通过按 F5,点击导航栏中的相同链接或类似链接)。支持中明显错误的数据按预期正确显示,但也应标记为无效。因此,我需要一种在每次页面加载时调用验证的方法(目前它仅通过 &lt;f:ajax&gt; 对象调用)。

我试着摆弄这样的东西

<f:ajax event="load" execute="editform" render="editform"/>

附加到&lt;h:body&gt;。这行得通,但是该站点被绘制了两次-如果首先绘制页面,然后通过ajax请求进行验证和更新,是否没有邪恶的闪烁,我真的不在乎。

我已经搜索了几个小时来解决这个问题,也许我只是在错误的方向上搜索。有关如何解决此问题的任何建议?

【问题讨论】:

  • 等待.. bean 是会话范围的??
  • 嗨@BalusC,很抱歉我的回复迟了。是的,bean(嗯,不是直接的 bean,而是持有 bean 的对象,我从中引用 bean)是 @SessionScoped 以在整个会话中保留 bean,而不仅仅是请求。那是问题吗?如果您愿意,我可以添加有关确切用例的更多信息。为什么我会这样做。

标签: java ajax jsf


【解决方案1】:

不要使用@SessionScoped bean 来支持页面;这是 JSF 设计的味道(如果有的话)


使用preRenderView 事件触发(或检查)您在页面加载时选择的任何验证逻辑。作为开始:

<f:event type="preRenderView" listener="#{bean.validate}" rendered="#{facesContext.postBack}" />
  1. &lt;f:event/&gt; 标记在您的页面上注册一个事件侦听器。
  2. type="preRenderView" 属性规定事件应该在页面加载之前执行
  3. rendered="#{facesContext.postBack}" 将确保仅在刷新同一页面时才加载事件,而不是在第一次加载时加载
  4. listener 将引用一个支持 bean 方法,您可以在其中执行所需的验证。在此侦听器中,您可以抛出 ValidationException 并适当地排队 FacesMessages

替代方案:

  1. 您可以在 viewParam 中引用组件的值并将相同的验证器附加到该组件:

    <f:metadata>
        <f:viewParam name="theParam" rendered="#{facesContext.postBack}" value="param['form:input2']" validator="customValidator"/>
    </f:metadata>
    

    这会尝试重新提交input2 组件的值作为视图参数。视图参数(在此用法中)与任何其他参数一样是 UIComponent,并且遵循相同的转换/验证语义。

  2. 如果您想要更复杂地处理该组件的内容,您也可以将整个组件作为属性传递给viewParam。首先将input2组件绑定到页面作用域:

     <h:inputText id="input2" binding="#{input2}" value="#{bean.property}">
         <f:validator validatorId="customValidator" />
         <f:ajax execute="@form" render="@this" />
     </h:inputText>
    

    然后将组件作为属性传递:

      <f:metadata>
        <f:viewParam name="theParam" rendered="#{facesContext.postBack}" validator="customValidator"/>
             <f:attribute name="input2" value="#{input2}"/>
      </f:metadata>
    

然后您可以在验证器中检索该值:

      UIInput input2= (UIInput)component.getAttributes().get("input2");

      String input2Value= input2.getSubmittedValue().toString();

【讨论】:

  • &lt;f:event&gt; 不支持rendered 属性(它不是UIComponent)并且FacesContext 没有isIsPostback()getIsPostback() 方法。 ValidationException 不是 JSF API 的一部分,即使这样 JSF 也不会像在流程验证阶段那样从那里捕获验证异常。你在发布之前测试过你的答案吗?
  • 即使它可以这样工作,我将如何从支持 bean 侦听器方法触发我的 CustomValidator 的使用?
  • @BalusC,我的错误,我的意思是facesContext.postBackf:event 在我的 JSF 2.2 发行版中确实具有 rendered 属性(显示在完整的代码和所有内容中)。还没来得及测试通过。我会在早上试一试
  • @kolossus 如何从bean.validate 触发我的CustomValidator faces Validator?我真的很想给你赏金并接受这个答案:)
  • @INK - 抱歉,我一直忙得不可开交。您可以通过在保存输入值的组件上调用 processValidations 从后端手动触发验证。我还没有发布它,因为我还没有测试它(参见上面的“没有时间”)。我会尽快解决的
【解决方案2】:

您可以隐藏表单并使用 JSF-AJAX 节点的 onevent 属性。 当获取 AJAX 响应并将您的表单设置为可见时,它将被调用。

所以整个过程可能是这样的:

  1. 通过 css 使表单不可见。喜欢&lt;form style="display:none"&gt;
  2. 正在处理您的 &lt;f:ajax&gt; 元素。
  3. 在获得响应后,它的属性 onevent 被调用,并将设置您的表单可见。

提示:为了获得更好的外观和感觉,您可以使用 JQuery 来显示表单。像这样使用它:

$("#myform").fadeIn();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-09
    • 1970-01-01
    • 1970-01-01
    • 2011-09-04
    相关资源
    最近更新 更多