我遇到以下问题:

恢复我的视图后,对该字段的验证会导致JSF跳至“渲染”响应阶段(因为必填字段为空)。但是,即使呈现了当前值(空字符串)以向用户显示他/她没有填写任何内容,也不会执行以下语句:

 <c:if test="#{empty cc.attrs.fieldValue}">
     <f:attribute name="style" value="background-color: yellow;"/>
 </c:if>


它是错误还是功能?请帮忙。

完整的测试示例(Netbeans 6.8项目)在这里:http://www.221b.cz/so/JSFTester.zip

在教程中:“如果请求是回发,并且在应用请求值阶段,过程验证阶段或更新模型值阶段遇到错误,则在“渲染”响应阶段呈现原始页面”(http://java.sun.com/javaee/5/docs/tutorial/doc/bnaqq.html

这是否意味着如果在“还原视图”阶段还原视图,然后任何应用请求/验证/更新模型阶段失败,并跳至“渲染响应”,则渲染响应仅通过还原的视图,而对客户端没有任何更改?

托管Bean(TesterBean.java):

package cz.test;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

@ManagedBean
@RequestScoped
public class TesterBean {

// Simple DataStore (in real world EJB)
private static String storedSomeValue = null;

private String someValue;

public TesterBean() {
}

public String storeValue() {
    storedSomeValue = someValue;
    return "index";
}

public String eraseValue() {
    storedSomeValue = null;
    return "index";
}

public String getSomeValue() {
    someValue = storedSomeValue;
    return someValue;
}

public void setSomeValue(String someValue) {
    this.someValue = someValue;
}

}


复合组件(field-component.xhtml):

<?xml version='1.0' encoding='ISO-8859-1' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:f="http://java.sun.com/jsf/core"
  xmlns:composite="http://java.sun.com/jsf/composite"
  xmlns:c="http://java.sun.com/jsp/jstl/core">

<!-- INTERFACE -->
<composite:interface>
    <composite:attribute name="currentBehaviour" type="java.lang.String" required="true"/>
    <composite:attribute name="fieldValue" required="true"/>
</composite:interface>

<!-- IMPLEMENTATION -->
<composite:implementation>
    <h:panelGrid columns="3">
        <c:choose>
            <c:when test="#{cc.attrs.currentBehaviour == 'READONLY'}" >
                <h:outputText id="fieldValue" value="#{cc.attrs.fieldValue}">
                </h:outputText>
            </c:when>
            <c:when test="#{cc.attrs.currentBehaviour == 'MANDATORY'}" >
                <h:inputText id="fieldValue" value="#{cc.attrs.fieldValue}" required="true">
                    <f:attribute name="requiredMessage" value="Field is mandatory"/>
                    <c:if test="#{empty cc.attrs.fieldValue}">
                        <f:attribute name="style" value="background-color: yellow;"/>
                    </c:if>
                </h:inputText>&nbsp;*
            </c:when>
            <c:when test="#{cc.attrs.currentBehaviour == 'OPTIONAL'}" >
                <h:inputText id="fieldValue" value="#{cc.attrs.fieldValue}">
                </h:inputText>
            </c:when>
        </c:choose>
        <h:message for="fieldValue" style="color:red;" />
    </h:panelGrid>
</composite:implementation>




页面(index.xhtml):

<?xml version='1.0' encoding='UTF-8' ?>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml"
   xmlns:h="http://java.sun.com/jsf/html"
   xmlns:ez="http://java.sun.com/jsf/composite/components">

<h:head>
    <title>Testing page</title>
</h:head>
<h:body>
    <h:form>
        <h:outputText value="Some value:"/>
        <ez:field-component currentBehaviour="MANDATORY" fieldValue="#{testerBean.someValue}"/>
        <h:commandButton value="Store" action="#{testerBean.storeValue}"/>
        <h:commandButton value="Erase" action="#{testerBean.eraseValue}" immediate="true"/>
    </h:form>

    <br/><br/>
    <b>Why is field's background color not set to yellow?</b>
    <ol>
        <li>NOTICE: Field has yellow background color (mandatory field with no value)</li>
        <li>Fill in any value (eg. "Hello") and press Store</li>
        <li>NOTICE: Yellow background disappeared (as mandatory field has value)</li>
        <li>Clear text in the field and press Store</li>
        <li><b>QUESTION: Why is field's background color not set to yellow?</b></li>
        <li>Press Erase</li>
        <li>NOTICE: Field has yellow background color (mandatory field with no value)</li>
    </ol>
</h:body>




按照Brian的建议进行编辑(field-component.xhtml)

<?xml version='1.0' encoding='ISO-8859-1' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:f="http://java.sun.com/jsf/core"
  xmlns:composite="http://java.sun.com/jsf/composite">

<!-- INTERFACE -->
<composite:interface>
    <composite:attribute name="currentBehaviour" type="java.lang.String" required="true"/>
    <composite:attribute name="fieldValue" required="true"/>
</composite:interface>

<!-- IMPLEMENTATION -->
<composite:implementation>
    <h:panelGrid columns="3">
        <h:outputText rendered="#{cc.attrs.currentBehaviour == 'READONLY'}" id="fieldValue1" value="#{cc.attrs.fieldValue}" />

        <h:inputText rendered="#{cc.attrs.currentBehaviour == 'MANDATORY'}" id="fieldValue2" title="#{cc.attrs.fieldValue}" value="#{cc.attrs.fieldValue}" required="true" style="#{empty cc.attrs.fieldValue ? 'background-color: yellow;' : ''}">
            <f:attribute name="requiredMessage" value="Field is mandatory"/>
        </h:inputText>&nbsp;*

        <h:inputText rendered="#{cc.attrs.currentBehaviour == 'OPTIONAL'}" id="fieldValue3" value="#{cc.attrs.fieldValue}"/>

        <h:message for="fieldValue" style="color:red;" />
    </h:panelGrid>
</composite:implementation>




但是即使我摆脱了JSTL,仍然无法正常工作:-(似乎只有value属性用h:inputText中的http请求中的新值更新,而其余属性在阶段渲染响应中没有重新评估。

最佳答案

您使用的<c:choose><c:when>标记是JSTL标记,而不是JSF标记。这意味着它们在构建时而不是在渲染时进行评估。回发时,不会重新构建组件树,而是会重新渲染它,并且不会重新评估<c:标记。

使用<h:panelGroup rendered="#{}">标记而不是<c:标记重试您的示例。

有关更多详细信息,请参见此文章:
http://drewdev.blogspot.com/2008/03/build-time-vs-render-time.html


  重要的是要记住,您不能在JSF表单的回发中“重新出现”组件。这是因为在保存状态和恢复状态之间绝不能更改JSF组件树。这非常重要,因此让我再说一遍,在保存状态和恢复状态之间,绝不能更改JSF组件树。

07-24 09:45
查看更多