13

以下のように、jQuery を使用して HTMLchangeのすべてのイベント リスナーを登録しています。input

<h:head>
    <script type="text/javascript">
        //<![CDATA[
        $(document).ready(function(){
            $(':input').each(function() {
                $(this).change(function() {
                    console.log('From docReady: ' + this.id);
                });
            });
        });

        function changeHandler() {
            console.log("from changeHandler");
        }
        //]]>
    </script>
</h:head>
<h:body>
    <h:form id="topForm">
        <p:commandButton id="myButton" value="update"
                         action="#{testBean.submit}"
                         partialSubmit="true" process=":myForm:panel"
                         update=":myForm:panel" />
    </h:form>
    <h:form id="myForm">
        <p:panel id="panel">
            <p:inputTextarea id="myTextarea"
                             value="#{testBean.val}"
                             onchange="changeHandler();"/>
        </p:panel>
    </h:form>
</h:body>

ユーザーが のコンテンツを変更すると、両方changeのイベントがトリガーされますmyTextarea。ただし、を部分的に更新する更新ボタンを押した後myTextareaは、changeHandler のみがトリガーされます。バインドされたイベント$(document).ready()がトリガーされなくなりました。

これは PrimeFaces に関連するものですか、または予想される動作ですか? はいの場合、ドキュメント準備スクリプトを再実行せずに 2 番目のイベントを確実にトリガーするにはどうすればよいですか。

4

1 に答える 1

31

問題の原因として、ajaxリクエストはajaxレスポンスからの新しいHTML要素でHTMLDOMツリーを更新します。これらの新しいHTML要素には、明らかに、jQueryイベントハンドラー関数がアタッチされていません。ただし、$(document).ready()ajaxリクエストでは再実行されません。手動で再実行する必要があります。

これはさまざまな方法で実現できます。最も簡単な方法は、$(document).on(event, selector, function)の代わりにを使用することです$(selector).on(event, function)。これはドキュメントに関連付けられており、givenは、givenに一致する要素でgivenがトリガーされたfunctionRefときに常に呼び出されます。したがって、JSF手段によって関数を明示的に再実行する必要はありません。eventNameselector

$(document).on("change", ":input", function() {
    console.log("From change event on any input: " + this.id);
});

別の方法は、ajaxリクエストの完了時に自分で関数を明示的に再実行することです。readyこれは、 /イベント中に関数をすぐに実行することに実際に関心がある場合の唯一の方法ですload(たとえば、日付ピッカーなど、プラグイン固有の動作/ルックアンドフィールを直接適用する場合)。$(document).ready()まず、次のようにジョブを再利用可能な関数にリファクタリングする必要があります。

$(document).ready(function(){
    applyChangeHandler();
});

function applyChangeHandler() {
    $(":input").on("change", function() {
        console.log("From applyChangeHandler: " + this.id);
    });
}

$.each()(私はあなたの完全に不必要なアプローチを削除して単純化したことに注意してください)

次に、次のいずれかの方法を選択して、ajaxリクエストの完了時に再実行します。

  1. oncompletePrimeFacesコマンドボタンの属性を使用します。

    oncomplete="applyChangeHandler()"
    
  2. <h:outputScript target="body">の代わりに使用$(document).ready()

    <h:outputScript id="applyChangeHandler" target="body">
        applyChangeHandler();
    </h:outputScript>
    

    そしてそれをupdate属性で参照します:

    update=":applyChangeHandler"
    
  3. <p:outputPanel autoUpdate="true">すべてのajaxリクエストで自動更新するために使用します。

    <p:outputPanel autoUpdate="true">
        <h:outputScript id="applyChangeHandler">
            applyChangeHandler();
        </h:outputScript>
    </p:outputPanel>
    
  4. の代わりにOmniFaces を使用し、すべてemで使用します。<o:onloadScript>$(document).ready()<h:outputScript>

    <o:onloadScript>applyChangeHandler();</o:onloadScript>
    
于 2013-01-18T14:16:47.263 に答える