0

我有以下代码:

<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。什么是最优雅和面向未来的重构方式来做到这一点?

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

4

3 回答 3

5

作为 JSF 的经验法则,如果您想有条件地渲染任何东西,您应该将它包装在一个容器组件 ( <foo:panel/>) 中,并使该容器组件成为 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 更新的请求都会失败。容器组件策略是确保标记区域的全面更新,无论之前有什么

于 2013-02-28T17:06:06.787 回答
3

问题是,当您将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>
于 2013-02-28T17:06:47.730 回答
1

根据 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<div/>h:panelGrid<table/>

于 2013-02-28T20:14:23.653 回答