0

In my asp.NET application I have implemented a control to validate forms input data using server side logic.

The idea is to drag the control to wherever it's needed, set it up in the code behind and the form will be validated. This validation occurs on the onchange event of each field and on form submission - synchronous ajax call to the server side.

This was working fine until I published it to IIS.

The problem is the following: the user is writing something in a textbox. Then, with the focus on that textbox, clicks on a button or linkbutton, not related to the form being validated. The validation ajax call occurs (jQuery onchange fires) and the button postback is not reached. Through debugging I found the problem to be the ajax call is somehow preventing the postback to fire (almost feels like a synchronism problem).

I reduced the problem to the point that an alert seems to be causing the same thing as the ajax call. Please have a look at the following project: EDIT: Link removed because I can't post more than 2 links on the same post - sorry!

Consider the first 2 textboxes and the button: 1) If you write something on the first, then click the button: the onchange fires, an alert is shown and the postback does not occurr. 2) If you write something on the second, then click the button: the onchange fires and the postback occurrs.

Can someone please explain why this behavior happens and if there's any solution to this, ie, make the postback fire after the javascript finishes running?

I can think of 2 ways to solve my problem but I need to know (inside the textbox change event) the ID of the control clicked by the user. Any way of getting it? That way I could: trigger the control explicitly OR verifiy if it doesn't belong to the form controls and don't event validate the input in that moment (that would make sense).

Thanks in advance.


EDITED 22-10-2014:

The plot thickens. This seems to be a synchronism problem. Check this other test application where I removed the alerts (this concentrated too much attention and is not actually related to the issue as I'm not using alert boxes in my project - I'm using little balloons) and just left the AJAX call.

Now, on the server side (WebMethod) I put a Thread.Sleep(). If the thread sleeps for too long, it seems to miss the postback. In my case, on my development environment, the threshold seems to be 80ms. If the ajax call takes less than ~80ms, then the postback is done, if it takes more than that, it misses the postback. Any ideas or similar (resolved) issues you have seen? Note that my ajax call has async: false.


EDITED 24-10-2014:

Finally had another look into this. I think I may have come to a possible solution, although I don't like the idea of relying on a setTimeout to handle the submit button 'click' before the 'focusin' (same control).

I changed the logic (still achieving the same goal) and now use different events. Now I need to distinguish when the submit control fires the 'focusin' event because it just gained focus (1) or it was clicked (2):

  1. The user could just be tabbing (validates the last field that had focus - if it belongs to the form being validated)
  2. The user could have clicked (does not validate the last field that had the focus, but the whole form and then submits or not)

Have a look at this new test app which is closer to what I have in my project.

Can you help me finding a better way to handle/process the click event before the focusin event on the same control without something unpredictable like a setTimeout? If I do need to rely on the setTimeout, how much do you think the wait should be set to? On my machine 150ms works, but on another persons, it may require more time? Something like some sort of callback would be ideal.

Thanks again

ca2s7l
  • 273
  • 1
  • 5
  • 12
  • `e.target.id` return the id of the element, but I don't know how can this solve your issue. – Rohith Oct 21 '14 at 13:21
  • Hi Rohith. e.target gives me the ID of the caller of the event and that is TextBox1 or TextBox2 in my small example. That does not help. What would help would be the ID of the control that caused the focus to be lost on the textboxes. Let's say you were writing something on TextBox1, then clicked on LinkButton25. What would help me would be to know, in Textbox1.change event, that 'LinkButton25' was clicked and the focus (action if it worked!) will be changed to that control. – ca2s7l Oct 21 '14 at 13:45
  • For that, see this [answer](http://stackoverflow.com/a/497108/1374307) and [this](http://stackoverflow.com/a/11278006/1374307) – Rohith Oct 21 '14 at 13:48
  • Hi Rohith, just tried the activeElement approach and that doesn't seem to work either. During the onchange event the activeElement is always the body. I made another small project just to test some events and it seems that, between textbox transitions, I can only have an actual (besides body) activeElement in the focusin and focus event. That does not help the case as I don't want to validate the inputs before the user starts typing. [See my other small test project here](https://db.tt/ky8JeZN0). – ca2s7l Oct 21 '14 at 20:43
  • In your code, add `OnClientClick="return AjaxCall();"` to the button. Now, on button click, the validation is called. Hope this helps. – Rohith Oct 22 '14 at 05:53
  • Hi Rohith, I already have that on submit: 'This validation occurs on the onchange event of each field and on form submission'. Besides the submit, I need to have the validation on focusout/change. I've edited the description, this seems to be a synchronism problem. – ca2s7l Oct 22 '14 at 13:39

2 Answers2

0

Use __doPostBack('',''); at end of your javascript function

ascii
  • 64
  • 6
  • Thanks, but that doesn't seem to work. I tried it after the alert in my example project and still the postback was not fired. Besides, even if it worked, it would trigger the postback when I didn't want to... and that is when I'm simply filling and tabbing through controls and the validation is occurring. – ca2s7l Oct 21 '14 at 11:11
  • can you please post your event function for both events – ascii Oct 21 '14 at 11:13
  • are you using AutoPostBack="true" ? – ascii Oct 21 '14 at 11:18
  • Hi Thruba, that's lots of code. The example I posted (see link above) has everything to replicate the problem, including an ajax call (if you wish to uncomment and reproduce the scenario). – ca2s7l Oct 21 '14 at 11:19
  • No. Autopostback is false. – ca2s7l Oct 21 '14 at 11:19
  • I'd rather not have autopostback set to true, but I tried it and it didn't work. Same result. – ca2s7l Oct 21 '14 at 11:23
  • Remove Return true from your AJAX's success function – ascii Oct 21 '14 at 12:23
  • Already tried and just did it again. Now my textbox1 onchange event only has the alert and the textbox2 onchange event has no code. Same result: when the user writes something on textbox1 and clicks the button, the postback is not fired. – ca2s7l Oct 21 '14 at 12:49
  • Is there any way of knowing which page control was clicked inside the onchange event? If I had that, my problem would be solved. – ca2s7l Oct 21 '14 at 12:54
0

It does appear that an alert box stops postback in this situation. The sensible solution I found was to use a jQuery dialog which doesn't seem to suppress a postback. Problem is of course the dialog doesn't persist itself through the postback but this is solved by a hidden field containing a 'flag' to display the dialog after postback or not.

You will need to add jquery-ui.js and some style for the dialog, if this is a serious application I suggest you download both files and put them in scripts folder as you already have with the 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>

Add a hidden field:

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

And a Div to be the dialog box:

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

Code is based on your downloadable test website application.

-- not a working solution below --

Try this - copy/paste replace these lines in your test web application:

$(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();
  });

});

The only change I did was replace single quotes with double quotes in jquery selector here

$('#TextBox2')

with

$("#TextBox2")

Edit: actually it doesn't work, I had a bug in my test code. Will look more into this.

Iztoksson
  • 980
  • 16
  • 32
  • I think you may have misunderstood the question (maybe?). I want the postback to happen. Using your code, no postback is done. – ca2s7l Oct 21 '14 at 14:44
  • Yes I understood, I was messing with my test code and was getting postbacks but not with this code. Don't mind the current proposed solution, I'm looking into this, it's an interesting issue. – Iztoksson Oct 21 '14 at 14:49
  • I added another solution, hope you will be able to use it. Regarding the alert blocking postback I believe this is by design - this is a note in w3s "Note: The alert box takes the focus away from the current window, and forces the browser to read the message. Do not overuse this method, as it prevent the user from accessing other parts of the page until the box is closed." – Iztoksson Oct 22 '14 at 10:37
  • Hi Uporabnik003, thanks for your dedication. Unfortunately, this is not an alert box issue. I used them to replicate the main problem, but I'm not using them in my project (I'm using balloons/divs). Your solution is actually being used by me somewhere else in my project and is a good one, but not helpful in this case. I just updated the main description and I'm thinking now this to be a synchronism issue. Please have a look at the new project and try the Thread.Sleep with 5ms and 150ms. I guess you'll understand the problem. Thanks! – ca2s7l Oct 22 '14 at 13:43