【问题标题】:JSF: how to hide outputText when validateLongRange failsJSF:当 validateLongRange 失败时如何隐藏 outputText
【发布时间】:2013-02-28 15:49:47
【问题描述】:

我有以下代码:

<h:form>
    <h:inputText id="inputField" value="#{bean.myProperty}">
        <f:validateLongRange
            minimum="#{bean.minimum}"
            maximum="#{bean.maximum}"/>
    </h:inputText>
    <h:commandButton id="submit" value="Submit" >
        <f:ajax execute="inputField" render="outputField errors" />
    </h:commandButton>
    <h:outputText id="outputField" value="#{bean.myPropertyFormatted}"/>
    <h:message id="errors" for="inputField"/>
</h:form>

当 inputText 验证失败时,我想从用户那里删除/隐藏 outputText。最优雅且面向未来的重构方式是什么?

我尝试在 outputText 元素上设置属性 rendered="#{!facesContext.validationFailed}",但这仅确定 outputText 元素是否被重新渲染,而不是保持旧文本不变。但是,当 validateLongRange 验证失败时,我想完全删除/隐藏用户的 outputText,因为用户将看到验证错误消息,并且对基于先前有效输入的旧输出消息不感兴趣仍然是存储在 bean 中的值。

【问题讨论】:

  • 我不明白为什么rendered 不能胜任这项工作。如果其中的 EL 返回 false outputText 元素将不会被渲染,这意味着您将根本没有该元素的 HTML 在浏览器中。这不是你需要的吗?
  • @partlov:是的,这就是我需要的,但这不是我看到的行为。相反,当我遇到验证错误时,outputText 将保持不变。我希望它消失。如果我反转 EL 输出(没有“!”),就更容易看到发生了什么。对于rendered="#{facesContext.validationFailed}",我没有在outputText 上获得任何有效值的更新,但是一旦我给出一个无效值,我就会得到更新,这会导致验证错误。即在验证错误时,我看到在输入无效值之前输入的最后一个有效值。
  • @partlov:我的代码没有像您预期的那样运行的原因可能与 f:ajax 元素的使用有关吗?另请参阅下面的答案。

标签: validation jsf


【解决方案1】:

根据 JSF 的经验,如果你想有条件地渲染 anything,你应该将它包装在一个容器组件中 (&lt;foo:panel/&gt;) 并让容器组件成为 ajax 更新的目标.

<h:form>
   <h:inputText id="inputField" value="#{bean.myProperty}">
      <f:validateLongRange
        minimum="#{bean.minimum}"
        maximum="#{bean.maximum}"/>
   </h:inputText>
   <h:commandButton id="submit" value="Submit" >
      <f:ajax execute="inputField" render="thePanel errors" />
   </h:commandButton>
   <h:panelGrid id="thePanel">
   <h:outputText rendered="#{!facesContext.validationFailed}" id="outputField" value="#{bean.myPropertyFormatted}"/>
   </h:panelGrid>
   <h:message id="errors" for="inputField"/>
</h:form>

对于要进行 ajax 更新的组件,它必须已经在浏览器的 DOM 中,这就是 ajax 的工作方式。因此,当您的视图最初呈现时,outputField 不存在,因为rendered 条件评估为假。因此,由于上述原因,任何后续对 ajax 更新的请求都会失败。容器组件策略是确保标记区域的全面更新,无论之前有什么

【讨论】:

  • 你在我完成我的工作时发布了你的答案。顺便说一句,您忘记将&lt;h:outputText&gt;&lt;h:message&gt; 包装在UIContainer
  • @LuiggiMendoza,你的出现时我正在编辑!这里是鲨鱼池XD。你赢得了我的选票
  • 不客气 :)。完成您的回答,以便我为您投票(请注意,您不会重新渲染 thePanel)。
  • @kolossus:感谢您的回答。我很难决定两个同时回答中的哪一个要勾选!我希望你原谅我接受另一个。两者似乎同样有效。您的答案中可能仍然缺少一件事。 facesContext.validationFailed 之前没有“不”。你能对此发表评论吗?
  • @Student,一切都很好,更好的答案得到了投票^_^,缺少的!只是我的一个错字
【解决方案2】:

问题是当你给一个对象设置rendered属性并且它的值为false时,组件将不会在组件树中,因为它没有被渲染并且你不能重新渲染(或更新) 它。解决方案是在UIContainer 中设置组件并渲染容器:

<h:commandButton id="submit" value="Submit" >
    <f:ajax execute="inputField" render="pnlResult" />
</h:commandButton>
<h:panelGrid id="pnlResult">
    <h:outputText id="outputField" value="#{bean.myPropertyFormatted}"
        rendered="#{not facesContext.validationFailed}" />
    <h:message id="errors" for="inputField"/>
</h:panelGrid>

【讨论】:

    【解决方案3】:

    根据 kolossus 和 Luiggi Mendoza 的出色回答,我最终做了以下事情:

    <h:form>
        <h:inputText id="inputField" value="#{bean.myProperty}">
            <f:validateLongRange
                minimum="#{bean.minimum}"
                maximum="#{bean.maximum}"/>
        </h:inputText>
        <h:commandButton id="submit" value="Submit" >
            <f:ajax execute="inputField" render="outputField errors" />
        </h:commandButton>
        <h:panelGroup layout="block" id="outputGroup">
            <h:outputText id="outputField" value="#{bean.myPropertyFormatted}" rendered="#{not facesContext.validationFailed}"/>
            <h:message id="errors" for="inputField"/>
        </h:panelGroup>
    </h:form>
    

    我选择了h:panelGroup 而不是h:panelGrid,因为我的 Web 开发人员背景让我对基于表格的布局的想法感到不寒而栗。似乎与layout="block" 一起,h:panelGroup 被渲染为&lt;div/&gt;,而h:panelGrid 被渲染为&lt;table/&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-01
      • 2011-07-04
      • 2018-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多