次の問題が発生しています。
ビューが復元された後、フィールドの検証により、JSF は Render response フェーズにスキップします (必須フィールドが空であるため)。ただし、現在の値 (空の文字列) がレンダリングされて、ユーザーが何も入力していないことをユーザーに示す場合でも、次のステートメントは実行されません。
<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> *
</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>
編集、ブライアンの提案 (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> *
<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 を削除してもまだ機能しません:-( h:inputText の http リクエストからの新しい値で value 属性のみが更新されているようですが、残りの属性はフェーズ Render Response で再評価されません。