PrimeFaces的keyup或其他ajax事件延迟

25

我有一个类似于:

<p:inputText...>
    <p:ajax event="keyup" update="somefield" listener="#{someBean.doSomething}"/>
</p:inputText>

但我不想在每次按键时都进行Ajax请求,我希望在用户停止输入半秒钟后再进行请求。

在另一个问题中,我看到了在jQuery中解决这个问题的方法: 如何延迟.keyup()事件处理程序,直到用户停止打字?

我想知道是否可能在PrimeFaces上实现此功能,或者如何调整从jQuery问题中获得的解决方案。
我正在使用PrimeFaces 3.0.M4。
提前感谢您的帮助。

4个回答

25
如果使用Primefaces 5.x,那么在标记中有一个delay属性可以用于此目的。因此,做法如下:
<p:inputText...>
    <p:ajax event="keyup" delay="1000" listener="#{someBean.doSomething}"
        update="somefield" process="@this" />
</p:inputText>

如果不行的话,你可以使用f:ajax来代替p:ajax(是的,它也适用于p:inputText)。从JSF 2.2开始,f:ajax增加了对队列控制的支持。因此代码看起来像这样:

<p:inputText...>
    <f:ajax event="keyup" delay="1000" listener="#{someBean.doSomething}"
        render="somefield" execute="@this" />
</p:inputText>

另请参阅:


f:ajax 支持每个 PrimeFaces 组件拥有的所有事件吗?还是有限制? - Kukeltje
@Kukeltje,不太确定。理论上,p:ajax 是一种更强大的实现方式,但是组件也应该可以与 f:ajax 一起工作。无论如何,在我看来,这个答案是不在这个具体情况下使用 f:ajax 的唯一缺点。 - Aritz
尝试为 p:ajax 添加“delay”属性,但根据文档,该属性应该是存在的。 - Kukeltje
@Kukeltje,你说得对。这是在5.x中添加的。我会更新我的回答;-) - Aritz
1
现在我想要一半的声望;-) - Kukeltje
也许更好的做法是编辑已经被接受的答案,并将其分为两部分...5.0之前和5.0之后。 - Kukeltje

18

为什么不使用PrimeFaces的RemoteCommand组件?

它提供了一个全局的Javascript函数,您可以随时从任何地方调用它。它还允许您调用托管bean方法,并具有用于部分更新的update属性。

<p:inputText id="input" />

<h:form>
    <p:remoteCommand name="sendAjaxical" update="somefield" action="#{someBean.doSomething}"/>
</h:form>

注册事件处理程序,我从你发布的同一答案中借鉴了以下内容:

var delay = (function() {
    var timer = 0;
    return function(callback, ms) {
        clearTimeout (timer);
        timer = setTimeout(callback, ms);
    };
})();


jQuery("#input").keyup(function() {
    delay(function() { sendAjaxical(); }, 2000); //sendAjaxical is the name of remote-command
});

1
这个很好用,我之前不知道remoteCommand。我必须用类似下面的代码替换脚本中的jQuery部分:`function ajaxDelay(){ delay(function() { sendAjaxical(); }, 2000);}`然后像这样调用它 <p:inputText onkeyup="ajaxDelay()">
非常感谢!
- Roteke

1

如果您选择了jquery/javascript解决方案,那么您将无法使用Primefaces Ajax组件。您需要实现自己的javascript函数(带有ajax/xmlHttpRequest支持),并在半秒后触发该函数。

但是还有另一种解决方案,即一个变通方法:您可以使用一个自动完成组件,并使用3个有用的属性:valueChangeListener引用处理valuchangeevent的方法表达式 - 您使用它来代替completeMethod,因为您不需要返回建议),queryDelay发送每个查询到服务器之前等待的延迟时间(以毫秒为单位))和minQueryLength开始查询之前要键入的字符数 - 如果您不想在键入一个字符后立即启动ajax请求)。

我希望您会发现这个解决方案非常有趣...请在此处查看自动完成组件的演示(http://www.primefaces.org/showcase-labs/ui/autocompleteHome.jsf),您可以通过阅读Primefaces User Guide for 3.0.M4来了解更多信息。


这个方法成功地调用了我想要的延迟的bean方法,但它没有更新(我需要更新),当值改变监听器被执行时,也不能提交该值。 但是这个答案帮助我找到了其他的解决方案。 非常感谢。 - Roteke

1

一个快速的解决方法是在p:ajaxonstart中添加延迟。 在您的JavaScript中的某个地方定义以下函数:

function keyupDelay(request, cfg, delay) {
    delay = delay || 2000;// if no delay supplied, two seconds are the default seconds between ajax requests
    setTimeout(function() {
        cfg.onstart = null;
        request.send(cfg)
    }, delay);
    return false;
}

基本上,该函数会在一定的延迟时间后触发ajax请求,同时对于立即执行的请求返回false,并清空该超时请求的onstart,以避免陷入恶性循环。

然后在p:ajax中:

<p:ajax event="keyup" onstart="return keyupDelay(this, cfg)" />

延迟参数在此处是可选的,默认为2秒。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接