jQuery $ (document) .ready і UpdatePanels?


475

Я використовую jQuery для підключення деяких ефектів миші на елементи, що знаходяться в UpdatePanel. Події пов'язані в $(document).ready. Наприклад:

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

Звичайно, це працює чудово при першому завантаженні сторінки, але коли UpdatePanel робить часткове оновлення сторінки, воно не запускається, і ефекти миші перестають працювати всередині UpdatePanel.

Який рекомендований підхід для підключення матеріалів у jQuery не лише під час завантаження першої сторінки, але кожного разу, коли UpdatePanel виконує часткове оновлення сторінки? Чи повинен я використовувати життєвий цикл ASP.NET ajax замість $(document).ready?


Спробуйте це, я думаю, це вирішить вашу проблему codeproject.com/Articles/21962/…
Baxterboom

1
Подібно до цього питання: stackoverflow.com/questions/301473 / ...
Per Hornshøj-Schierbeck

Відповіді:


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 під час кожного оновлення. Прочитайте всю документацію, перш ніж використовувати цей підхід, оскільки він може відповідати вашим потребам. Існує багато плагінів jQuery, які нерозумно використовуватимуть рефактори, .delegate()або .on(), тому в цих випадках вам краще повторно підписатися.


1
Будьте точнішими, коли ви даєте пояснення. Я маю на увазі приклад використання набагато краще, ніж пара розкиданих рядків коду. Дивіться пояснення Брайана Маккея. Це прекрасно!
шукач правди

3
@Dan, станом на jQuery 1.7, .delegate()витіснив.on()
Габріеле Петріолі

@ GabyakaG.Petrioli Я розумію, що це було замінено, але оскільки ця відповідь, як видається, вирішує загальну проблему, я хотів досягти максимальної сумісності зі старими версіями jQuery, які ще не були оновлені. Мою відповідь, раніше рекомендовану, .live(...)яка офіційно застаріла в 1.7 і може бути видалена в наступній версії. Я навмисно вибрав, .delegate()оскільки він вже деякий час підтримується в jQuery і, швидше за все, не буде видалений найближчим часом. Однак я уточню свою відповідь, щоб згадати .on()також і тих, хто може її використовувати.
Ден Герберт

12
Краще оголосити і з'єднати prm var всередині $ (document). Вже, оскільки можливо, Sys ще не був оголошений (залежно від того, де знаходиться сценарій).
drake7707

1
@AhmedSamy Більше не рекомендується використовувати jQuery.delegate(). Це було замінено, jQuery.on()яким є кращий API для використання. delegate()це просто обгортка для конкретного використання on(), і можливо, в майбутньому вона може застаріти. Моя попередня згадка про коментар delegate()була написана понад рік тому, коли jQuery 1.7 (який представив on()API) був нещодавно випущений. Оскільки jQuery 1.9 вже вийшов і 2.0 в бета-версії готується до випуску, це гарна ідея уникати використання delegate()будь-якого нового коду.
Дан Герберт

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>

Добре працює для asp: GridView TextBox всередині <EditItemTemplate>
Ден Рендолф

Проблема цього рішення полягає в тому, що, хоча він працює, він вбиває асинхронний пост UpdatePanel назад - робить UpdatePanel знову марним. (зітхання)
MC9000

63

Контроль користувача за допомогою jQuery всередині оновлення

Це не пряма відповідь на питання, але я вирішив скласти це рішення, прочитавши відповіді, які знайшов тут, і думав, що хтось може вважати його корисним.

Я намагався використовувати обмежувач текстових повідомлень jQuery всередині User Control. Це було хитро, тому що User Control працює всередині 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, який я використовую.
Адам Юндерс

У моєму випадку я додавав сценарій за допомогою ScriptManager.RegisterClientScriptBlock, який додає скрипт до того, як буде визначено Sys, тому я в кінцевому підсумку скористався RegisterStartupScript (див. Різницю тут )
Firas Assaad

2
Класна відповідь! це працювало як шарм у моєму веб-додатку asp.net. + для вас
Пранеш Джанартанан

33

Оновіть до jQuery 1.3 та використовуйте:

$(function() {

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

});

Примітка: живі роботи з більшістю подій, але не з усіма. Існує повний список в документації .


Використовуючи живі виправлення проблеми з панелями оновлення. Ніякі обручі не потребували, щоб перестрибнути їх.
Тім Скарборо

А що з тим, що має статися при завантаженні сторінки? Наприклад, столи для смугастих зебр? $ ('TABLE TR: nth-child (непарні)'). AddClass ('alt-рядок');
Адам Юндерс

3
Просто для оновлення, оскільки jQuery 1.7 тепер рекомендується використовувати .on () замість
Джордж

1
Щойно виявив серйозний збій під час використання live()методу в IE7 (jQuery 1.5.1 / VS2010 проект). При використанні live()всередині UpdatePanel в v3.5 ASP.NET регулярні AutoPostbackз <asp:DropDownList />причин 2 часткові постбека на відміну від очікуваного 1. Додаткового постбека виданої браузер відчуває нестачу контенту (перерваний) змушуючи Page.IsPostBackбути false(що вбиває стан всередині моєї кордону контролю). Винуватцем я був метод live (). Я усвідомлюю, що 1-я поштова розсилка, яку потрібно відмінити UpdatePanel за специфікацію, але тільки якщо в черзі є ще одна, якої немає.
timmi4sa

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 () - подія ajax ASP.NET, яка виконується кожного разу при завантаженні сторінки на стороні клієнта.


pageLoad дублює події на кожному ASync поштовому звороті панелі оновлень.
Zo має

17

Моя відповідь?

function pageLoad() {

  $(document).ready(function(){

тощо.

Працювало як шарм, де ряд інших рішень невдало провалився.


Ідеально підходить для зміни розміру текстових областей у моєму перегляді списку в моєму UpdatePanel в моєму UserControl відповідно до кількості тексту.
Ресурс

Я намагався зробити так, щоб функції dom jquery працювали коректно в режимі післягарантії з панелями оновлення, це рішення спрацювало, і мені не довелося дублювати виклики функцій у двох сценаріях. Це забезпечило доступність функцій jquery та слухача. Примітка. Я розміщую всю свою скрипту та бібліотеку jquery прямо перед тегом FORM [end] внизу сторінки. Дякую!!!
moto_geek

7

Я б застосував один із наступних підходів:

  1. Інкапсулюйте прив'язку події до функції та запускайте її щоразу, коли ви оновлюєте сторінку. Ви завжди можете містити прив'язку події до конкретних елементів, щоб не прив'язувати події кілька разів до одних і тих же елементів.

  2. Скористайтеся плагіном 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

функціональну сторінкуLoad () дуже небезпечно використовувати у цій ситуації. Можливо, події стали проводними кілька разів. Я б також тримався подалі від .live (), оскільки він прикріплюється до елемента документа і повинен переходити всю сторінку (повільно і хитро).

Найкраще рішення, яке я бачив до цього часу, - це використовувати функцію jQuery .delegate () на обгортці поза панеллю оновлення та використовувати пузир. Крім того, ви завжди можете підключити обробників за допомогою бібліотеки Ajax Microsoft, яка була розроблена для роботи з UpdatePanels.


6

Якщо $(document).ready(function (){...})не працює після публікації сторінки назад, тоді використовуйте функцію JavaScript сторінкуЗавантажте в Asp.page наступним чином:

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

Так, перевірте isPartialLoad , а також: stackoverflow.com/questions/301473 / ...
Steve Greene

4

У мене була подібна проблема, і я знайшов спосіб, який найкраще працював, - покластися на Bubbling Event та делегацію подій для його вирішення. Приємна річ у делегуванні подій - це те, що після налаштування вам не доведеться відновлювати події після оновлення AJAX.

Що я роблю в своєму коді - це встановити делегат на батьківський елемент панелі оновлення. Цей батьківський елемент не замінюється під час оновлення, тому зв’язування події не впливає.

Існує ряд хороших статей та плагінів для обробки делегування подій у jQuery, і ця функція, ймовірно, буде включена у версію 1.3. Стаття / плагін, який я використовую для посилання:

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

Як тільки ви зрозумієте, що відбувається, я думаю, що ви знайдете це набагато більш елегантне рішення, яке є більш надійним, ніж пам’ятати про повторне зв’язування подій після кожного оновлення. Це також має додаткову перевагу в тому, що ви дасте одну подію, яку потрібно скасувати при завантаженні сторінки.


4

FWIW, у мене виникли подібні проблеми з мотобулами. Повторне приєднання моїх подій було правильним кроком, але це потрібно було зробити в кінці запиту. Напр

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

Просто щось, про що слід пам’ятати, якщо beginRequest змушує вас отримати нульові посилання винятків JS.

Ура



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

Функція pageLoad ідеально підходить для цього випадку, оскільки вона працює під час початкового завантаження сторінки та кожного оновлення асинхронізації після оновлення панелі оновлення. Мені просто довелося додати метод відключення, щоб змусити jquery працювати над оновленнями панелей оновлення.

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

це буде добре працювати ...


Старий пост, але той, який мені допоміг. Одне, що я хотів би додати до цього: розташування коду add_endRequest має бути всередині UpdatePanel, оскільки Sys.WebForms.PageRequestManager доступний лише в цей момент. Однак фактична функція не повинна бути в цьому місці. Отже, у моєму випадку у мене є файл script.js, який містить код, який я хочу пов'язати, який міститься у функції. У цьому файлі script.js у мене є виклик документу, який викликає вищевказану функцію. Потім у своєму UpdatePanel я маю код add_endRequest, який також викликає вищевказану функцію.
Кіран Рамасвамі

1

Використовуйте сценарій нижче та відповідно змініть тіло сценарію.

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

0

У відповідь на відповідь Брайана Маккея:

Я вставляю JavaScript на свою сторінку через ScriptManager замість того, щоб вводити його безпосередньо в HTML UserControl. У моєму випадку мені потрібно прокрутити форму, яка стане видимою після завершення та повернення 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
        });
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.