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?
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:
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.
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: