Search code examples
javascriptasp.netwebformssweetalert2

Why .click() was not triggered after confirming on sweet alert?


I am trying to create a reusable function in javascript to call on buttons that require user confirmation.

I already have this code on my Master Page in WebForms.

function sweetAlertConfirm(btn, title, msg, icon) {
    if (btn.dataset.confirmed) {
        // The action was already confirmed by the user, proceed with server event
        btn.dataset.confirmed = false;
        return true;
    } else {
        // Ask the user to confirm/cancel the action
        event.preventDefault();
        Swal.fire({
            icon: icon,
            title: title,
            text: msg,
            showDenyButton: true,
            showCancelButton: true,
            confirmButtonText: 'Yes',
            denyButtonText: `No`,
        }).then((result) => {
            if (result.isConfirmed) {
                // Trigger the button click event to proceed with the server event
                btn.dataset.confirmed = true;
                btn.click();
            }
        });
    }
}

And I am implementing it on my LinkButton like this.

<asp:LinkButton runat="server" Style="margin-right: 10px;" ID="cmdDeleteGoal"
   CommandArgument='<%# DataBinder.Eval(Container.DataItem, "GoalCode") %>'
   OnClientClick="return sweetAlertConfirm(this, 'Delete Goal?', 'Do you want to delete this goal?', 'question');"
   OnClick="cmdDeleteGoal_Click"  >
   <i class="fa-solid fa-trash text-danger" data-bs-toggle="tooltip"
      data-bs-placement="top"
      title="Delete Goal"></i>
</asp:LinkButton>

CODE BEHIND

LinkButton cmdDeleteGoal = (LinkButton)sender;
                bool _converted = int.TryParse(cmdDeleteGoal.CommandArgument, out int goalCode);
               
                if (!_converted) { 
                    ShowToast("", "#00ff00");
                    return;
                }

                _systemProcess = new DeleteGoalLogic();
                _userInput = new UserInput()
                {
                    KRACode = 1,
                    GoalCode = goalCode
                };
                _systemResult = _systemProcess.DoProcess(_userInput);

                ShowToast(_systemResult.Message, (_systemResult.ResultCode == SystemResult.ResultCode_Success ? "#00ff00" : "#ff0000"));

this is the element rendered in HTML

    <a id="_bodyContent_rptrGoals_cmdDeleteGoal_0"
        href="javascript:__doPostBack('ctl00$_bodyContent$rptrGoals$ctl00$cmdDeleteGoal','')" 
        style="margin-right: 10px;">
           <i class="fa-solid fa-trash text-danger" data-bs-toggle="tooltip" data-bs-placement="top" aria-label="Delete Goal" data-bs-original-title="Delete Goal"></i>
   </a>

Now, the scenario is, The sweetalert is showing, and after I confirm on sweet alert. btn.click(); was not triggered.

I already tried console.log('test') inside this code

if (result.isConfirmed) {
    // Trigger the button click event to proceed with the server event
    btn.dataset.confirmed = true;
    btn.click();
}

and it works properly.

Now, my question is, What am I doing wrong and How can I successfully trigger the btn.click if the user confirms?


Solution

  • Remove the event prevent default.

    Let's make a working example.

    Do not use the prevent default.

    Say we have a Grid view, link button click.

    This:

    <asp:GridView ID="GHotels" runat="server" AutoGenerateColumns="False" 
            DataKeyNames="ID" CssClass="table table-hover" Width="50%">
            <Columns>
                <asp:BoundField DataField="FirstName" HeaderText="FirstName"  />
                <asp:BoundField DataField="LastName" HeaderText="LastName"    />
                <asp:BoundField DataField="HotelName" HeaderText="HotelName"  />
                <asp:TemplateField HeaderText="Active" ItemStyle-HorizontalAlign="Center">
                    <ItemTemplate>
                        <asp:CheckBox ID="chkActive" runat="server" Checked='<%# Eval("Active") %>' />
                    </ItemTemplate>
                </asp:TemplateField>
    
                <asp:BoundField DataField="Description" HeaderText="Description"  />
    
                <asp:TemplateField HeaderText="Delete" ItemStyle-HorizontalAlign="Center">
                    <ItemTemplate>
                        <asp:LinkButton ID="cmdDeleteHotel" 
                            ToolTip="Delete this file"
                            runat="server"
                            OnClick="cmdDeleteHotel_Click"
                            OnClientClick="return sweetAlertConfirm(this, 'Delete Hotel?', 'Delete this hotel?', 'question');"
                            >
                                <span class="fa fa-trash-o fa-lg"></span>
                        </asp:LinkButton>
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>
    

    code to load, and link delete button code:

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        If Not IsPostBack Then
            LoadGrid
        End If
    End Sub
    
    Sub LoadGrid()
    
        GHotels.DataSource = MyRst("SELECT * FROM tblHotelsA ORDER BY HotelName")
        GHotels.DataBind()
    
    End Sub
    
    Protected Sub cmdDeleteHotel_Click(sender As Object, e As EventArgs)
    
        Dim btn As LinkButton = sender
        Dim gRow As GridViewRow = btn.NamingContainer
    
        Debug.Print("Row index = " & gRow.RowIndex)
        Dim intPK As Integer = GHotels.DataKeys(gRow.RowIndex).Item("ID")
    
        Dim cmdSQL As New SqlCommand("DELETE FROM tblHotels WHERE ID = @ID")
        cmdSQL.Parameters.Add("@ID", SqlDbType.Int).Value = intPK
        'MyRstPE(cmdSQL)
        Debug.Print($"Will delete {intPK}")
    
    End Sub
    

    And the script is this:

            <script>
                function sweetAlertConfirm(btn, title, msg, icon) {
    
                    if (btn.dataset.confirmed) {
                        // The action was already confirmed by the user, proceed with server event
                        btn.dataset.confirmed = false;
                        return true;
                    } else {
                        // Ask the user to confirm/cancel the action
    
                        swal(msg, {
                            buttons: ["No", "Yes"],
                        }).then((willDelete) => {
                            if (willDelete) {
                                // Trigger the button click event to proceed with the server event
                                btn.dataset.confirmed = true;
                                btn.click();
                            }
                        });
                    }
                    return false;
                }
    

    The result is this:

    enter image description here

    output:

    Row index = 5
    Will delete 3
    

    So, you return a true or false. The above works fine as a proof of concept.

    Clean up your code, your cut + paste, or code has all kinds of errors.

     Swal --- no, it lower case!!! swal(.....
    

    and this:

        }).then((result) => {
            if (result.isConfirmed) {
    

    should be this:

      }).then((result) => {
         if (result) {
    

    So, yes, remove the prevent default.

    Just return a true, or false to control running of the server side button.

    Your click probably does not work due to errors in your js code.

    Edit#2: using sweet alert 2

    So, I now have this, same code really, and it still works just fine.

    Remember, it is the CONCEPTS you want to learn here.

    So, say we have this:

    <script src="//cdn.jsdelivr.net/npm/sweetalert2@10"></script>
    
    <asp:GridView ID="GHotels" runat="server" AutoGenerateColumns="False" 
            DataKeyNames="ID" CssClass="table table-hover" Width="800px">
            <Columns>
                <asp:BoundField DataField="FirstName" HeaderText="FirstName"  />
                <asp:BoundField DataField="LastName" HeaderText="LastName"    />
                <asp:BoundField DataField="HotelName" HeaderText="HotelName"  />
                <asp:TemplateField HeaderText="Active" ItemStyle-HorizontalAlign="Center">
                    <ItemTemplate>
                        <asp:CheckBox ID="chkActive" runat="server" Checked='<%# Eval("Active") %>' />
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:BoundField DataField="Description" HeaderText="Description"  />
                <asp:TemplateField HeaderText="Delete" ItemStyle-HorizontalAlign="Center">
                    <ItemTemplate>
                        <asp:LinkButton ID="cmdDeleteHotel" 
                            ToolTip="Delete this file"
                            runat="server"
                            OnClick="cmdDeleteHotel_Click"
                            OnClientClick="return sweetAlertConfirm(this);"
                            >
                            <span class="fa fa-trash-o fa-lg"></span>
                        </asp:LinkButton>
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>
    
    
            <script>
                function sweetAlertConfirm(btn) {
    
                    if (btn.dataset.confirmed) {
                        btn.dataset.confirmed = false;
                        return true;
                    }
    
                    Swal.fire({
                        title: 'Are you sure?',
                        text: "Delete This Hotel?",
                        icon: 'warning',
                        showCancelButton: true,
                        confirmButtonText: 'Yes, delete it!',
                        cancelButtonText: 'No, Cancel',
                    }).then((result) => {
                        if (result.isConfirmed) {
                            // Trigger the button click event to proceed with the server event
                            btn.dataset.confirmed = true;
                            btn.click();
                        }
                    })
                    return false;
                }
            </script>
    

    And once again, our code behind is this:

    Protected Sub cmdDeleteHotel_Click(sender As Object, e As EventArgs)
    
        Dim btn As LinkButton = sender
        Dim gRow As GridViewRow = btn.NamingContainer
        Dim intPK As Integer = GHotels.DataKeys(gRow.RowIndex).Item("ID")
    
        Dim cmdSQL As New SqlCommand("DELETE FROM tblHotelsA WHERE ID = @ID")
    
        cmdSQL.Parameters.Add("@ID", SqlDbType.Int).Value = intPK
        MyRstPE(cmdSQL)
        LoadGrid()  ' update gv to show deleted
    
    End Sub
    

    And I as noted, UN-commented out the delete command, and removed the debug.prints.

    And results are now this:

    enter image description here