2011年6月15日水曜日

s:forEachとm:renderedとte:inputHiddenと

引き続きS2JSFのおはなしです。前の記事で二重のループを使った入力ができるようになりました。ところがm:renderedでinputタグのON/OFFを実装してみると、またまた更新ができなくなり呪いの言葉を吐く今日この頃です。

更新用のアクションは実行されますが、画面で入力した値がDTOのフィールドにセットされていません。

いろいろと試してみると、s:forEachとm:renderedの属性値に使うリストをte:inputHiddenで持っていることが原因のようです。試しにセッションに入れてみると、無事に更新されます。

そこを足掛りに調べてみれば、Teeda ExtensionのinputHiddenの仕様「Validationフェーズを正常終了すると、すぐにModelを更新する」にたどりつきました。


JSFでのリクエスト処理のライフサイクルは、
  1. Restore View
  2. Apply Request Values
  3. Process Validation
  4. Update Model Values
  5. Invoke Application
  6. Render Response
です。

te:inputHiddenで画面に持たせたリストは、仕様によれば3の「Process Validation」で復元されます。ところが画面で入力した値を扱うのは2の「Apply Request Values」です。この「Apply Request Values」でそのリストを使いたいのです。

そこで「m:immediate=true」ならば「Apply Request Values」のときに復元するように変更してみました。

--- javax/faces/component/html/HtmlInputHidden.java.orig
+++ javax/faces/component/html/HtmlInputHidden.java
@@ -45,12 +45,6 @@
         if (!isImmediate()) {
             executeValidate(context);
         }
-        try {
-            updateModelImmediately(context);
-        } catch (RuntimeException e) {
-            context.renderResponse();
-            throw e;
-        }
     }
 
     protected void updateModelImmediately(FacesContext context) {
@@ -73,4 +67,15 @@
             setValid(false);
         }
     }
-}
+    
+    public void validate(FacesContext context) {
+        super.validate(context);
+        try {
+            updateModelImmediately(context);
+        } catch (RuntimeException e) {
+            context.renderResponse();
+            throw e;
+        }
+    }
+    
+} 

目論見通りにte:inputHiddenだけで更新されています。これでセッションオブジェクトを大きくしてしまう罪悪感から逃れられそうです。

Teeda 1.0.13-rc4で試してみました。

0 件のコメント:

コメントを投稿