jQuery $ (dokumen) .ready dan UpdatePanels?

475

Saya menggunakan jQuery untuk menghubungkan beberapa efek mouseover pada elemen yang ada di dalam UpdatePanel. Peristiwa terikat $(document).ready. Sebagai contoh:

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

Tentu saja, ini berfungsi dengan baik pertama kali halaman dimuat, tetapi ketika UpdatePanel melakukan pembaruan sebagian halaman, itu tidak berjalan dan efek mouseover tidak berfungsi lagi di dalam UpdatePanel.

Apa pendekatan yang disarankan untuk memasang kabel di jQuery tidak hanya pada pemuatan halaman pertama, tetapi setiap kali UpdatePanel mengaktifkan pembaruan sebagian halaman? Haruskah saya menggunakan siklus hidup ASP.NET ajax bukan $(document).ready?

Ramuan Caudill
sumber
Memberikan ini mencoba saya pikir itu akan memecahkan masalah Anda codeproject.com/Articles/21962/...
Baxterboom
1
Mirip dengan pertanyaan ini: stackoverflow.com/questions/301473/…
Per Hornshøj-Schierbeck

Jawaban:

545

UpdatePanel sepenuhnya menggantikan konten panel pembaruan pada pembaruan. Ini berarti bahwa peristiwa yang Anda langgani tidak lagi berlangganan karena ada elemen baru di panel pembaruan itu.

Apa yang telah saya lakukan untuk mengatasi ini adalah berlangganan kembali ke acara yang saya butuhkan setelah setiap pembaruan. Saya menggunakan $(document).ready()untuk memuat awal, kemudian menggunakan Microsoft PageRequestManager(tersedia jika Anda memiliki panel pembaruan pada halaman Anda) untuk berlangganan kembali setiap pembaruan.

$(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
});

Ini PageRequestManageradalah objek javascript yang tersedia secara otomatis jika panel pembaruan ada di halaman. Anda tidak perlu melakukan apa pun selain kode di atas untuk menggunakannya selama UpdatePanel ada di halaman.

Jika Anda memerlukan kontrol yang lebih terperinci, peristiwa ini meneruskan argumen yang mirip dengan bagaimana .NET peristiwa dilewati argumen (sender, eventArgs)sehingga Anda dapat melihat apa yang mengangkat peristiwa tersebut dan hanya mengikat kembali jika diperlukan.

Ini adalah versi terbaru dari dokumentasi dari Microsoft: msdn.microsoft.com/.../bb383810.aspx


Opsi yang lebih baik yang mungkin Anda miliki, tergantung pada kebutuhan Anda, adalah menggunakan jQuery's .on(). Metode ini lebih efisien daripada berlangganan ulang ke elemen DOM pada setiap pembaruan. Baca semua dokumentasi sebelum Anda menggunakan pendekatan ini, karena mungkin atau mungkin tidak memenuhi kebutuhan Anda. Ada banyak plugin jQuery yang tidak masuk akal untuk ditolak untuk digunakan .delegate()atau .on(), jadi dalam kasus itu, Anda lebih baik berlangganan ulang.

Dan Herbert
sumber
1
Harap lebih tepat saat Anda memberikan penjelasan. Maksud saya contoh penggunaan jauh lebih baik daripada beberapa baris kode yang tersebar. Lihat penjelasan Brian MacKay. Itu sempurna!
truthseeker
3
@Dan, Pada jQuery 1.7, .delegate()telah digantikan oleh.on()
Gabriele Petrioli
@ GabyakaG.Petrioli Saya menyadari itu telah digantikan, tetapi karena jawaban ini tampaknya memecahkan masalah umum, saya ingin memaksimalkan kompatibilitas dengan versi jQuery yang lebih lama yang belum diupgrade. Jawaban saya sebelumnya direkomendasikan .live(...)yang secara resmi tidak digunakan lagi di 1.7 dan dapat dihapus di versi yang akan datang. Saya sengaja memilih .delegate()karena telah didukung di jQuery untuk sementara waktu sekarang dan tidak mungkin dihapus dalam waktu dekat. Namun, saya akan memperbarui jawaban saya untuk menyebutkan .on()juga bagi mereka yang dapat menggunakannya.
Dan Herbert
12
Lebih baik mendeklarasikan dan memasang prm var di dalam $ (dokumen). Sudah, karena mungkin Sys belum dideklarasikan (tergantung di mana skrip berada).
drake7707
1
@AhmedSamy Tidak disarankan untuk menggunakan jQuery.delegate()lagi. Itu telah digantikan oleh jQuery.on()yang merupakan API yang disukai untuk digunakan. delegate()hanya pembungkus untuk penggunaan khusus on(), dan mungkin saja itu akan menjadi usang di masa depan. Penyebutan komentar saya sebelumnya delegate()ditulis lebih dari setahun yang lalu ketika jQuery 1.7 (yang memperkenalkan on()API) baru dirilis. Dengan jQuery 1.9 yang sudah keluar dan 2.0 dalam versi beta sedang disiapkan untuk rilis, adalah ide yang baik untuk menghindari penggunaan delegate()dalam kode baru apa pun.
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>

Area yang akan diperbarui.

<asp:UpdatePanel...
<ContentTemplate
     <script type="text/javascript">
                    Sys.Application.add_load(BindEvents);
     </script>
 *// Staff*
</ContentTemplate>
    </asp:UpdatePanel>
Barbaros Alp
sumber
Berfungsi dengan baik untuk asp: GridView TextBox di dalam <EditItemTemplate>
Dan Randolph
Masalah dengan solusi ini, adalah bahwa, ketika ia bekerja, ia membunuh kembali posting asinkron UpdatePanel - membuat UpdatePanel tidak berguna lagi. (menghela napas)
MC9000
63

Kontrol Pengguna dengan jQuery Di dalam UpdatePanel

Ini bukan jawaban langsung untuk pertanyaan itu, tetapi saya memang menyatukan solusi ini dengan membaca jawaban yang saya temukan di sini, dan saya pikir seseorang mungkin menganggapnya berguna.

Saya mencoba menggunakan pembatas teks jQuery di dalam Kontrol Pengguna. Ini rumit, karena Kontrol Pengguna berjalan di dalam UpdatePanel, dan kehilangan ikatannya saat dipanggil kembali.

Jika ini hanya sebuah halaman, jawaban di sini akan diterapkan secara langsung. Namun, Kontrol Pengguna tidak memiliki akses langsung ke tag kepala, juga tidak memiliki akses langsung ke UpdatePanel seperti yang diasumsikan oleh beberapa jawaban.

Saya akhirnya menempatkan blok skrip ini tepat di atas markup Kontrol Pengguna saya. Untuk ikatan awal, ia menggunakan $ (dokumen). Sudah, dan kemudian menggunakan prm.add_endRequest dari sana:

<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>

Jadi ... Hanya berpikir seseorang mungkin ingin tahu bahwa ini berhasil.

Brian MacKay
sumber
2
Saya tidak bisa mendapatkan ini bekerja untuk kehidupan saya. Lalu saya memindahkannya dari kepala ke kaki dan itu berhasil. Tidak positif, tetapi saya pikir ini harus dilakukan setelah ScriptManager yang saya gunakan.
Adam Youngers
Dalam kasus saya, saya menambahkan skrip menggunakan ScriptManager.RegisterClientScriptBlock yang menambahkan skrip sebelum Sys didefinisikan, jadi saya akhirnya menggunakan RegisterStartupScript sebagai gantinya (lihat perbedaan di sini )
Firas Assaad
2
Jawaban keren! itu bekerja seperti pesona di aplikasi web asp.net saya. + untuk Anda
Pranesh Janarthanan
33

Tingkatkan ke jQuery 1.3 dan gunakan:

$(function() {

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

});

Catatan: siaran langsung dengan sebagian besar acara, tetapi tidak semua. Ada daftar lengkap dalam dokumentasi .

svinto
sumber
Menggunakan perbaikan langsung masalah dengan panel pembaruan. Tidak perlu simpai untuk melompati.
Tim Scarborough
Bagaimana dengan sesuatu yang perlu terjadi pada pageload? Misalnya tabel penguraian zebra? $ ('TABLE TR: nth-child (odd)'). AddClass ('alt-row');
Adam Youngers
3
Hanya untuk memperbarui, sejak jQuery 1.7 sekarang disarankan untuk menggunakan .on () sebagai gantinya
George
1
Baru saja menemukan kegagalan serius saat menggunakan live()metode di IE7 (proyek jQuery 1.5.1 / VS2010). Bila menggunakan live()dalam sebuah UpdatePanel di v3.5 ASP.NET biasa AutoPostbackdari <asp:DropDownList />penyebab 2 postbacks parsial yang bertentangan dengan 1. diharapkan The postback ekstra yang dikeluarkan oleh browser tidak memiliki konten (dibatalkan) menyebabkan Page.IsPostBackmenjadi false(yang membunuh negara dalam terikat saya kontrol). Saya menemukan pelakunya menjadi metode live (). Saya menyadari bahwa postback pertama dibatalkan oleh UpdatePanel per spec tetapi hanya jika ada satu lagi dalam antrian yang tidak ada.
timmi4sa
20

Anda juga dapat mencoba:

<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>

, karena pageLoad () adalah peristiwa ajax ASP.NET yang dijalankan setiap kali halaman dimuat di sisi klien.

Daniel Hursan
sumber
pageLoad menduplikasi acara di setiap postback ASync dari Panel Pembaruan.
Zo Memiliki
17

Jawabanku?

function pageLoad() {

  $(document).ready(function(){

dll.

Bekerja seperti pesona, di mana sejumlah solusi lain gagal total.

Jono
sumber
Sempurna untuk mengubah ukuran teks di Listview saya di UpdatePanel saya di UserControl saya sesuai dengan jumlah teks.
Sumberdaya
Saya berjuang untuk membuat fungsi dom jquery berfungsi dengan benar pada postback dengan panel pembaruan, solusi ini berhasil dan saya tidak harus menduplikasi panggilan fungsi saya dalam 2 skenario. Ini membuat fungsi jquery dan pendengar tersedia. Catatan saya meletakkan semua skrip dan pustaka jquery saya sertakan tepat sebelum tag FORMULIR [akhir] di bagian bawah halaman. Terima kasih!!!
moto_geek
7

Saya akan menggunakan salah satu pendekatan berikut:

  1. Meringkas peristiwa yang mengikat dalam suatu fungsi dan menjalankannya setiap kali Anda memperbarui halaman. Anda selalu dapat berisi acara yang mengikat elemen tertentu agar tidak mengikat acara berulang kali ke elemen yang sama.

  2. Gunakan plug-in livequery , yang pada dasarnya melakukan metode satu untuk Anda secara otomatis. Preferensi Anda dapat bervariasi tergantung pada jumlah kontrol yang ingin Anda miliki pada acara yang mengikat.

Eran Galperin
sumber
7

Ini bekerja untuk saya:

$(document).ready(function() {

    // Do something exciting

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

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

});
Turbojohan
sumber
6

fungsi pageLoad () sangat berbahaya untuk digunakan dalam situasi ini. Anda bisa membuat acara menjadi kabel beberapa kali. Saya juga akan tinggal jauh dari .live () karena melekat pada elemen dokumen dan harus melintasi seluruh halaman (lambat dan jelek).

Solusi terbaik yang saya lihat sejauh ini adalah dengan menggunakan fungsi jQuery .delegate () pada pembungkus di luar panel pembaruan dan memanfaatkan penggelembungan. Selain itu, Anda selalu bisa memasang penangan menggunakan perpustakaan Ajax Microsoft yang dirancang untuk bekerja dengan UpdatePanels.

Norma
sumber
6

Ketika $(document).ready(function (){...})tidak berfungsi setelah posting halaman kembali maka gunakan fungsi JavaScript pageLoad di Asp.page sebagai berikut:

<script type="text/javascript" language="javascript">
function pageLoad() {
// Initialization code here, meant to run once. 
}
</script>
Pradeep Lebih Banyak
sumber
Ya, periksa juga isPartialLoad: stackoverflow.com/questions/301473/…
Steve Greene
4

Saya memiliki masalah yang sama dan menemukan cara yang paling berhasil adalah mengandalkan Event Bubbling dan delegasi acara untuk menanganinya. Hal yang menyenangkan tentang pendelegasian acara adalah bahwa sekali pengaturan, Anda tidak harus membatalkan acara setelah pembaruan AJAX.

Apa yang saya lakukan dalam kode saya adalah mengatur delegasi pada elemen induk dari panel pembaruan. Elemen induk ini tidak diganti pada pembaruan dan oleh karena itu pengikatan acara tidak terpengaruh.

Ada sejumlah artikel dan plugin yang bagus untuk menangani delegasi acara di jQuery dan fitur ini kemungkinan akan dimasukkan ke rilis 1.3. Artikel / plugin yang saya gunakan untuk referensi adalah:

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

Setelah Anda memahami apa yang terjadi, saya pikir Anda akan menemukan ini solusi yang jauh lebih elegan yang lebih dapat diandalkan daripada mengingat untuk mengikat kembali acara setelah setiap pembaruan. Ini juga memiliki manfaat tambahan yaitu memberi Anda satu acara untuk dilepas saat halaman dibongkar.

Joe Brinkman
sumber
4

FWIW, saya mengalami masalah serupa w / mootools. Melampirkan kembali acara saya adalah langkah yang benar, tetapi perlu dilakukan di akhir permintaan..ceg

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

Hanya sesuatu yang perlu diingat jika beginRequest menyebabkan Anda mendapatkan referensi JS pengecualian nol.

Bersulang


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

Fungsi pageLoad sangat cocok untuk kasus ini karena berjalan pada halaman awal dan setiap postback updatepanel async. Saya hanya perlu menambahkan metode unbind untuk membuat jquery bekerja pada postback updatepanel.

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

Duane
sumber
2

Jawaban saya didasarkan pada semua komentar ahli di atas, tetapi di bawah ini adalah kode berikut yang dapat digunakan siapa pun untuk memastikan pada setiap postback dan pada setiap postback asinkron, kode JavaScript masih akan dieksekusi.

Dalam kasus saya, saya memiliki kontrol pengguna dalam satu halaman. Cukup tempel kode di bawah ini di kontrol pengguna Anda.

<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>
Abhishek Shrivastava
sumber
2

Panel Pembaruan selalu menggantikan Jquery Anda dengan skrip Scriptmanager bawaannya setelah setiap pemuatan. Lebih baik jika Anda menggunakan metode instance pageRequestManager seperti ini ...

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

itu akan bekerja dengan baik ...

Rohit Sharma
sumber
Posting lama, tetapi yang membantu saya. Satu hal yang ingin saya tambahkan ke ini: lokasi kode add_endRequest harus di dalam UpdatePanel, karena Sys.WebForms.PageRequestManager hanya tersedia pada saat itu. Namun, fungsi sebenarnya tidak harus di lokasi itu. Jadi, dalam kasus saya, saya memiliki file script.js yang berisi kode yang saya inginkan terikat, terkandung dalam suatu fungsi. Dalam file script.js itu, saya memiliki panggilan document.ready, yang memanggil fungsi di atas. Kemudian, di UpdatePanel saya, saya memiliki kode add_endRequest, yang juga memanggil fungsi di atas.
Kiran Ramaswamy
1

Gunakan skrip di bawah ini dan ubah badan skrip yang sesuai.

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

Menanggapi jawaban Brian MacKay:

Saya menyuntikkan JavaScript ke halaman saya melalui ScriptManager alih-alih memasukkannya langsung ke HTML UserControl. Dalam kasus saya, saya perlu menggulir ke formulir yang dibuat terlihat setelah UpdatePanel selesai dan dikembalikan. Ini berlaku pada kode di belakang file. Dalam sampel saya, saya sudah membuat variabel PRM di halaman konten utama.

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;
}
fujiiface
sumber
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
        });
}
Tony Dong
sumber