首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

JSF DataTable 驗證失敗時無法恢復用戶輸入值的解決方案

     編輯:Java 相關知識

問題背景

JSF 的事件驅動模式雖優雅,但 1.2 版本在細節處理上仍有不足。通常頁面驗證失敗時,JSF 會將用戶剛輸入的錯誤值(如在綁定 int 屬性的輸入框輸入 "abcd")重新渲染顯示,而非後台原值,這符合預期。然而若頁面包含可編輯的 <h:dataTable>,驗證失敗時,DataTable 內輸入組件卻會顯示後台綁定的原值,而非用戶剛輸入的值——除非 DataTable 內部自身有錯誤輸入。這顯然違背用戶體驗。

問題重現代碼

<h:form id="mainForm">
    <h:messages style="color:red" />
    名字:<h:inputText id="listName" value="#{Test1.listName}">
        <f:validateLength maximum="5"/>
    </h:inputText>
    <h:commandButton value="Submit" action="#{Test1.save}"/>
    測試用:<h:inputText id="testName" value="#{Test1.testName}"/>
    <h:dataTable headerClass="header" rowClasses="header" bgcolor="blue" cellspacing="1" cellpadding="0" border="0" value="#{Test1.listDataModel}" id="data" var="p">
        <h:column>
            <f:facet name="header"><h:outputText value="Name"/></f:facet>
            <h:outputText style="background-color:white;width:100%" id="name" value="#{p.name}"/>
        </h:column>
        <h:column>
            <f:facet name="header"><h:outputText value="Sex"/></f:facet>
            <h:inputText id="sex" value="#{p.sex}"/>
        </h:column>
        <h:column>
            <f:facet name="header"><h:outputText value="Age"/></f:facet>
            <h:inputText id="age" value="#{p.age}"/>
        </h:column>
        <h:column>
            <f:facet name="header"><h:outputText value="Email"/></f:facet>
            <h:inputText id="email" value="#{p.email}"/>
        </h:column>
    </h:dataTable>
</h:form>

根因分析

查閱 JSF 源碼發現,DataTable 有特殊渲染機制:只有當它被嵌套在另一個 DataTable 內部,或自身內部值有錯誤時,才會渲染 submittedValue(用戶提交的值);否則直接渲染後台綁定值。

解決方案:外層包裹一個空 DataTable

在目標 DataTable 外層再包一個無實際數據的 DataTable(value="1"),強制觸發 submittedValue 渲染邏輯。雖稍顯不雅,但 JSF 1.2 下無更優雅辦法,期待 JSF 2.0 改進。

修正後代碼關鍵片段

<h:dataTable value="1"><!-- 外層空 DataTable -->
    <h:column>
        <h:dataTable headerClass="header" rowClasses="header" bgcolor="blue" cellspacing="1" cellpadding="0" border="0" value="#{Test1.listDataModel}" id="data" var="p">
            <!-- 原有列定義保持不變 -->
        </h:dataTable>
    </h:column>
</h:dataTable>

完整 JSP 代碼見原文,Java 端僅含 Getter/Setter,此處不贅述。若有更好方案歡迎分享。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved