このフォームには、セッションスコープのBeanの値を含む約170個の個別のテキストボックスがあります。コンポーネントに特定のCSSクラスがある場合にのみ値を送信する必要があります。
私が最初にこれにアプローチした方法は、UPDATE_MODEL_VALUESでPhaseListenerを作成し、そこでCSSクラスをテストすることでした。クラスが影響を受けるクラスである場合、コンポーネントの値をnullに設定しました。次に、フロントエンドで、ジェネリックJavaScriptメソッドを使用してフォーカスのクラスを切り替えました。これは、追加する必要があるのは、各コンポーネントへの変更という意味です。
... styleClass="examfieldgrey" onfocus="whiteField(this);"
変更する必要のあるコンポーネントの数を考えると、これはちょっといいことです。
複数のhフォームタグを使用するようにeフォームをリファクタリングするまで、これは正常に機能していました。現在、CSSclassはフロントエンドで切り替わっていますが、この変更は保存されていません。フェーズリスナーは古いクラスを取得しています。
これは明らかに、jQuery/javascriptでクラスを切り替えることに関連していると思います。私が疑問に思っているのは:
- これを今が最高!! できれば、170以上のコンポーネントを変更する必要がないことを意味しますか?
- クラスを切り替えるためにJavascriptの使用を継続する必要がある場合、その変更をjavascriptから投稿する方法はありますか?
これが明らかな質問である場合は申し訳ありませんが、JSFのライフサイクルについてはまだ少し環境に配慮しています。
JSF2.0MyFacesを使用しています
参考までに、フィルタリングする必要のあるフォーム上のコンポーネントの例を次に示します。
<h:inputTextarea
id="inputVal"
styleClass="midTextArea examfieldgrey"
onfocus="whiteField(this);"
value="#{bean.form.val}"/>
ここで、「examfieldgrey」は、コンポーネントをブロックするかどうかを決定するときにテストするクラスです。
そしてwhiteFieldメソッド:
function whiteField(field){
if(! jQuery(field).hasClass("examfieldgrey")){
return;
}
jQuery(field).removeClass("examfieldgrey");
jQuery(field).addClass("examfieldwhite");
}
そして、私がフィルタリングするフェーズメソッドの前のフェーズリスナー:
// TODO: make whatever mode allows ghosting to be configurable outside of
// the system (perhaps in the config file)
/**
* Before the model is updated, test each component's CSS on the form. If the
* CSS style is 'examfieldgrey' set the value to null so it doesn't get submitted
*/
@Override
public void beforePhase(PhaseEvent arg0) {
//We need the session to get the backing bean
if (arg0.getFacesContext().getExternalContext().getSessionMap() == null) {
return;
}
//get the measurements bean so we can determine the form mode
if (arg0.getFacesContext().getExternalContext().getSessionMap()
.get("measurements") == null) {
return;
}
//ensure the bean is the expected data type, it should always be this type. I'm just paranoid ;)
if (!(arg0.getFacesContext().getExternalContext().getSessionMap()
.get("measurements") instanceof MeasurementsController)) {
return;
}
//get, convert and check the backing bean's mode. We only filter if the mode is COPY
if (((MeasurementsController) arg0.getFacesContext()
.getExternalContext().getSessionMap().get("measurements"))
.getMode() != FormMode.COPY) {
return;
}
//recursivly traverse the componenets and filter the ones who have the CSS class
traverseChildren(arg0.getFacesContext().getViewRoot().getChildren());
}
/**
* Traverse a List of UIComponenets and check the CSS. If it's the 'examfieldgrey' class
* and the component is a UIInput component, set the value to null.
* @param children a List of the componenets to filter on the form.
*/
private void traverseChildren(List<UIComponent> children) {
debugLevelCount++;
if (children == null || children.size() == 0) {
debugLevelCount--;
return;
}
for (UIComponent component : children) {
if (component instanceof UIInput) {
if (component.getAttributes() != null
&& component.getAttributes().get("styleClass") != null
&& component.getAttributes().get("styleClass")
.toString().contains("examfieldgrey")) {
((UIInput) component).setValue(null);
} else {
debugPrintAllow(component);
}
continue;
}
traverseChildren(component.getChildren());
}
debugLevelCount--;
}
印刷機能を無視してください、彼らは何もしません;)
みんなありがとう!
編集
これはコピー操作であるため、Beanの構築後にバッキングBeanに値が含まれます。[送信]をクリックし、バッキングBeanがまだ入力されていない場合は、primefacesセレクターを使用するオプションが最適です。しかし、実際にそれらの値をクリアできるかどうかはわかりません。
もう1つ注意すべき点は、フォームオブジェクトのインスタンス内の値を参照していることです。それが役立つかどうかはわかりませんが、元の投稿にはありませんでした。