【问题标题】:Postback not triggered after javascript on change eventjavascript 更改事件后未触发回发
【发布时间】:2014-10-21 10:59:26
【问题描述】:

在我的 asp.NET 应用程序中,我实现了一个控件来使用服务器端逻辑验证表单输入数据。

这个想法是将控件拖到任何需要它的地方,在后面的代码中设置它,然后表单将被验证。 此验证发生在每个字段的 onchange 事件和表单提交时 - 对服务器端的同步 ajax 调用。

在我将它发布到 IIS 之前,它运行良好。

问题如下:用户正在文本框中写一些东西。然后,将焦点放在该文本框上,单击与正在验证的表单无关的按钮或链接按钮。 发生验证 ajax 调用(触发 jQuery onchange)并且未达到按钮回发。通过调试,我发现问题在于 ajax 调用以某种方式阻止了回发(几乎感觉像是一个同步问题)。

我将问题减少到警报似乎导致与 ajax 调用相同的程度。请查看以下项目:编辑:链接已删除,因为我不能在同一个帖子上发布超过 2 个链接 - 抱歉!

考虑前 2 个文本框和按钮: 1)如果你在第一次写了一些东西,然后单击按钮:onchange 触发,显示警报并且不会发生回发。 2) 如果你在第二个写了一些东西,然后点击按钮:onchange 触发并且回发发生。

有人可以解释为什么会发生这种行为,如果有任何解决方案,即在 javascript 完成运行后触发回发?

我可以想出两种方法来解决我的问题,但我需要知道(在文本框更改事件中)用户单击的控件的 ID。有什么办法得到吗? 这样我就可以:显式触发控件,或者验证它是否不属于表单控件,并且在那一刻不验证输入(这是有道理的)。

提前致谢。


2014 年 10 月 22 日编辑:

情节变厚了。这似乎是一个同步问题。检查this other test application 我删除了警报(这集中了太多注意力,实际上与问题无关,因为我没有在我的项目中使用警报框 - 我正在使用小气球),然后离开了 AJAX 调用。

现在,在服务器端 (WebMethod) 我放置了一个 Thread.Sleep()。如果线程睡眠时间过长,它似乎会错过回发。就我而言,在我的开发环境中,阈值似乎是 80 毫秒。如果 ajax 调用花费的时间少于 ~80 毫秒,则回发完成,如果花费的时间超过 80 毫秒,则会错过回发。您看到过任何想法或类似(已解决)的问题吗?请注意,我的 ajax 调用具有 async: false。


2014 年 10 月 24 日编辑:

终于又看了一遍。我想我可能已经找到了一个可能的解决方案,尽管我不喜欢依靠 setTimeout 在“focusin”(相同的控件)之前处理提交按钮“click”的想法。

我改变了逻辑(仍然实现相同的目标),现在使用不同的事件。 现在我需要区分提交控件何时触发 'focusin' 事件,因为它刚刚获得焦点 (1) 或被点击 (2):

  1. 用户可能只是在切换(验证最后一个具有焦点的字段 - 如果它属于正在验证的表单)
  2. 用户可能已单击(不验证具有焦点的最后一个字段,但验证整个表单然后提交与否)

看看at this new test app,它更接近我的项目。

您能否帮助我找到一种更好的方法来处理/处理同一控件上的 focusin 事件之前的 click 事件,而不需要像 setTimeout 这样不可预测的东西?如果我确实需要依赖 setTimeout,您认为应该将等待设置为多少?在我的机器上 150 毫秒有效,但在其他人身上,可能需要更多时间?诸如某种回调之类的东西是理想的。

再次感谢

【问题讨论】:

  • e.target.id返回元素的id,不知道怎么解决你的问题。
  • 嗨罗希斯。 e.target 给了我事件调用者的 ID,在我的小例子中是 TextBox1 或 TextBox2。这没有帮助。有什么帮助将是导致焦点在文本框上丢失的控件的 ID。假设您在 TextBox1 上写了一些东西,然后单击了 LinkBut​​ton25。什么会帮助我知道,在 Textbox1.change 事件中,点击了“LinkBut​​ton25”并且焦点(如果有效,则操作!)将更改为该控件。
  • 对此,请参阅answerthis
  • 嗨 Rohith,刚刚尝试了 activeElement 方法,但似乎也不起作用。在 onchange 事件期间,activeElement 始终是主体。我做了另一个小项目只是为了测试一些事件,似乎在文本框转换之间,我只能在 focusin 和 focus 事件中有一个实际的(除了正文)activeElement。这无济于事,因为我不想在用户开始输入之前验证输入。 See my other small test project here.
  • 在您的代码中,将OnClientClick="return AjaxCall();" 添加到按钮。现在,单击按钮时,将调用验证。希望这会有所帮助。

标签: javascript jquery asp.net ajax


【解决方案1】:

使用 __doPostBack('','');在你的 javascript 函数结束时

【讨论】:

  • 谢谢,但这似乎不起作用。我在示例项目中的警报之后尝试了它,但仍然没有触发回发。此外,即使它起作用了,它也会在我不想这样做时触发回发……那就是当我只是通过控件填充和制表符并且正在进行验证时。
  • 能否请您发布两个事件的事件函数
  • 你在使用 AutoPostBack="true" 吗?
  • 您好 Thruba,这是很多代码。我发布的示例(请参见上面的链接)包含复制问题的所有内容,包括 ajax 调用(如果您希望取消注释并重现该场景)。
  • 没有。自动回发是假的。
【解决方案2】:

在这种情况下,警报框似乎会停止回发。我发现的明智解决方案是使用似乎不会抑制回发的 jQuery 对话框。问题当然是对话框不会在回发中持续存在,但这可以通过包含“标志”的隐藏字段来解决,以便在回发后显示对话框。

你需要为对话框添加 jquery-ui.js 和一些样式,如果这是一个严肃的应用程序,我建议你下载这两个文件并将它们放在脚本文件夹中,就像你已经使用 jquery min 一样。

<head runat="server">
<title>Postback with dialog</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css">
<script src="scripts/jquery-1.8.2.min.js" type="text/javascript"></script>
<script src="//code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
<script type="text/javascript">

    $(document).ready(function() {

        $("#TextBox1").on('change', function(e) {
            $("#doDisplayDialog").val("yes"); // Add a flag so it shows after postback.
            $('#jqAlert').dialog({
                closeOnEscape: true,
                open: function(event, ui) {
                    $(this).parent().appendTo("form");
                }
            });
        });

        if ($("#doDisplayDialog").val() == "yes") {
            $('#jqAlert').dialog({
                closeOnEscape: true,
                open: function(event, ui) {
                    $(this).parent().appendTo("form");
                }
            });
            $("#doDisplayDialog").val("no"); // Clear the flag so it doesn't display after postback.
        }

    });

</script>
</head>

添加隐藏字段:

<asp:HiddenField ID="doDisplayDialog" runat="server" />

还有一个Div作为对话框:

<div id="jqAlert" title="Alert" style="display: none;">
    <p>Postback will happen!</p>
</div>

代码基于您的可下载测试网站应用程序。

-- 下面不是一个可行的解决方案--

试试这个 - 复制/粘贴替换测试 Web 应用程序中的这些行:

$(document).ready(function() {

  $("#TextBox1").on('change', function() {
    alert('T1 Postback does not fire');
    return true;
    //return AjaxCall();
  });

  $("#TextBox2").on('change', function() {
    alert('T2 Postback does not fire');
    return true;
    //return AjaxCall();
  });

});

我所做的唯一更改是在此处的 jquery 选择器中将单引号替换为双引号

$('#TextBox2')

$("#TextBox2")

编辑:实际上它不起作用,我的测试代码中有一个错误。将对此进行更多研究。

【讨论】:

  • 我想你可能误解了这个问题(也许?)。我希望回发发生。使用您的代码,不会完成回发。
  • 是的,我明白了,我弄乱了我的测试代码并且得到了回发,但没有使用此代码。不要介意当前提出的解决方案,我正在研究这个,这是一个有趣的问题。
  • 我添加了另一个解决方案,希望您能够使用它。关于警报阻止回发,我相信这是设计使然-这是 w3s 中的注释“注意:警报框将焦点从当前窗口移开,并强制浏览器阅读消息。不要过度使用此方法,因为它阻止用户在框关闭之前访问页面的其他部分。”
  • 嗨 Uporabnik003,感谢您的奉献。不幸的是,这不是警报框问题。我用它们来复制主要问题,但我没有在我的项目中使用它们(我正在使用气球/div)。您的解决方案实际上正在我的项目中的其他地方使用,并且是一个很好的解决方案,但在这种情况下没有帮助。我刚刚更新了主要描述,我现在认为这是一个同步问题。请查看新项目并尝试使用 5ms 和 150ms 的 Thread.Sleep。我想你会明白这个问题的。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-22
  • 2013-05-26
  • 2021-08-24
  • 2021-09-30
  • 2014-01-03
  • 1970-01-01
相关资源
最近更新 更多