Ponowne wiązanie zdarzeń w jQuery po aktualizacji Ajax (panel aktualizacji)

80

Mam kilka elementów wejściowych i opcji na mojej stronie, każdy (prawie) ma dołączone zdarzenie, aby zaktualizować tekst na stronie po ich zmianie. Używam jQuery, które jest naprawdę fajne :)

Używam również frameworka Microsofts Ajax , wykorzystując UpdatePanel. Powodem, dla którego to robię, jest to, że pewne elementy są tworzone na stronie w oparciu o logikę po stronie serwera. Naprawdę nie chcę wyjaśniać, dlaczego używam UpdatePanel - nawet jeśli można (można to z pewnym wysiłkiem) przepisać tak, aby używał tylko jQuery. Nadal chcę tego UpdatePanel.

Prawdopodobnie zgadłeś - po ogłoszeniu zwrotnym na UpdatePanel zdarzenia jQuery przestają działać. Właściwie spodziewałem się tego, ponieważ "ogłaszanie zwrotne" nie jest tak naprawdę nowym ogłoszeniem zwrotnym, więc mój kod w pliku document.ready, który wiąże zdarzenia, nie zostanie ponownie uruchomiony. Potwierdziłem również swoje podejrzenie, czytając o tym w bibliotekach pomocy jQuery.

W każdym razie pozostaje problem z ponownym wiązaniem moich kontrolek po zakończeniu aktualizacji DOM przez UpdatePanel . Preferuję rozwiązanie, które nie wymaga dodawania większej liczby plików .js (wtyczek jQuery) do strony, ale coś tak prostego, jak przechwycenie `` afterupdating '' UpdatePanel, w którym mogę po prostu wywołać moją metodę, aby ponownie powiązać wszystkie elementy formularza .

Per Hornshøj-Schierbeck
źródło
To jest bardzo podobne do tego pytania: stackoverflow.com/questions/256195/…
Dan Herbert

Odpowiedzi:

85

Ponieważ korzystasz z ASP.NET AJAX, będziesz mieć dostęp do programu pageLoadobsługi zdarzeń, który jest wywoływany za każdym razem, gdy strona publikuje zwrotną, pełną lub częściową z UpdatePanel. Wystarczy umieścić tę funkcję na swojej stronie, nie jest wymagane podłączanie.

function pageLoad(sender, args)
{
   if (args.get_isPartialLoad())
   {
       //Specific code for partial postbacks can go in here.
   }
}
Phil Jenkins
źródło
1
Nie ma problemu - to tylko jeden sposób na zrobienie tego przy okazji. Jeśli potrzebujesz większej elastyczności, sprawdź zdarzenie endRequest w klasie PageRequestManager.
Phil Jenkins,
Niesamowite! Zastąpiłem moje jquery $ (document) .ready twoim pageLoad (bez bloku if) i to rozwiązało mój problem!
Chris,
10
Uwaga: na stronie jest wykonywana tylko jedna funkcja „pageLoad” - ostatnia zdefiniowana. Więc jeśli akcje, które mają być wykonane, znajdują się na różnych kontrolkach - istnieją łatwiejsze sposoby osiągnięcia wymaganego zachowania - takie jak „Sys.Application.add_load”.
Paulius
23

Lub możesz sprawdzić najnowszą funkcjonalność na żywo jQuery za pomocą on()metody.

Jerzy
źródło
To było dla mnie najlepsze rozwiązanie, ponieważ znaczna część moich znaczników jQuery jest umieszczona w kilku kontrolkach użytkownika na stronie.
Kyle B.,
1
czy możesz opublikować przykład z DatePicker?
Perica Zivkovic
Po prostu używałem „on” do łączenia się z rozwijaną listą w panelu, który uruchamia asynchroniczne wyzwalanie po. NIE DZIAŁAŁO, dopóki nie zamieściłem odpowiedzi powyżej autorstwa @Phil Jenkins. Nie jestem pewien, czy robi różnicę, czy jest to post asynchroniczny, czy pełny post z powrotem, ale włączone. Segregator nie zajmował się tym po powrocie poczty.
Casey
22
Sys.Application.add_load(initSomething);
function initSomething()
{
  // will execute on load plus on every UpdatePanel postback
}
Paulius
źródło
14

Począwszy od jQuery 1.7, zalecanym sposobem na to jest użycie składni .on () jQuery .

Upewnij się jednak, że zdarzenie zostało skonfigurowane na obiekcie dokumentu , a nie na samym obiekcie DOM. Na przykład to się zepsuje po ogłoszeniu zwrotnym UpdatePanel :

$(':input').on('change', function() {...});

... ponieważ ': input' zostało przepisane. Zrób to zamiast tego:

$(document).on('change', ':input', function() {...});

Dopóki dokument jest w pobliżu, wszelkie dane wejściowe (w tym te z odświeżeń UpdatePanel) będą wyzwalać procedurę obsługi zmian.

lambinator
źródło
Niesamowite ! (dokument) działał wspaniale, używając następującego .... $ (dokument) .on ('click', '# tagsAdd', function () bez względu na to, ile mam paneli aktualizacji, które dzielą zawartość strony :) Thx
Martin Sansone - MiOEE
9

Użyj następującego kodu

Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(pageLoaded);

function pageLoaded(sender, args) {
    var updatedPanels = args.get_panelsUpdated();
    // check if Main Panel was updated 
    for (idx = 0; idx < updatedPanels.length; idx++) {
        if (updatedPanels[idx].id == "<%=upMain.ID %>") {
            rebindEventsForMainPanel();
            break;
        }
    }
}
shatl
źródło
8

Możesz użyć jQuery i delegowania zdarzeń. Zasadniczo podpinaj zdarzenia do kontenerów, a nie do każdego elementu, i wysyłaj zapytania do event.target i na tej podstawie uruchamiaj skrypt.

Ma wiele zalet, ponieważ redukujesz szum kodu (nie ma potrzeby ponownego wiązania). Jest również łatwiejsze w pamięci przeglądarki (mniej zdarzeń powiązanych w DOM).

Szybki przykład tutaj .

Wtyczka jQuery do łatwego delegowania zdarzeń.

PS Jestem na 99% pewien, że delegacja będzie w rdzeniu jQuery w następnej wersji.

plac Czerwony
źródło
5

Użyj następującego kodu, musisz zweryfikować, czy formant użyje datapicker:

    <script type="text/javascript" language="javascript">

         Sys.WebForms.PageRequestManager.getInstance().add_endRequest(addDataPicker); 
         function addDataPicker(sender, args)
         {
            var fchFacturacion = document.getElementById('<%= txtFechaFacturacion.ClientID %>');
            if (fchFacturacion != null) {
               $(fchFacturacion).datepicker({ onSelect: function () { }, changeMonth: true, changeYear: true, showOn: 'button', buttonImage: '../Imagenes/calendar.gif', buttonImageOnly: true});}
         } 

    </script>

     <asp:UpdatePanel ID="upEjem" runat="server" UpdateMode="Conditional">
       <ContentTemplate>
              <div id="div1" runat="server" visible="false">
                  <input type="text" id="txtFechaFacturacion" 
                      name="txtFechaFacturacion" visible="true"
                      readonly="readonly" runat="server" />
              </div>
       </ContentTemplate>
     </asp:UpdatePanel>
rocke_amiga
źródło
4

         <script type="text/javascript">
             function pageLoad() {

                 if (Sys.WebForms.PageRequestManager.getInstance().get_isInAsyncPostBack()) {


       }

            </script>

        </ContentTemplate>
    </asp:UpdatePanel>

w "if" możesz umieścić kod, który chcesz wykonać za każdym razem, gdy updatepanel wykonuje AsyncPostBack.

civanm
źródło
2

Wiąż swoje wydarzenia za pomocą nowej metody „na żywo” jQuery. Będzie wiązać wydarzenia ze wszystkimi twoimi obecnymi i przyszłymi elementami. Cha Ching! :)

John Strickler
źródło