2

このフォームには、セッションスコープのBeanの値を含む約170個の個別のテキストボックスがあります。コンポーネントに特定のCSSクラスがある場合にのみ値を送信する必要があります。

私が最初にこれにアプローチした方法は、UPDATE_MODEL_VALUESでPhaseListenerを作成し、そこでCSSクラスをテストすることでした。クラスが影響を受けるクラスである場合、コンポーネントの値をnullに設定しました。次に、フロントエンドで、ジェネリックJavaScriptメソッドを使用してフォーカスのクラスを切り替えました。これは、追加する必要があるのは、各コンポーネントへの変更という意味です。

... styleClass="examfieldgrey" onfocus="whiteField(this);"

変更する必要のあるコンポーネントの数を考えると、これはちょっといいことです。

複数のhフォームタグを使用するようにeフォームをリファクタリングするまで、これは正常に機能していました。現在、CSSclassはフロントエンドで切り替わっていますが、この変更は保存されていません。フェーズリスナーは古いクラスを取得しています。

これは明らかに、jQuery/javascriptでクラスを切り替えることに関連していると思います。私が疑問に思っているのは:

  1. これを今が最高!! できれば、170以上のコンポーネントを変更する必要がないことを意味しますか?
  2. クラスを切り替えるために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つ注意すべき点は、フォームオブジェクトのインスタンス内の値を参照していることです。それが役立つかどうかはわかりませんが、元の投稿にはありませんでした。

4

2 に答える 2

5

コンポーネントに特定の CSS クラスがある場合にのみ、値を送信する必要があります。

PrimeFacesを既に使用している場合、または使用する予定がある場合は、最新の 3.3 バージョン以降、jQuery ベースの CSS セレクターとPrimeFaces ajax コンポーネントの属性 (JSF 標準コンポーネントの属性と同等) を受け入れる新しい@()セレクター構文を使用できます。 )。processupdateexecuterender<f:ajax>

例えば

<p:commandButton ... process="@(.foo)" />

また

<p:ajax ... process="@(.foo)" />

クラス名が の HTML 入力要素のみを処理するように JSF に指示しますfoo


現在、CSSclass はフロント エンドで切り替えられていますが、この変更は保存されていません。フェーズ リスナーは古いクラスを取得しています。

これは、サーバー側の JSF コンポーネント ツリーをクライアント側の HTML DOM ツリーと同期させていなかったためです。これについてJSFに通知せずに、クライアント側でのみ変更を加えています。CSS クラスはリクエスト パラメータとしてサーバー側に送信されず、HTML フォームの入力値のみが送信されます。基本的には、JS/jQuery ではなく JSF で CSS クラスを変更して、変更が JSF コンポーネント ツリーにも反映されるようにする必要があります。

ただし、これを実装するのは簡単ではなく、無駄になる可能性があります。したがって、最も簡単なのは、PrimeFaces をその@()セレクターのサポートとともに使用することです。このセレクターはクライアント側で評価され、セレクターに一致する JSF が理解できるコンポーネント クライアント ID の文字列に変換されます。したがって、これにより、クライアント側の変更が完全に考慮されます。

于 2012-06-03T18:14:18.917 に答える
0

フィールドのIDである文字列キーを使用して、フォームの各フィールドのブール値のマップを作成することで、これを解決することができました。各値は、天気を表すか、フィールドをコピーしないかを表します。ブラーの ajax を使用してこの値を更新します。そして、そのフィールドのマップのブール値に基づくように CSS クラスを設定しました。

レンダリングがうまくいきませんでした。もともと私はこれをすべてフォーカスで行っていましたが、テキストボックスをフォーカスでレンダリングしようとすると、実際にはテキストボックスへのフォーカスが失われることがすぐに明らかになりました。そのため、最初に行っていたように、焦点を合わせて簡単な js 関数を呼び出してクラスを切り替えます。

css クラスはフロント エンドのマップに基づいて選択されるため、フェーズ リスナーが呼び出される前に更新され、コンポーネントが適切にフィルター処理されます。

助けてくれてありがとう BalusC!

于 2012-06-06T14:57:49.220 に答える