JQuery Click handler being run twice

I have a thread
http://forums.asp.net/t/2012306.aspx?Click+Event+handler+being+run+twice
 here.  It is about the click event on a link being run multiple times.  See below

  $(document).on("click", "a[id*='btnSave']", (function (e) {
      debugger
        var subLineId = e.target.id.toString().substr(7)
        //$("tr[data-pr-sublines ='prSubLine-" + subLineId + "']");
        var sURLSectionB = '@Url.Action("UpdatePRSubLine", "AJAXFunctions")';
        var returnedValue = "";
        var bError = false;
        var PRSubLineNumber = $.trim($("#tdSubLineNum_" + subLineId).text()) + $.trim($('#PRSubLineNumberCharPart').val());
        var PRSLQty = $("input[id*='PRSubLine_PRSubLineQty']").val()
        var options = {
            url: sURLSectionB,
            data: {
                __RequestVerificationToken: $('input[name=__RequestVerificationToken]').val(),
                PRSLID: subLineId,
                PRSLNumber: PRSubLineNumber,
                PRSLQty: PRSLQty
            },
            type: "POST",
            cache: false,
            async: false,
        };
      //alert(options.url);
        $.ajax(options).done(function (data) {
        debugger
            if (data != null) {
                if (data == "Good") {
                    returnedValue = data;
                }
                else {
                    bError = true;
                    alert("An Error has occurred.n" + data.toString());
                    returnedValue = "An Error has occurred.n" + data.toString();
                }
            }
            else {
                bError = true;
                alert("An Error has occurred.nIt was not possible to update the PR SubCLIN.");
                returnedValue = "An Error has occurred.nIt was not possible to update the PR SubCLIN.";
            }
        });
       debugger
        var test = bError;
        $("#PRSectionB").empty();
       //alert(returnedValue);
        var sURLSectionB = '@Url.Action("Edit", "PR")';
        //alert(sURLSectionB);
       debugger
        var options = {
            url: sURLSectionB,
            type: "get",
            cache: false,
            async: false
        };
        //alert(options.url);
        $.ajax(options).done(function (data) {
          debugger
            $("#PRSectionB").replaceWith(data);
        });
        if (bError) {
            $("#LinesEdited").addClass("field-validation-error").text(returnedValue).show();
        }
        else {
            $("#LinesEdited").removeClass("field-validation-error").text("").hide();
        }
        return false;
    }));

The first time through it is run once.  subsequent times it is run twice.  Having received no further help I am following the advice of the SQL Server Forum monitors and re-entering a new thread about this issue.  Can someone advise me on how this can even
happen?

Where is this script sitting. in main view or partial view?

if it in partial view, move it to main view. and check.

usually if you attach an event handler more than once. handler executes no of time you attach.

so if this script is in partial view every time it loads. event handler is being attached 

It is the views referred to at this post
http://forums.asp.net/t/2009250.aspx?Switch+Html+DisplayFor+to+Html+EditorFor+on+Button+click
+  Based on the answer to this post, I have a view that contains a partial view, that inserts another partial view as the result of a click on a link. 

The btnSave referenced on the above code is on the partial view that replaces a row on the table of the main partial with a edtiable row.  The click event for that button instead of being on the partial view that contains that button as recommended by JohnLocke
on thread http://forums.asp.net/t/2007181.aspx?Problem+with+MVC+calling+controller+Post+method+on+load+of+view+  is located on the partial view
with the original table, because at the end of that click event handler, it has to repopulate the main partial view using a call to the controller that gets the data and calls the main partial view, and based upon the return from the ajax call populates the
original partial view with a an error message as needed.

So in answer to your question, this script is sitting in a partial view, addressing an event from a partial view on that partial view.  Below is a sequence of events (since I can’t show a flow diagram in this format.)

  1. PR controller Edit action opens Edit view.
  2. Call to partial view on Edit view opens _SectionB partial view.
  3. Click event of "Edit" link on row of table listing items replaces contents of that tr row with partial view _SectionBEdit (which contains "btnSave" for that item).
  4. Click event of "btnSave" referenced above makes an AJAX call an Ajax Action which calls one stored procedure to verify whether the change is permitted.
  5. If the change is permitted then the AJax returns a plag saying everything is OK.  If not, it returns a message indicating that the change is not permitted and saves that data to a message variable and sets a boolean variable indicating whether the change
    was permitted or not.
  6. The call is made to the Edit Action of the PR controller which because it is an Ajax request only returns the HTML for the SectionB partial view and replaces the Contents of Section B with that HTML and then updates the text of a span on that partial view
    with the return error message, if any.
  7. What is happening is that once this has occurred one time then any time this event fires it fires the first time and properly populates everything and then runs again this time calling the AJAX method in step 4 which this time does not return an error and
    the section B is repopulated without an error message.

New information.  On the second time through, one of the parameters in the first AJAX call is left as undefined. and the break point in the JSon  Action is not hit.

Hi joller,

According to your post ,it seems that you didn’t set a right url to the action in your controller.

please check the url for your second ajax. 

Best Regards,

Kevin Shen.

 

Joeller

On the second time through, one of the parameters in the first AJAX call is left as undefined. and the break point in the JSon  Action is not hit.

Kevin Shen – MSFT

According to your post ,it seems that you didn’t set a right url to the action in your controller.

please check the url for your second ajax. 

Not true.

The reason the parameter was undefined is because it is looking for a value from an element which exists on the table row that is inserted for editing purpose as suggested by JohnLocke.  When the second AJAX call in this procedure is made the first time
through, then the original table without that edit line is rendered as the partial view.  Therefore that element is not found when attempting to assign a value from the elements $("input[id*='PRSubLine_PRSubLineQty']") and $(‘#PRSubLineNumberCharPart’) to
PRSLQty and PRSubLineNumber.  I redid the AjAX call to provide a success function and a failure function and sure enough the failure function was hit on the seccond time through.

Now I created another function to do something similar on another part of this view.  It too is being called by a link as described above and here

http://forums.asp.net/t/2010964.aspx?Links+not+acting+like+standard+links+in+a+table
  .

And I found that is also being run twice.  Now I am wondering, if this is the result of the function being called by a link and doing a return false.  I am going to try to replace the links with a button and see if the the same thing happens.

UPDATE:  No.  Even when I replace the link with an input of type button it stills runs the handler twice anytime on all clicks subseqent to the first time clicked..

UPDATE II: Actually it is being run four or more times.

Having received no suggestionson how to keep the event from firing multiple times I had an idea for a workaround.

 $(document).on("click", "a[id*='btnSave']", (function (e) {
      debugger
        var subLineId = e.target.id.toString().substr(7)
        //$("tr[data-pr-sublines ='prSubLine-" + subLineId + "']");
        var sURLSectionB = '@Url.Action("UpdatePRSubLine", "AJAXFunctions")';
        var returnedValue = "";
        var bError = false;
        var PRSubLineNumber = $.trim($("#tdSubLineNum_" + subLineId).text()) + $.trim($('#PRSubLineNumberCharPart').val());
        var PRSLQty = $("input[id*='PRSubLine_PRSubLineQty']").val()
        if (typeof PRSLQty == 'undefined') {
            return false;
        }
        var options = {
            url: sURLSectionB,
            data: {
                __RequestVerificationToken: $('input[name=__RequestVerificationToken]').val(),
                PRSLID: subLineId,
                PRSLNumber: PRSubLineNumber,
                PRSLQty: PRSLQty
            },
            type: "POST",
            cache: false,
            async: false,
            success: function (data) {
                debugger
                if (data != null) {
                    if (data == "Good") {
                        returnedValue = data;
                    }
                    else {
                        bError = true;
                        alert("An Error has occurred.n" + data.toString());
                        returnedValue = "An Error has occurred.n" + data.toString();
                    }
                }
                else {
                    bError = true;
                    alert("An Error has occurred.nIt was not possible to update the PR SubCLIN.");
                    returnedValue = "An Error has occurred.nIt was not possible to update the PR SubCLIN.";
                }
            },
            error: function () {
                bError = true;
                alert("An Error has occurred.nIt was not possible to update the PR SubCLIN.");
                returnedValue = "An Error has occurred.nIt was not possible to update the PR SubCLIN.";
            }
        };
      //alert(options.url);
        $.ajax(options).done();
       debugger
        var test = bError;
        $("#PRSectionB").empty();
       //alert(returnedValue);
        var sURLSectionB = '@Url.Action("Edit", "PR")';
        //alert(sURLSectionB);
       debugger
        var options = {
            url: sURLSectionB,
            type: "get",
            cache: false,
            async: false
        };
        //alert(options.url);
        $.ajax(options).done(function (data) {
          debugger
            $("#PRSectionB").replaceWith(data);
        });
        if (bError) {
            $("#LinesEdited").addClass("field-validation-error").text(returnedValue).show();
        }
        else {
            $("#LinesEdited").removeClass("field-validation-error").text("").hide();
        }
        return false;
    }));

See the underlined code.  On the second time through the input is not going to exist so the variable will be undefined.  Then I just kick out of the function without making any of the AJAX calls or making any changes.

Untill someone comes up with a why and a fix, that is what I will do.

This workaround was find for the specific couple of buttons who issue it address.  However, now there is another click event which is being run multiple times upon click.  The kind of workaround devised here does not work.

So once again I ask for input on why this is doing that.

Leave a Reply