jQuery $ (belge) .ready ve UpdatePanels?


475

Bir UpdatePanel içindeki öğeler üzerinde bazı fareyle üzerine gelme efektleri bağlamak için jQuery kullanıyorum. Olaylar bağlı $(document).ready. Örneğin:

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

Tabii ki, bu sayfa ilk yüklendiğinde iyi çalışır, ancak UpdatePanel kısmi sayfa güncellemesi yaptığında çalışmaz ve fareyle üzerine gelme efektleri UpdatePanel içinde artık çalışmaz.

JQuery'de yalnızca ilk sayfa yüklemesinde değil, bir UpdatePanel kısmi sayfa güncellemesi her başlattığında kablolama için önerilen yaklaşım nedir? Bunun yerine ASP.NET ajax yaşam döngüsünü $(document).readymi kullanmalıyım ?


Bunu deneyin, sorununuzu çözeceğini düşünüyorum codeproject.com/Articles/21962/…
Baxterboom

Yanıtlar:


545

Bir UpdatePanel, bir güncellemedeki güncelleme panelinin içeriğini tamamen değiştirir. Bu, bu güncelleme panelinde yeni öğeler olduğu için abone olduğunuz etkinliklerin artık abone olmadığı anlamına gelir.

Bu sorunu çözmek için yaptığım, her güncellemeden sonra ihtiyacım olan olaylara yeniden abone olmak. $(document).ready()İlk yükleme için kullanırım , ardından PageRequestManagerher güncellemeye yeniden abone olmak için Microsoft'un (sayfanızda bir güncelleme paneliniz varsa kullanılabilir) kullanın.

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

Bu PageRequestManager, sayfada bir güncelleme paneli varsa otomatik olarak kullanılabilen bir javascript nesnesidir. UpdatePanel sayfada olduğu sürece kullanmak için yukarıdaki koddan başka bir şey yapmanız gerekmez.

Daha ayrıntılı kontrole ihtiyacınız varsa, bu olay, .NET olaylarının bağımsız değişkenlerden nasıl geçirildiğine benzer argümanlar geçirir, (sender, eventArgs)böylece olayı neyin yükselttiğini görebilir ve yalnızca gerektiğinde yeniden bağlayabilirsiniz.

Microsoft'un belgelerinin en son sürümü: msdn.microsoft.com/.../bb383810.aspx


İhtiyaçlarınıza bağlı olarak sahip olabileceğiniz daha iyi bir seçenek, jQuery'leri kullanmaktır .on(). Bu yöntem, her güncellemede DOM öğelerine yeniden abone olmaktan daha etkilidir. Ancak, bu yaklaşımı kullanmadan önce tüm belgeleri okuyun, çünkü ihtiyaçlarınızı karşılayabilir veya karşılamayabilir. Kullanmak için refactor için mantıksız olacak bir sürü jQuery eklentisi vardır, .delegate()ya da .on()bu gibi durumlarda, yeniden abone olmanız daha iyi olur.


1
Lütfen açıklama yaparken daha kesin olun. Yani bir kullanım örneği dağınık çift kod satırından çok daha iyi. Brian MacKay açıklamasına bakın. Mükemmel!
truthseeker

3
@ Dan, jQuery 1.7 itibariyle, .delegate()yerini aldı.on()
Gabriele Petrioli

@ GabyakaG.Petrioli Yerini aldığını anlıyorum, ancak bu cevap ortak bir sorunu çözdüğü için henüz yükseltilmemiş olan jQuery'nin eski sürümleriyle uyumluluğu en üst düzeye çıkarmak istedim. Cevabım daha önce .live(...)önerilmişti ve 1.7'de resmen kullanımdan kaldırıldı ve gelecekteki bir sürümde kaldırılabilir. .delegate()Bir süredir jQuery'de desteklendiğinden ve yakında kaldırılamayacağı için kasıtlı olarak seçtim . Ancak, cevabımı .on()kullananlar için de bahsetmek istiyorum .
Dan Herbert

12
$ (Belge) içindeki prm değişkenini bildirmek ve bağlamak daha iyidir.
drake7707

1
@AhmedSamy Artık kullanılması önerilmez jQuery.delegate(). Yerini jQuery.on()kullanmak için tercih edilen API olan yerini almıştır . delegate()sadece belirli bir kullanımı için bir on()sarıcıdır ve gelecekte kullanımdan kaldırılması mümkündür. Benim önceki yorum bahseden delegate()bir yıl önce jQuery 1.7 ( on()API tanıttı ) yeni yayınlandığı zaman yazılmıştır . JQuery 1.9 zaten çıkmış ve 2.0 sürümü beta sürümünde hazırlanırken delegate(), herhangi bir yeni kodda kullanmaktan kaçınmak iyi bir fikirdir .
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>

Güncellenecek alan.

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

Asp için iyi çalışıyor: <EditItemTemplate> içindeki GridView TextBox
Dan Randolph

Bu çözümün sorunu, çalışırken, UpdatePanel'in eşzamansız gönderisini geri öldürmesi ve UpdatePanel'i bir kez daha yararsız hale getirmesidir. (iç
çekiyor

63

Bir UpdatePanel İçinde jQuery ile Kullanıcı Kontrolü

Bu soruya doğrudan bir cevap değil, ama burada bulduğum cevapları okuyarak bu çözümü bir araya getirdim ve birinin yararlı bulabileceğini düşündüm.

Bir Kullanıcı Denetimi içinde bir jQuery textarea sınırlayıcı kullanmaya çalışıyordum. Bu zor, çünkü Kullanıcı Denetimi bir UpdatePanel içinde çalışır ve geri arama sırasında bağlarını kaybediyordu.

Bu sadece bir sayfa olsaydı, buradaki yanıtlar doğrudan geçerli olurdu. Ancak, Kullanıcı Denetimlerinin kafa etiketine doğrudan erişimi yoktur ve bazı yanıtların varsaydığı gibi UpdatePanel'e doğrudan erişimi yoktur.

Bu komut dosyası bloğunu Kullanıcı Denetimimin işaretlemesinin en üstüne koydum. İlk bağlama için $ (document) .ready kullanır ve sonra oradan prm.add_endRequest kullanır:

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

Yani ... Birisinin bunun işe yaradığını bilmek isteyebileceğini düşündüm.


2
Bunu hayatım boyunca çalıştıramadım. Sonra başından altbilgiye taşıdım ve işe yaradı. Olumlu değil, ama kullandığım ScriptManager sonra gelmesi gerektiğini düşünüyorum.
Adam Youngers

Bunun yerine RegisterStartupScript kullanarak sona erdi Benim durumumda ben Sys önce komut dosyasını ekler ScriptManager.RegisterClientScriptBlock kullanarak alfabenin eklediğini tanımlanır, bu nedenle (farkı görmek burada )
Firas Assaad

2
Güzel cevap! benim asp.net web uygulamasında bir cazibe gibi çalıştı. + senin için
Pranesh Janarthanan

33

JQuery 1.3 sürümüne yükseltin ve şunları kullanın:

$(function() {

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

});

Not: Canlı, tüm etkinliklerle değil, çoğu etkinlikle çalışır. Belgelerde tam bir liste var .


Canlı kullanımı, güncelleme panelleriyle ilgili sorunu giderir. Atlamak için çemberlere gerek yok.
Tim Scarborough

Sayfa yüklemesinde olması gereken bir şey ne olacak? Örneğin zebra çizgi masaları? $ ('TABLO TR: nth-child (tek)'). AddClass ('alt-satır');
Adam Youngers

3
Sadece güncellemek için, jQuery 1.7'den beri artık .on () kullanılması önerilir
George

1
live()IE7 (jQuery 1.5.1 / VS2010 projesi) yöntemini kullanırken ciddi bir hata buldum . Kullanırken live()bir UpdatePanel içine v3.5 ASP.NET düzenli AutoPostbackbir <asp:DropDownList />nedenleri tarayıcı tarafından yayınlanan ekstra geri gönderme (iptal) içeriği yoksun beklenen 1. aksine 2 kısmi geri yayınları neden Page.IsPostBackolmak falsebenim bağlı iç durumunu öldürür hangi ( kontroller). Suçluyu live () yöntemi olarak buldum. Ben 1st postback spec başına UpdatePanel tarafından iptal edileceğini, ancak sadece kuyrukta olmayan başka bir tane varsa farkındayım.
timmi4sa

20

Ayrıca deneyebilirsiniz:

<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 (), sayfa istemci tarafına her yüklendiğinde yürütülen bir ASP.NET ajax olayı olduğundan.


pageLoad Güncelleme Paneli'nin her ASync geri gönderisindeki olayları çoğaltın.
Zo

17

Cevabım?

function pageLoad() {

  $(document).ready(function(){

vb.

Bir dizi diğer çözümün sefil bir şekilde başarısız olduğu bir cazibe gibi çalıştı.


UserControl benim UpdatePanel benim liste görünümünde metin miktarına göre yeniden boyutlandırma için mükemmel.
Kaynak

Dom jquery işlevlerinin güncelleme panelleriyle geri gönderimde doğru çalışmasını sağlamak için mücadele ettim, bu çözüm çalıştı ve işlev senaryolarımı 2 senaryoda çoğaltmak zorunda kalmadım. Bu, jquery işlevlerini ve dinleyiciyi kullanılabilir tuttu. Not Tüm komut dosyası ve jquery kitaplığı, sayfanın altındaki FORM [bitiş] etiketinin hemen önüne koydum. Teşekkürler!!!
moto_geek

7

Aşağıdaki yaklaşımlardan birini kullanırdım:

  1. Olay bağlamasını bir işlevde kapsülleyin ve sayfayı her güncellediğinizde çalıştırın. Olayları aynı öğelere birden çok kez bağlamamak için her zaman olayı belirli öğelere bağlayabilirsiniz.

  2. Temel olarak otomatik olarak sizin için birinci yöntemi uygulayan livequery eklentisini kullanın . Tercihiniz, etkinlik bağlaması üzerinde olmasını istediğiniz denetim miktarına bağlı olarak değişebilir.


7

Bu benim için çalıştı:

$(document).ready(function() {

    // Do something exciting

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

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

});

6

pageLoad () işlevi bu durumda kullanmak için çok tehlikelidir. Etkinliklerin birden çok kez kablolanmasını sağlayabilirsiniz. Ayrıca belge öğesine bağlı ve tüm sayfayı (yavaş ve bok) geçmek zorunda olduğu gibi .live () uzak kalmak istiyorum.

Şimdiye kadar gördüğüm en iyi çözüm, güncelleme panelinin dışındaki bir sarıcıda jQuery .delegate () işlevini kullanmak ve köpürme kullanmaktır. Bunun dışında, her zaman Microsoft'un UpdatePanels ile çalışacak şekilde tasarlanmış Ajax kütüphanesini kullanarak işleyicileri bağlayabilirsiniz.


6

Ne zaman $(document).ready(function (){...})sayfa sonrası arka peşinde değil iş sonra aşağıdaki gibi Asp.page JavaScript işlevi pageload kullanın:

<script type="text/javascript" language="javascript">
function pageLoad() {
// Initialization code here, meant to run once. 
}
</script>

Evet, isPartialLoad için de kontrol edin: stackoverflow.com/questions/301473/…
Steve Greene

4

Benzer bir sorunum vardı ve en iyi şekilde çalışmanın Olay Bubbling'e ve olay delegasyonuna güvenmek olduğunu gördüm. Etkinlik yetkilendirmesi ile ilgili güzel bir şey, kurulumdan sonra, AJAX güncellemesinden sonra olayları yeniden hatırlatmanız gerekmemesidir.

Kodumda ne yaptığım güncelleme panelinin üst öğesinde bir temsilci kurmaktır. Bu üst öğe bir güncelleştirme ile değiştirilmez ve bu nedenle olay bağlama etkilenmez.

JQuery'de etkinlik yetkilendirmesini ele almak için bir dizi iyi makale ve eklenti vardır ve özellik muhtemelen 1.3 sürümüne dönüştürülecektir. Referans için kullandığım makale / eklenti:

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

Ne olduğunu anladıktan sonra, her güncellemeden sonra olayları yeniden bağlamayı hatırlamaktan daha güvenilir olan çok daha zarif bir çözüm bulacağınızı düşünüyorum. Bu ayrıca, sayfa kaldırıldığında size bir etkinlik açmanız için ek bir avantaj sağlar.


4

FWIW, mootools ile benzer bir sorun yaşadım. Etkinliklerimi yeniden eklemek doğru hamleydi, ancak isteğin sonunda yapılması gerekiyordu ...

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

BeginRequest, null referans JS istisnaları almanıza neden oluyorsa akılda tutulması gereken bir şey.

Şerefe



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

PageLoad işlevi, ilk sayfa yüklemesinde ve her güncelleme paneli zaman uyumsuz geri gönderilmesinde çalıştığı için bu durum için mükemmeldir. Ben sadece jquery updatepanel postbacks çalışması için unbind yöntemi eklemek zorunda kaldı.

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


2

Cevabım yukarıdaki tüm uzman yorumlarına dayanmaktadır, ancak aşağıda herkesin her bir geri gönderme ve her bir eşzamansız geri bildirimde JavaScript kodunun yürütülmesini sağlamak için kullanabileceği aşağıdaki kod yer almaktadır.

Benim durumumda, bir sayfada kullanıcı kontrolüm vardı. Aşağıdaki kodu kullanıcı kontrolünüze yapıştırmanız yeterlidir.

<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

Güncelleme Paneli, her yükten sonra her zaman Jquery'nizi dahili Scriptmanager'in komut dosyalarıyla değiştirir. Böyle pageRequestManager'ın örnek yöntemlerini kullanırsanız daha iyi ...

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

iyi çalışacak ...


Eski bir yazı, ama bana yardım eden bir yazı. Buna eklemek istediğim bir şey var: Sys.WebForms.PageRequestManager yalnızca bu noktada kullanılabilir olduğu için add_endRequest kodunun konumu UpdatePanel içinde olmalıdır. Ancak, gerçek işlevin bu konumda olması gerekmez. Yani, benim durumumda, ben bir fonksiyon içinde yer alan, bağlı istiyorum kod içeren bir script.js dosyası var. Bu script.js dosyasında, yukarıdaki işlevi çağıran bir document.ready çağrı var. Sonra, benim UpdatePanel, ben de yukarıdaki işlevi çağıran add_endRequest kodu var.
Kiran Ramaswamy

1

Aşağıdaki komut dosyasını kullanın ve komut dosyasının gövdesini uygun şekilde değiştirin.

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

0

Brian MacKay'ın cevabına cevap olarak:

JavaScript'i doğrudan UserControl HTML'sine koymak yerine ScriptManager aracılığıyla sayfama enjekte ediyorum. Benim durumumda, UpdatePanel bittikten ve döndükten sonra görünür hale getirilmiş bir forma geçmem gerekiyor. Bu dosyanın arkasındaki koda gider. Örneğimde , ana içerik sayfasında prm değişkenini zaten oluşturdum .

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
        });
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.