Как повторно выполнить функцию javascript после формы reRender?

Мне нужно повторно выполнить javascript сразу после повторной визуализации формы. Просто вставка javascript после содержимого XHTML не поможет, поскольку это частичный запрос. Кроме того, я не могу использовать «onComplete», поскольку commandButton, из которого я повторно отображаю форму, находится в компоненте JSF, используемом в нескольких местах. Мне нужно получить исправление на месте.

Там в любом случае? Мне было интересно, поможет ли f: ajax в этом случае.

Пожалуйста, дайте мне знать, если кто-нибудь знает об этом.


person A.G.    schedule 26.10.2012    source источник


Ответы (3)


Самый простой способ — просто поместить вызов функции JS в сам обновляемый компонент.

<h:form>
    ...
    <h:commandButton value="submit"><f:ajax render="@form" /></h:commandButton>
    <h:outputScript>someFunction();</h:outputScript>
</h:form>

Таким образом, он выполняется при загрузке страницы, а также при обновлении формы с помощью ajax.

Что касается самого <f:ajax>, вы также можете использовать его атрибут onevent.

<f:ajax ... onevent="handleAjax" />

с участием

function handleAjax(data) {
    var status = data.status;

    switch(status) {
        case "begin":
            // This is invoked right before ajax request is sent.
            break;

        case "complete":
            // This is invoked right after ajax response is returned.
            break;

        case "success":
            // This is invoked right after successful processing of ajax response and update of HTML DOM.
            someFunction();
            break;
    }
}

Вы можете добавить глобальный хук с помощью jsf.ajax.addOnEvent(), чтобы вам не нужно было указывать его в каждом отдельном атрибуте onevent <f:ajax>, если функциональное требование применяется к каждому запросу ajax.

jsf.ajax.addOnEvent(handleAjax);

В качестве альтернативы можно использовать библиотеку утилит OmniFaces JSF, которая предлагает <h:onloadScript> именно для этой цели. Вы можете разместить его в голове так, как хотите.

<h:onloadScript>someFunction();</h:onloadScript>

Это автоматически повторно выполняется для каждого отдельного запроса ajax в представлении, поэтому вам не нужно копировать его в несколько отдельных мест в представлении, которое может быть обновлено с помощью ajax, или повторять его родительский идентификатор в каждом <f:ajax render>.

person BalusC    schedule 26.10.2012
comment
Спасибо BalusC! Это кажется простым и прямым путем. Это сработало. - person A.G.; 26.10.2012
comment
Простое добавление h:outputScript помогло мне удалить все действия oncomplete :) - person A.G.; 26.10.2012
comment
Очень элегантное решение @BalusC - person Padmarag; 28.12.2012
comment
Когда я помещаю функцию JS в h: outputScript, она выполняется, но выдает ошибку из других используемых ею сценариев, например. $(...).datetimepicker не является функцией - person Alex Po; 26.08.2016

Первый ответ BalusC является наиболее подходящим, если вы хотите выполнять сложные операции с JQuery/JS и не особо заботитесь о это

Для более сложного JS, если вы решите использовать глобальный обработчик событий и, например, вы используете JS для bind функций для элементов, эти функции будут повторно привязаны (следовательно, выполняться дважды), поэтому вам нужен какой-то способ определить, что нужно подлежать повторному исполнению.

Что я наконец сделал, так это получил идентификатор из обратного вызова события и выполнил только соответствующий JS/JQuery:

jsf.ajax.addOnEvent(ajaxCompleteProcess);


function ajaxCompleteProcess(data) {
    if (data.status && data.status === 'success') {
        var children1 = data.responseXML.children;
        for (i = 0; i < children1.length; i += 1) {
            var children2 = children1[i].children;
            for (j = 0; j < children2.length; j += 1) {
                var children3 = children2[j].children;
                for (y = 0; y < children3.length; y += 1) {
                    if (children3[y].id.indexOf('javax.faces.ViewState') != -1)
                        continue;
                    elementProcess(('#' + children3[y].id.replace(/\:/g, '\\:')));
                }
            }
        }
    }
}

Примечание: эти уродливые циклы for, вероятно, не нужны (можно использовать clildren[0]), но я пока не нашел времени проверить спецификацию.

person Ioannis Deligiannis    schedule 15.12.2013
comment
Было бы неплохо узнать причину отрицательного голосования. Это работает, и единственный фрагмент кода, который вам нужен, — это код для всего вашего приложения. Так что либо пост плохой, либо есть плохой по какой-то причине. - Спасибо - person Ioannis Deligiannis; 02.08.2014

Вы можете добавить jQuery в свое приложение и сделать что-то вроде:

$(#yourComponentId).load(function(){
   //execute javascript.
});

Вы можете посмотреть здесь http://api.jquery.com/load/

LE: это происходит

$(document).ready(function(){
}

офк.

person tartak    schedule 26.10.2012
comment
Это не сработает. Это выполняется только при загрузке/готовности DOM и не выполняется повторно при запросах ajax. - person BalusC; 26.10.2012
comment
В событии готовности документа мы перехватываем функцию, которая будет выполняться каждый раз, когда компонент с id=yourComponentId запускает событие загрузки. Возможно, было бы лучше выполнять функцию при «готовом» событии компонента, но в любом случае, я думаю, что это сработает. Что вы думаете о BalusC? - person tartak; 26.10.2012
comment
Событие готовности DOM не вызывается при манипуляциях с DOM в результате ответов ajax. - person BalusC; 26.10.2012