【问题标题】:How to re-execute javascript function after form reRender?表单重新渲染后如何重新执行javascript函数?
【发布时间】:2012-10-16 09:02:46
【问题描述】:

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

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

如果有人知道,请告诉我。

【问题讨论】:

    标签: javascript jsf rerender


    【解决方案1】:

    最简单的方法就是将JS函数调用放在待更新组件本身中。

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

    这样它会在页面加载时执行,如果表单被 ajax 更新,也会执行。

    至于&lt;f:ajax&gt; 本身,你也可以使用它的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() 添加一个全局挂钩,这样如果功能要求适用于每个ajax 请求,您就不需要在&lt;f:ajax&gt; 的每个onevent 属性中指定它。

    jsf.ajax.addOnEvent(handleAjax);
    

    另一种方法是使用OmniFaces JSF utility library,它提供&lt;h:onloadScript&gt; 正是为此目的。你可以把它放在你想要的头上。

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

    这会在视图上的每个 ajax 请求上自动重新执行,因此您无需将其复制到视图中可以进行 ajax 更新的多个单独位置,或者在每个 @ 中重复其父 ID 987654334@.

    【讨论】:

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

    如果你想用 JQuery/JS 做复杂的操作并且不是特别关心this

    ,BalusC 第一个答案是最合适的

    对于更复杂的 JS,如果你决定使用全局事件处理程序,例如你使用 JS 到 bind 函数到元素,这些函数将被重新绑定(因此执行两次),所以你需要一些方法来确定需要重新执行的内容。

    我最后做的是从事件回调中获取 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]),但我还没有时间检查规范。

    【讨论】:

    • 很高兴知道投反对票的原因。这确实有效,您唯一需要的代码就是整个应用程序的代码。因此,它要么是一个糟糕的帖子,要么是由于某种原因而变得糟糕。 - 谢谢
    【解决方案3】:

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

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

    你可以看这里http://api.jquery.com/load/

    LE:正在开启

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

    ofc.

    【讨论】:

    • 这行不通。这仅在 DOM 加载/就绪时执行,并且不会在 ajax 请求上重新执行。
    • 在 document-ready 事件中,我们挂钩函数,该函数将在每次 id=yourComponentId 的组件触发 'load' 事件时执行。也许在组件的“就绪”事件中执行该函数会更好,但无论如何,我认为这会起作用。你觉得 BalusC 怎么样?
    • 由于 ajax 响应,DOM 操作不会调用 DOM 就绪事件。
    猜你喜欢
    • 2013-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-31
    • 1970-01-01
    • 2021-12-27
    相关资源
    最近更新 更多