单击 p:commandButton 时,不会调用 p:inputText 上的 p:ajax blur 事件

p:ajax blur event on p:inputText is not invoked when p:commandButton is clicked

提问人:Venu 提问时间:2/11/2020 最后编辑:KukeltjeVenu 更新时间:4/6/2023 访问量:726

问:

我想在单击命令按钮时通过ajax调用将数据传递到后备bean。 我有一个包含几个输入文本字段的表单,其中每个字段都有ajax模糊事件。 除了在流动的场景中,每件事在快乐的流动中都工作正常。

当我直接单击提交时,Ajax 模糊事件正在调用,这应该在提交单击之前发生,因此我应该再次单击提交按钮以调用 ajax 调用来保存我的表单。

这是代码。

输入文本字段:

<p:inputText id="txt_name"
    value="#{partnerVO.partnerName}"
    required="true" maxlength="30"
    rendered="#{!partnerVO.isReadOnly}">
    <p:keyFilter regEx="/[A-Za-z0-9@.,&amp;- ]/i"
        for="txt_name" preventPaste="false" />
    <p:ajax update="txt_name" event="blur" />
</p:inputText>

<p:inputText id="txt_assigned"
    value="#{partnerVO.assignedName}"
    required="true" maxlength="30"
    rendered="#{!partnerVO.isReadOnly}">
    <p:keyFilter regEx="/[A-Za-z0-9@.,&amp;- ]/i"
        for="txt_assigned" preventPaste="false" />
    <p:ajax update="txt_assigned" event="blur" />
</p:inputText>

命令按钮:

<p:commandButton id="btn_save"
    title="Save"
    value="#{lbl['tpdetails.remove.additional.address']}"
    update="@form" process="@this"
    action="#{partnerDetailsController.save}">
</p:commandButton>

我正在使用 JSF 2.2

请提供一些建议来克服这种奇怪的行为。

注意:此处省略了表单相关代码。

Ajax JSF primefaces XHTML

评论

0赞 Kukeltje 2/11/2020
1:是JSF还是PrimeFaces ajax事件?2:这是 JSF 2.2 特有的功能,还是只使用 JSF 2.2?3:这里的xhtml具体是什么?3:尝试使用带有 ?4:遗漏并不总是好的。确保它始终是一个最小的可重现示例,以便其他人更容易尝试重现。5:尝试过使用commandLink吗?这行得通吗?有效地查看问题是否更通用。f:inputTextf:ajax
0赞 Holger 2/12/2020
@Venu 是的,这就是行为。如果有一个带有“blur”事件的 ajax 调用,并且单击 commandButton 首先触发 blur 事件,则唯一的 ajax 调用将是 blur 调用。commandButton 的 ajax 调用是“forgotton?
0赞 Venu 2/12/2020
@Holger是的。commandButton 的 ajax 调用被遗忘了。有没有办法在模糊事件ajax调用后调用ajax命令按钮,而无需第二次单击按钮?
0赞 Holger 2/12/2020
我没有找到。我删除了模糊的ajax调用。
0赞 Holger 2/12/2020
或。。。如果您通过 Button 的 onclick 来保护 JavaScript 中的状态,并在 Blur AJAX 调用的 oncomplete 中查看此状态,则可以发出对按钮的单击或调用 remoteCommand

答:

1赞 gogognome 4/6/2023 #1

我们使用 ICEFaces 4.3 并且遇到了同样的问题(带有嵌套标签,该标签在 blur 上提交值)和 .这是我在记录点击事件和 jsf 事件后发现的。ace:textEntryace:ajaxace:pushButton

  1. 单击字段以使其成为焦点。ace:textEntry
  2. 键入一些字符以更改其内容。
  3. 单击 .ace:pushButton
  4. 焦点在 上丢失,导致由于标记而向服务器发送请求。ace:textEntryace:ajax
  5. 单击事件在收到请求的响应之前触发。单击事件不会触发提交表单的新请求。
  6. 收到请求的响应(从 4 开始)。

这里有一个争用条件:如果在生成点击事件之前收到请求的响应,则点击将导致提交表单的请求。

您可以通过按下鼠标按钮轻松测试这一点,并且仅在收到请求的响应(从 4 开始)后才释放它。为该事件生成单击事件。mouseup

我通过使用 Javascript 来检测 ajax 请求期间是否发生点击事件,从而为此问题创建了一个解决方法。仅当该 ajax 请求不是单击的结果时,请等待 ajax 请求结束,然后再次调度 click 事件:

/** Indicates whether an ajax request is currently in progress. */
let ajaxRequestInProgress = false;

/** The source of the current ajax request. */
let currentAjaxRequestSource = null;

/** The event that must be delayed. */
let delayedEvent = null;

/** The event that has been redispatched after a delay. */
let redispatchedEvent = null;

function requestInProgressTracker(data) {
    const oldValue = ajaxRequestInProgress
    if (data.type === 'event' && data.status === 'begin') {
        ajaxRequestInProgress = true;
    } else if (data.type === 'event' && data.status === 'success') {
        ajaxRequestInProgress = false;
    } else if (data.type === 'error') {
        ajaxRequestInProgress = false;
    }

    if (oldValue !== ajaxRequestInProgress) {
        if (ajaxRequestInProgress) {
            console.log("------ Start of request");
            currentAjaxRequestSource = data.source;
        } else {
            console.log("------ End of request");
            currentAjaxRequestSource = null;
        }

        if (!ajaxRequestInProgress && delayedEvent) {
            setTimeout(() => {
                redispatchedEvent = delayedEvent;
                delayedEvent = null;
                console.log("------ Dispatch event again for", redispatchedEvent.target);
                redispatchedEvent.target.dispatchEvent(redispatchedEvent);
            }, 10); // Small delay to ensure this method is called after the request has completely finished.
        }
    }
}

function delayEventUntilAfterRequest(e) {
    if (!ajaxRequestInProgress) {
        return;
    }

    if (e === redispatchedEvent) {
        console.log("------ Prevent delaying and dispatching the event again for", e.target);
        return;
    }

    if (delayedEvent) {
        console.log("------ DELAY NEW EVENT WHILE OLD EVENT HAS NOT BEEN DISPATCHED AGAIN.");
    }

    if (currentAjaxRequestSource && currentAjaxRequestSource.contains(e.target)) {
        console.log("------ No need to delay this event, because the current request was triggered by the event for", e.target);
       return;
    }

    delayedEvent = e;
    console.log("------- Event occurred during request", e);
}

document.addEventListener("click", delayEventUntilAfterRequest);

jsf.ajax.addOnEvent(requestInProgressTracker);
jsf.ajax.addOnError(requestInProgressTracker);