jQuery $(document).readyおよびUpdatePanels?


475

私はjQueryを使用して、UpdatePanel内の要素にマウスオーバー効果を関連付けています。イベントはバインドされています$(document).readyます。例えば:

$(function() {    
    $('div._Foo').bind("mouseover", function(e) {
        // Do something exciting
    });    
});

もちろん、これは最初にページが読み込まれたときに正常に機能しますが、UpdatePanelが部分的なページ更新を実行すると、ページは実行されず、マウスオーバー効果はUpdatePanel内では機能しなくなります。

最初のページの読み込み時だけでなく、UpdatePanelが部分的なページの更新を起動するたびにjQueryでデータを配線するための推奨されるアプローチは何ですか?代わりにASP.NET Ajaxライフサイクルを使用する必要があり$(document).readyますか?


私はそれはあなたの問題解決すると思います。この試してみるcodeproject.com/Articles/21962/...
Baxterboom

回答:


545

UpdatePanelは、更新時に更新パネルの内容を完全に置き換えます。つまり、更新パネルに新しい要素があるため、サブスクライブしたイベントはサブスクライブされなくなりました。

これを回避するために私が行ったのは、更新のたびに必要なイベントを再度サブスクライブすることです。私$(document).ready()は最初のロードに使用し、次にMicrosoft PageRequestManager(ページに更新パネルがある場合に使用可能)を使用してすべての更新を再サブスクライブします。

$(document).ready(function() {
    // bind your jQuery events here initially
});

var prm = Sys.WebForms.PageRequestManager.getInstance();

prm.add_endRequest(function() {
    // re-bind your jQuery events here
});

PageRequestManager更新パネルがページ上にある場合、自動的に利用可能であるjavascriptオブジェクトです。UpdatePanelがページ上にある限り、コードを使用するために上記のコード以外を実行する必要はありません。

より詳細な制御が必要な場合、このイベントは.NETイベントが引数を渡す方法と同様の引数を渡します。(sender, eventArgs)これにより、イベントを発生させた原因を確認し、必要な場合にのみ再バインドできます。

Microsoftのドキュメントの最新バージョンは次のとおりです。msdn.microsoft.com/.../ bb383810.aspx


必要に応じて、jQueryを使用することをお勧めします.on()。これらの方法は、更新のたびにDOM要素に再サブスクライブするよりも効率的です。ただし、このアプローチを使用する前に、すべてのドキュメントを読んでください。これは、ニーズを満たしていない場合があるためです。.delegate()またはを使用するようにリファクタリングするのが無理なjQueryプラグインはたくさんある.on()ので、そのような場合は、再サブスクライブするほうがよいでしょう。


1
説明するときは、より正確に説明してください。つまり、使用例は、数行のコードを分散させるよりもはるかに優れています。Brian MacKayの説明を参照してください。それは完璧だ!
Truthseeker 2010年

3
@ Dan、jQuery 1.7以降、これに.delegate()置き換えられました.on()
Gabriele Petrioli

@ GabyakaG.Petrioli私はそれが置き換えられていることを理解していますが、この回答は一般的な問題を解決するようなので、まだアップグレードされていない古いバージョンのjQueryとの互換性を最大化したいと思いました。以前に推奨し.live(...)た私の回答は1.7で正式に非推奨になり、将来のバージョンでは削除される可能性があります。.delegate()しばらくの間jQueryでサポートされており、すぐに削除される可能性がないため、私は意図的に選択しました。ただし、回答をアップグレードして.on()、それを使用できる人にも言及します。
Dan Herbert

12
Sysがまだ宣言されていない可能性があるため(スクリプトの場所によって異なります)、$(document).ready内でprm変数を宣言して配線することをお勧めします。
drake7707 2012年

1
@AhmedSamyこれjQuery.delegate()以上使用することはお勧めしません。jQuery.on()どちらが優先APIとして使用されるかで置き換えられました。delegate()は、の特定の用途の単なるラッパーon()であり、将来的に非推奨になる可能性があります。私が以前に言及しdelegate()たコメントは、jQuery 1.7(on()API を導入)が新しくリリースされた1年以上前に書かれました。jQuery 1.9はすでにリリースされ、2.0はベータ版としてリリースの準備が整っているのでdelegate()、新しいコードでの使用は避けることをお勧めします。
Dan Herbert、

159
<script type="text/javascript">

        function BindEvents() {
            $(document).ready(function() {
                $(".tr-base").mouseover(function() {
                    $(this).toggleClass("trHover");
                }).mouseout(function() {
                    $(this).removeClass("trHover");
                });
         }
</script>

更新される予定のエリア。

<asp:UpdatePanel...
<ContentTemplate
     <script type="text/javascript">
                    Sys.Application.add_load(BindEvents);
     </script>
 *// Staff*
</ContentTemplate>
    </asp:UpdatePanel>

<EditItemTemplate>内のasp:GridView TextBoxで適切に機能します
Dan Randolph

このソリューションの問題は、機能している間、UpdatePanelの非同期ポストバックが強制終了されることです。UpdatePanelが再び役に立たなくなります。(ため息)
MC9000

63

UpdatePanel内のjQueryによるユーザーコントロール

これは質問への直接の回答ではありませんが、私がここで見つけた回答を読んでこの解決策をまとめました。誰かが役に立つと思うかもしれません。

ユーザーコントロール内でjQuery textareaリミッターを使用しようとしました。ユーザーコントロールがUpdatePanel内で実行され、コールバック時にバインディングが失われるため、これはトリッキーでした。

これが単なるページの場合、ここでの回答は直接適用されます。ただし、一部の回答が想定しているように、ユーザーコントロールはヘッドタグに直接アクセスすることも、UpdatePanelに直接アクセスすることもできませんでした。

このスクリプトブロックをユーザーコントロールのマークアップの一番上に配置することにしました。最初のバインドでは、$(document).readyを使用し、次にそこからprm.add_endRequestを使用します。

<script type="text/javascript">
    function BindControlEvents() {
        //jQuery is wrapped in BindEvents function so it can be re-bound after each callback.
        //Your code would replace the following line:
            $('#<%= TextProtocolDrugInstructions.ClientID %>').limit('100', '#charsLeft_Instructions');            
    }

    //Initial bind
    $(document).ready(function () {
        BindControlEvents();
    });

    //Re-bind for callbacks
    var prm = Sys.WebForms.PageRequestManager.getInstance(); 

    prm.add_endRequest(function() { 
        BindControlEvents();
    }); 

</script>

だから...誰かがこれがうまくいくことを知りたいのかもしれないと思っただけです。


2
私の人生でこれを機能させることができませんでした。それから私はそれを頭からフッターに移しました、そしてそれはうまくいきました。ポジティブではありませんが、私が使用しているScriptManagerの後に来る必要があると思います。
Adam Youngers、2011

私の場合、Sysが定義される前にスクリプトを追加するScriptManager.RegisterClientScriptBlockを使用してスクリプトを追加していたので、代わりにRegisterStartupScriptを使用しました(ここの違いを参照
Firas Assaad

2
かっこいい答え!それは私のasp.net Webアプリの魅力のように機能しました。+あなたのために
Pranesh Janarthanan

33

jQuery 1.3にアップグレードして使用します。

$(function() {

    $('div._Foo').live("mouseover", function(e) {
        // Do something exciting
    });

});

注:ライブはほとんどのイベントで機能しますが、すべてではありません。ドキュメントに完全なリストがあります


ライブを使用すると、更新パネルの問題が修正されます。ジャンプするのにフープは必要ありません。
Tim Scarborough、

ページロードで発生する必要がある何かはどうですか?たとえばゼブラストライプテーブルですか?$( 'TABLE TR:nth-​​child(odd)')。addClass( 'alt-row');
Adam Youngers、2011

3
更新するだけです。jQuery1.7以降では、代わりに.on()を使用することが推奨されています
George

1
live()IE7(jQuery 1.5.1 / VS2010プロジェクト)でこのメソッドを使用しているときに重大なエラーが見つかりました。live()通常AutoPostbackのv3.5 ASP.NETのUpdatePanel内で使用する場合<asp:DropDownList />とは対照的に、2つの部分ポストバックの原因は、ブラウザによって発行1.余分なポストバックが発生コンテンツ(中止さを)持たないと予想Page.IsPostBackするfalse私のバウンド内の状態を殺しました(コントロール)。犯人はlive()メソッドであることがわかりました。仕様に従ってUpdatePanelによって最初のポストバックが中止されることを理解していますが、キューに別のポストバックがない場合に限られます。
timmi4sa 2013

20

あなたも試すことができます:

<asp:UpdatePanel runat="server" ID="myUpdatePanel">
    <ContentTemplate>

        <script type="text/javascript" language="javascript">
        function pageLoad() {
           $('div._Foo').bind("mouseover", function(e) {
               // Do something exciting
           });
        }
        </script>

    </ContentTemplate>
</asp:UpdatePanel>

、pageLoad()はASP.NET ajaxイベントであるため、ページがクライアント側で読み込まれるたびに実行されます。


pageLoadは、更新パネルのすべてのASyncポストバックでイベントを複製します。
Zoは

17

私の答え?

function pageLoad() {

  $(document).ready(function(){

他の多くのソリューションが惨めに失敗した魅力のように働きました。


テキストの量に応じて、UserControlのUpdatePanelにあるリストビューのテキストエリアのサイズを変更するのに最適です。
リソース

更新パネルを使用してdom jquery関数をポストバックで正しく機能させるのに苦労しましたが、このソリューションは機能し、2つのシナリオで関数呼び出しを複製する必要はありませんでした。これにより、jquery関数とリスナーが利用可能になりました。注:スクリプトとjqueryライブラリーのすべてのインクルードを、ページ下部のFORM [end]タグの直前に配置していることに注意してください。ありがとう!!!
moto_geek

7

次のいずれかの方法を使用します。

  1. イベントバインディングを関数にカプセル化し、ページを更新するたびに実行します。イベントを同じ要素に何度もバインドしないように、特定の要素にイベントバインドを常に含めることができます。

  2. 基本的にメソッド1を自動で自動的に実行するlivequeryプラグインを使用します。優先順位は、イベントバインディングを制御する量によって異なります。


7

これは私のために働きました:

$(document).ready(function() {

    // Do something exciting

    var prm = Sys.WebForms.PageRequestManager.getInstance();

    prm.add_endRequest(function() {
        // re-bind your jQuery events here
    });

});

6

関数pageLoad()は、この状況で使用するのは非常に危険です。イベントを複数回配線することができます。また、.live()はドキュメント要素にアタッチされ、ページ全体をトラバースする必要があるため(低速で安っぽい)、私は.live()から離れます。

これまで見てきた最善の解決策は、更新パネルの外のラッパーでjQuery .delegate()関数を使用し、バブリングを利用することです。それ以外の場合は、UpdatePanelsで動作するように設計されたMicrosoftのAjaxライブラリを使用して、ハンドラーを常に接続できます。



4

私にも同様の問題があり、イベントバブリングとイベント委任を利用してそれを処理するのが最も効果的であることがわかりました。イベントの委任の良い点は、一度設定すると、AJAXの更新後にイベントを再バインドする必要がないことです。

私のコードでは、更新パネルの親要素にデリゲートを設定しています。この親要素は更新時に置き換えられないため、イベントバインディングは影響を受けません。

jQueryでのイベントの委任を処理する優れた記事とプラグインがいくつかあり、その機能は1.3リリースに組み込まれる可能性があります。参考に使用する記事/プラグインは次のとおりです。

http://www.danwebb.net/2008/2/8/event-delegation-made-easy-in-jquery

何が起こっているのか理解したら、更新のたびにイベントを再バインドすることを覚えておくことよりも信頼性の高い、はるかにエレガントなソリューションであると思います。これには、ページがアンロードされるときに1つのイベントをバインド解除するという追加の利点もあります。


4

FWIW、mootoolsで同様の問題が発生しました。イベントの再アタッチは正しい動きでしたが、リクエストの最後に行う必要がありました。

var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(function() {... 

beginRequestによってnull参照JS例外が発生する場合に注意する必要があることだけです。

乾杯



3
pageLoad = function () {
    $('#div').unbind();
    //jquery here
}

pageLoad関数は、最初のページ読み込みとすべてのupdatepanel非同期ポストバックで実行されるため、このケースに最適です。jqueryをupdatepanelポストバックで機能させるには、バインド解除メソッドを追加する必要がありました。

http://encosia.com/document-ready-and-pageload-are-not-the-same/


2

私の回答は上記のすべてのエキスパートコメントに基づいていますが、以下は、ポストバックごとと非同期ポストバックごとにJavaScriptコードが引き続き実行されることを確認するために誰でも使用できる次のコードです。

私の場合、ページ内にユーザーコントロールがありました。以下のコードをユーザーコントロールに貼り付けるだけです。

<script type="text/javascript"> 
        var prm = Sys.WebForms.PageRequestManager.getInstance();
    prm.add_endRequest(EndRequestHandler);
    function EndRequestHandler(sender, args) {
        if (args.get_error() == undefined) {
            UPDATEPANELFUNCTION();
        }                   
    }

    function UPDATEPANELFUNCTION() {
        jQuery(document).ready(function ($) {
            /* Insert all your jQuery events and function calls */
        });
    }

    UPDATEPANELFUNCTION(); 

</script>

2

更新パネルは、ロードのたびにJqueryを常に組み込みのScriptmanagerのスクリプトに置き換えます。このようなpageRequestManagerのインスタンスメソッドを使用すると、より良い...

Sys.WebForms.PageRequestManager.getInstance().add_endRequest(onEndRequest)
    function onEndRequest(sender, args) {
       // your jquery code here
      });

それはうまくいきます...


古い投稿ですが、私を助けてくれたものです。Sys.WebForms.PageRequestManagerはその時点でのみ使用できるため、これに追加したい1つのこと:add_endRequestコードの場所はUpdatePanel内にある必要があります。ただし、実際の関数がその場所にある必要はありません。したがって、私の場合、バインドしたいコードを含むscript.jsファイルが関数内に含まれています。このscript.jsファイルには、上記の関数を呼び出すdocument.ready呼び出しがあります。次に、UpdatePanelに、上記の関数を呼び出すadd_endRequestコードがあります。
キランラマスワミー2017年

1

以下のスクリプトを使用し、それに応じてスクリプトの本文を変更します。

       <script>
        //Re-Create for on page postbacks
        var prm = Sys.WebForms.PageRequestManager.getInstance();
        prm.add_endRequest(function () {
           //your codes here!
        });
    </script>

0

ブライアン・マッケイの答えに応じて:

JavaScriptをUserControlのHTMLに直接挿入するのではなく、ScriptManagerを介してページに挿入します。私の場合、UpdatePanelが完了して戻った後に表示されるフォームまでスクロールする必要があります。これは、コードビハインドファイルに入ります。私のサンプルでは、メインコンテンツページにprm変数をすでに作成しています。

private void ShowForm(bool pShowForm) {
    //other code here...
    if (pShowForm) {
        FocusOnControl(GetFocusOnFormScript(yourControl.ClientID), yourControl.ClientID);
    }
}

private void FocusOnControl(string pScript, string pControlId) {
    ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "focusControl_" + pControlId, pScript, true);
}

/// <summary>
/// Scrolls to the form that is made visible
/// </summary>
/// <param name="pControlId">The ClientID of the control to focus on after the form is made visible</param>
/// <returns></returns>
private string GetFocusOnFormScript(string pControlId) {
    string script = @"
    function FocusOnForm() {
        var scrollToForm = $('#" + pControlId + @"').offset().top;
        $('html, body').animate({ 
            scrollTop: scrollToForm}, 
            'slow'
        );
        /* This removes the event from the PageRequestManager immediately after the desired functionality is completed so that multiple events are not added */
        prm.remove_endRequest(ScrollFocusToFormCaller);
    }
    prm.add_endRequest(ScrollFocusToFormCaller);
    function ScrollFocusToFormCaller(sender, args) {
        if (args.get_error() == undefined) {
            FocusOnForm();
        }
    }";
    return script;
}

0
Sys.Application.add_load(LoadHandler); //This load handler solved update panel did not bind control after partial postback
function LoadHandler() {
        $(document).ready(function () {
        //rebind any events here for controls under update panel
        });
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.