通过Ajax更新JSF组件后,JavaScript/jQuery事件侦听器不起作用 [英] JavaScript/jQuery event listeners do not work after JSF component is updated via Ajax

查看:106
本文介绍了通过Ajax更新JSF组件后,JavaScript/jQuery事件侦听器不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在<p:dataTable>过滤器(其ID为id)上执行以下jQuery函数,该过滤器允许用户在过滤器组件中仅输入数字.

I'm executing the following jQuery function on <p:dataTable> filter (whose id is id) that allows users to enter only digits in the filter component.

$(document).ready(function() {
    $("#form\\:dataTable\\:id\\:filter").keydown(function(event) {
        //Allow: tab, escape, and enter
        if(event.keyCode===9||event.keyCode===27||event.keyCode===13||
            //Allow: Ctrl+A, Ctrl+C
            (event.keyCode===65&&event.ctrlKey===true)||(event.keyCode===67&&event.ctrlKey===true)||
            //Allow: home, end, left, right
            (event.keyCode>=35&&event.keyCode<=39)){
            //let it happen, don't do anything
            event.preventCapture();
            return;
        }//backspace, delete
        else if(event.keyCode===46||event.keyCode===8)
        {
            return;
        }
        else{//Ensure that it is a number and stop the keypress
            if (event.shiftKey||(event.keyCode<48||event.keyCode>57)&&(event.keyCode< 96||event.keyCode>105)){
                //event.preventDefault();
                event.preventCapture();
            }
        }
    });
});

此功能位于context/resources/default/js/digit_only_textfield.js下.因此,它可以在XHTML页面上使用,

This function is placed under context/resources/default/js/digit_only_textfield.js. Therefore, it can be used on XHTML pages like,

<h:outputScript library="default" name="js/digit_only_textfield.js"/>

XHTML页面如下所示.

The XHTML page looks like the following.

<h:outputScript library="default" name="js/digit_only_textfield.js"/>

<h:form id="form" prependId="true">

    <!--PrimeFaces extension <pe:blockUI>-->         

    <p:remoteCommand name="updateTable" update="dataTable"/>

    <p:panel id="panel">
        <h:panelGrid id="panelGrid" columns="3" cellpadding="5">

            <!--Some UIInput components-->

            <p:commandButton id="btnSubmit" 
                             update="panel" 
                             onstart="PF('blockUIWidget').block();" 
                             oncomplete="if(!args.validationFailed) {updateTable();}PF('blockUIWidget').unblock();" 
                             actionListener="#{bean.insert}" 
                             value="Save"/>
        </h:panelGrid>
    </p:panel>

    <p:dataTable id="dataTable" 
                 var="row" 
                 value="#{bean}"
                 filterEvent="keydown"

                 ...
                 ...  >

                 ...
                 ...
    <p:dataTable>
<h:form>

此jQuery可用于ID为is的过滤器,但通过按给定的<p:commandButton>更新此<p:dataTable>时,它将停止运行.

This jQuery works fine for the filter whose id is is but when this <p:dataTable> is updated by pressing the given <p:commandButton>, it stops functioning.

在AJAX更新<p:dataTable>之后如何使此功能起作用?

How to make this function work after <p:dataTable> is updated by AJAX?

引入了新的问题域:

问题以及对PrimeFaces社区的相应答复论坛仍然不会导致以下问题域的解决方法/解决方案.

This question and corresponding replies on the PrimeFaces Community Forum still do not lead to a workaround/solution to the following problem domain.

如果按下了错误的键(即,非数字键,除了退格键,请删除 等),然后不必要地更新数据表,这会导致某些 要在完全完整的数据库上触发代价高昂的查询 ..

if a wrong key is hit (i.e a non-digit key, except backspace, delete etc) then, the data table is updated unnecessarily that causes some costly queries to be fired upon the database which is completely unnecessary and the data table must be prevented from being updated.

推荐答案

流程如下:

  • 浏览器检索HTML输出.
  • 浏览器基于HTML标记填充HTML DOM树.
  • 完成后,浏览器将触发HTML DOM ready事件.
  • jQuery的$(document).ready()函数处理程序全部被调用.
  • 您可以通过ID在DOM中找到元素,并将keydown侦听器附加到该元素.
  • 在用户交互期间,将触发ajax请求,并使用ajax响应传递的新HTML元素更新HTML DOM树.
  • 在其他元素中,具有keydown侦听器的元素正是从HTML DOM树中删除的,并被替换为没有任何keydown侦听器的新元素.在ajax请求期间不会触发文档ready事件.您准备好的处理程序永远不会被调用. keydown侦听器永远不会重新连接.对于最终用户,它实际上确实似乎停止运行".
  • Browser retrieves HTML output.
  • Browser populates HTML DOM tree based on HTML markup.
  • When finished, browser triggers HTML DOM ready event.
  • jQuery's $(document).ready() function handlers are all invoked.
  • Yours finds an element in DOM by ID and attaches a keydown listener to it.
  • During user interaction, an ajax request is fired and the HTML DOM tree is updated with new HTML elements delivered by the ajax response.
  • Among others, exactly that element having the keydown listener is removed from HTML DOM tree and replaced by a fresh new element without any keydown listener. The document ready event is not fired during ajax requests. Your ready handler is never re-invoked. The keydown listener is never re-attached. To the enduser, it then indeed seemingly "stops functioning".

这种特殊情况上的解决方案现在应该很明显:在完成ajax调用后,显式重新附加keydown侦听器.最直接的方法是提取将keydown侦听器附加到可重用函数中的工作,然后按以下步骤触发它:

The solution on this particular case should now be obvious: explicitly re-attach the keydown listener on complete of ajax call. Most straightforward would be to extract the job of attaching the keydown listener into a reusable function and fire it as follows:

function applyKeydownOnTableFilter() { 
    // ...
}

$(document).ready(applyKeydownOnTableFilter);

这样您就可以执行以下操作:

So that you can just do a:

<p:commandButton ... oncomplete="applyKeydownOnTableFilter()" />

但是,对于每个单个的ajax命令/侦听器重复此操作很繁琐,而且对维护也不是很友好.更好的方法是采用不同的方法:改用jQuery的 $.on() .替换

But this is quite tedious to repeat for every single ajax command/listener and not very maintenance friendly. Better is to approach it differently: use jQuery's $.on() instead. Replace

$(document).ready(function() {
    $("#form\\:dataTable\\:id\\:filter").keydown(function(event) {
        // ...
    });
});

作者

$(document).on("keydown", "#form\\:dataTable\\:id\\:filter", function(event) {
    // ...
});

这样,keydown侦听器实际上并未附加到感兴趣的元素上.相反,借助JavaScript的事件冒泡功能,keydown事件最终将到达$(document)—它在JSF ajax请求期间始终存在并且通常不会更改.一旦到达,将触发$(document).on(),它将确定事件的来源并检查它是否与给定的选择器匹配,如果匹配,则调用该函数.所有这些都无需将keydown侦听器附加到物理元素,因此对于在HTML DOM树中是否删除/替换该元素不敏感.

This way the keydown listener isn't actually attached to the element of interest. Instead, thanks to the event bubbling feature of JavaScript, the keydown event will ultimately reach the $(document) — which is always present and usually not changed during JSF ajax requests. Once reached, the $(document).on() is triggered, which will then determine the source of the event and check it if matches the given selector and if so, then invoke the function. This all without the need to attach the keydown listener to the physical element and thus not sensitive to whether the element is removed/replaced in the HTML DOM tree.

顺便说一句,您还看到HTML DOM树和JSF组件树之间有多少相似之处吗?

By the way, do you also see how much similarities there are between HTML DOM tree and JSF component tree?

这篇关于通过Ajax更新JSF组件后,JavaScript/jQuery事件侦听器不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆