skip to Main Content

hope someone can help me understand..
I have an asp.net project for which I have decided to use SweetAlert for a confirmation button.
I have followed suggestions in here:

Using SweetAlert2 to replace "return confirm()" on an ASP.Net Button

The issue is that although the SweetAlert prompt is working fine, when accepting, the server side code is not being executed.

    <script src="Scripts/sweetalert-dev.js"></script>
<link href="Styles/sweetalert.css" rel="stylesheet" />

this is the button:

<asp:Button ID="btndiscard" runat="server" Font-Size="Large" Text="Discard" Width="100px" onClientClick="return fnConfirmDiscard(this);" OnClick="btndiscard_Click" ToolTip="Discard this application (must be pending)"/>

this is the javascript code:

<script type="text/javascript">
    var myok = false
    function fnConfirmDiscard(btndiscard) {
        //return confirm("Confirm to discard this application");

        if (btndiscard.dataset.confirmed) {
            // The action was already confirmed by the user, proceed with server event
            btndiscard.dataset.confirmed = false;
            alert("true");
            return true;
        } else {
            // Ask the user to confirm/cancel the action
            event.preventDefault();
            swal({
                title: 'Are you sure?',
                text: "You won't be able to revert this!",
                type: 'warning',
                showCancelButton: true,
                confirmButtonColor: '#3085d6',
                cancelButtonColor: '#d33',
                confirmButtonText: 'Yes, delete it!'
            }).then(function(myresult) {
                // Set data-confirmed attribute to indicate that the action was confirmed
                if (myresult) {
                    btndiscard.dataset.confirmed = true;
                    alert("test then");
                    // Trigger button click programmatically
                    btndiscard.click();
                }
            }).catch(function (reason) {
                // The action was canceled by the user
                alert("test catch");
            });
        }
    }

and this is the server side codebehind:

protected void btndiscard_Click(object sender, EventArgs e)
    {
        // this procedure will discard a credit application (change status to "X")
        // ask for confirmation

        bool wasposted = false;

        try
        {
            System.Data.SqlClient.SqlCommand qryproc;
            string CAccountsConnection = System.Configuration.ConfigurationManager.ConnectionStrings["CAConnectionString"].ConnectionString;
            string entid = ("00000" + lblentid.Text.Trim());

            qryproc = new System.Data.SqlClient.SqlCommand("exec sp_CAChangeStatus @entid,@newstatus");
            qryproc.Parameters.Add("@entid", SqlDbType.Char, 11);
            qryproc.Parameters.Add("@newstatus", SqlDbType.Char, 1);
            qryproc.Parameters["@entid"].Value = entid;
            qryproc.Parameters["@newstatus"].Value = "X";

            qryproc.Connection = new System.Data.SqlClient.SqlConnection(CAccountsConnection);
            qryproc.Connection.Open();
            qryproc.ExecuteNonQuery();

            wasposted = true;
            qryproc.Connection.Close();
            qryproc.Dispose();
            wasposted = true;
        }
        catch
        {
            wasposted = false;
        }

        if (wasposted)
        {
            lblcurrstatus.Text = "D";
            MessageToUser("Transaction successfull, application discarted.",MessageTypes.result_ok);
            ResetAllFields();
            lblentid.Text = "";
            btnnewpage.Text = "New";
            MultiView1.ActiveViewIndex = 0;
        }
        else
            MessageToUser("Transaction not successfull! please try again.",MessageTypes.error);
    }

before using sweetalert I was using a simple javascript confirm box and that was working without issues and the server side procedure ran without problems.

if I remove event.preventDefault() then the server side procedure is called BUT the sweetalert cancel does not work either (the server side code is executed anyway)

Anybody has seen this issue? Any help would be greatly appreciated, Thanks.

2

Answers


  1. Chosen as BEST ANSWER

    Thank you Albert D for your excellent explanation of the Issue. Upon reviewing the answer I noticed that the parameters used in my Swal Function were not in accordance with your code. I changed those parameters, but still was not working. I verified my source javascritpt file and the problem was basically that I was using bootstrap and was referencing the wrong one for the job.

    so instead of using:

    <script src="Scripts/sweetalert-dev.js"></script>
    

    I changed to (after downloading from https://www.cdnpkg.com/bootstrap-sweetalert/file/sweetalert.min.js/):

    <script src="Scripts/sweetalert.min.js"></script>
    

    finally, after making suggested tweaks this is the result:

        <script type="text/javascript">
        function fnConfirmDiscard(btndiscard) {
            //return confirm("Confirm to discard this application");
            // if no account has been created dont do anything...
            if (document.getElementById("lblentid").innerHTML.trim() == "")
                return false;
    
            if (btndiscard.dataset.confirmed) {
                // The action was already confirmed by the user, proceed with server event
                btndiscard.dataset.confirmed = false;
                return true;
            } else {
                // Ask the user to confirm/cancel the action
                event.preventDefault();
                swal({
                    title: "Are you sure you wish to discard application?",
                    text: "You will not be able to change this!",
                    icon: "warning",
                    buttons: ["Cancel","Continue"],
                    dangerMode:true,
                }).then(function(myresult) {
                    // Set data-confirmed attribute to indicate that the action was confirmed
                    if (myresult) {
                        btndiscard.dataset.confirmed = true;
                        // Trigger button click programmatically
                        btndiscard.click();
                    }
                }).catch(function (reason) {
                    // The action was canceled by the user
                });
            }
        }
    

    Now it is working as expected. Thanks again.


  2. Well, a simple js conform works, because alert, and confirm HALTS the code.

    however, these days, EVERY js routine does NOT halt the code. So, when you click that button, the js function you have runs, but DOES NOT wait. I repeat this again:

    The js routine does not wait!!!!

    It will run though, pop the sweet alert AND THAT POINT the true/false value will have been returned to the button click event. So, your dialog shows, but ALSO the button event also triggers.

    So, you can work around this issue with a bit of a trick. As noted, you need a public (global) flag var in your js code, and I see you do have this:

     var myok = false
     function fnConfirmDiscard(btndiscard) {
        //return confirm("Confirm to discard this application");
    
         if (btndiscard.dataset.confirmed) {
    

    So, on page load var myok = false is set – this sets ONLY the first time on each page load (or post back).

    So, we have to make your routine work this way:

    You click on button, dialog displays, and we MUST I repeat MUST return false to the onclient click routine for that button. The sweet dialog is now displayed, the function has run – AND DOES NOT HALT!!! It runs right on thought to the last line of that function and code.

    The code you need should look somthing like this:

    <script type="text/javascript">
        var myok = false
        function fnConfirmDiscard(btndiscard) {
        
        if (mydeleteok) {
            return true
        }
            swal({
                title: 'Are you sure?',
                text: "You won't be able to revert this!",
                type: 'warning',
                showCancelButton: true,
                confirmButtonColor: '#3085d6',
                cancelButtonColor: '#d33',
                confirmButtonText: 'Yes, delete it!'
    
               // for yes code, then do this:
                myok = true
                $(btndiscard).click()
    

    So, this is how this works:

    you click on your button.

    Function runs, returns false, server side code does not run. The dialog is NOW displayed, and the WHOLE js function is done, finished, has exited the function.

    Now, sweet alert still has that dialog displayed. If you hit yes, then we want our server side button code to run.

    So, we set our myok flag = true, and THEN click the button again!!!!

    The button is clicked, and then myok = true, and the FIRST part of the function now can return true, and the server side code behind will now run.

    So, the setup will look say like this:

            <asp:Button ID="Button1" runat="server" Text="alert test"
                OnClientClick="return mydelprompt(this)"
                OnClick="Button1_Click" />
            <script>
                var myok = false
                function mydelprompt(btn) {
    
                    if (myok) {
                        return true
                    }
                    swal({
                        title: "Are you sure?",
                        text: "Once deleted, you will not be able to recover this imaginary file!",
                        icon: "warning",
                        buttons: true,
                        dangerMode: true,
                    })
                        .then((willDelete) => {
                            if (willDelete) {
                                myok = true
                                btn.click()
                            }
                        });
                    return false
                }
            </script>
    

    So, what occurs is we actually wind up clicking that button two times!!!

    The first time, user clicks. The above function runs, displays the dialog, AND ALSO RETURNS FALSE!!!! Do not forget that last line of code – return false!!!!!

    Now because the function returned false, then our button click (server side) code did not run, does not run.

    We NOW have the sweet dialog displayed. function has LONG GONE and run and exited!!!! – (remember, js code today does NOT block, does NOT halt – it not really allowed anymore, since that would freeze up the browser. In short time we not even be allowed to use alert() or confirm() – they do halt code, and they will be depreciated.

    Ok, so dialog is displayed. we returned false, button server side click does not run.

    You NOW make your choice in the sweet alert. If you confirm "yes", then this code runs:

     .then((willDelete) => {
                            if (willDelete) {
                                myok = true
                                btn.click()
                            }
    

    we set myok = true, and click the button.

    What happens?

    our function runs again and the first lines of code is this:

                    if (myok) {
                        return true
                    }
    

    So, the function now returns true, and NOW our server side code will run.

    So, keep in mind that most (if not all) js code runs and is what we call asynchronous (does NOT halt – it runs right to the end of the function without waiting, without halting.

    So, use the 2nd code example as to how to lay this out.

    In effect, we do wind up running that button code two times!!! First time user clicks on the button – we return false.

    If user answer = yes in the sweet alert, then we set our flag, and click that SAME button again!!! The function runs again, and the first if (myok) it hit, it returns true, and now the server side code runs (since we returned true to the button click).

    Try the 2nd example and layout and approach. It is simple setting of myok = true and THEN execute a button click in js that simple "clicks" on that button, and that runs the js function again. We don’t really care that the function runs again, but WE MOST certainly do care that we now whacked and set that routine to return a value of true, which then means the function returns true, and the server side button event now runs, and hence code behind runs.

    Of course if the user does not confirm, then we just close the dialog, and nothing occurs, and we don’t care that no server side code ran.

    One might try the above using the button and "dataset" property of JavaScript. However, that first suggestion in your link HAS TWO buttons, and they click a 2nd button. That’s less then ideal, since now you having to add a extra button to the page. You also have to set the "data set" property in markup, and you don’t.

    So, I think the simple myok flag, not using "dataset", and not having to add nor use a 2nd button on the page as hidden is less then ideal. This is especially the case if you have say several buttons, you now have to double up those buttons, double up the "div" and markup to add the data set property.

    I just think a plane jane myok flag is a road with less pit falls.

    Edit: using dataset is fine

    However, if you want, you can dump the myok flag. I just test this, and it works fine:

                function mydelprompt(btn) {
                    if (btn.dataset.myok) {
                        btn.dataset.myok = false
                        return true
                    }
                    swal({
                        title: "Are you sure?",
                        text: "Once deleted, you will not be able to recover this imaginary file!",
                        icon: "warning",
                        buttons: true,
                        dangerMode: true,
                    })
                        .then((willDelete) => {
                            if (willDelete) {
                                btn.dataset.myok = true
                                btn.click()
                            }
                        });
                    return false
                }
    

    So, you can add the "myok" variable to the button if you wish – seems to work, and in fact I think I like it even better. So, despite my "forgiving’s" in regards to using dataset in the DOM and JavaScript? Gee, I kind of like that solution, and it means we don’t need to create a extra global var in the script code – and that’s even better.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search