表单reRender后如何重新执行javascript函数?

IT技术 javascript jsf rerender
2021-04-07 23:12:19

我需要在重新渲染表单后重新执行 javascript。简单地说,在 XHTML 内容之后放入 javascript 无济于事,因为它是部分请求。此外,我不能使用“onComplete”,因为我从中重新呈现表单的 commandButton 位于在多个地方使用的 JSF 组件中。我需要在本地进行修复。

有什么办法吗?我想知道 f:ajax 在这种情况下是否会有所帮助。

请让我知道,如果有人对此有所了解。

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

如果功能要求适用于每个 ajax 请求,您可以添加一个全局钩子,jsf.ajax.addOnEvent()这样您就不需要在每个onevent属性中指定它<f:ajax>

jsf.ajax.addOnEvent(handleAjax);

另一种方法是使用OmniFaces JSF 实用程序库,它<h:onloadScript>正是为此目的而提供的你可以把它放在你想要的头上。

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

这会在视图上的每个 ajax 请求上自动重新执行,这样您就不需要将它复制到视图中可以进行 ajax 更新的多个单独位置,或者在每个<f:ajax render>.

非常优雅的解决方案@BalusC
2021-05-25 23:12:19
只需输入 h:outputScript 就可以帮助我删除所有未完成的操作:)
2021-06-13 23:12:19
感谢 BalusC!这似乎是简单而直接的方式。有效。
2021-06-18 23:12:19
当我将 JS 函数放入 h:outputScript 时,它会被执行,但它会从它使用的其他脚本中抛出错误,例如 $(...).datetimepicker 不是函数
2021-06-18 23:12:19

如果你想用 JQuery/JS复杂的操作并且不是特别关心这个, BalusC first answer 是最合适的

对于更复杂的 JS,如果您决定使用全局事件处理程序,例如您使用 JSbind函数到元素,这些函数将被重新绑定(因此执行两次),因此您需要某种方法来确定需要什么被重新执行。

我最终做的是从事件回调中获取 id 并仅执行相关的 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]),但我还没有找到时间检查规范。

很高兴知道否决票的原因。这确实有效,并且您需要的唯一代码是整个应用程序的代码。所以,它要么是一个糟糕的帖子,要么是出于某种原因而糟糕。- 谢谢
2021-06-07 23:12:19

您可以将 jQuery 添加到您的应用程序并执行以下操作:

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

您可以在这里查看http://api.jquery.com/load/

LE:那是在

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

ofc.

这行不通。这仅在 DOM 加载/就绪时执行,并且不会在 ajax 请求上重新执行。
2021-05-27 23:12:19
作为 ajax 响应的结果,不会在 DOM 操作上调用 DOM 就绪事件。
2021-06-13 23:12:19
在 document-ready 事件中,我们挂接函数,该函数将在每次 id=yourComponentId 的组件触发 'load' 事件时执行。也许最好在组件的“就绪”事件中执行该函数,但无论如何,我认为这会起作用。你觉得 BalusC 怎么样?
2021-06-14 23:12:19