英文:
How to remove click event handler?
问题
In your new code, you're correct that the url
variable is not defined inside the click
event handler for #confirmButton
. This is because url
is defined within the scope of the click
event handler for a[data-bs-toggle="modal"][requires-confirmation]
, and it's not accessible within the #confirmButton
click event handler.
To make the url
variable accessible within the #confirmButton
click event handler, you can define it outside both event handlers in a higher scope. Here's how you can modify your code to achieve the desired behavior:
$(function () {
$.ajaxSetup({ cache: false });
var url; // Define the 'url' variable in a higher scope
$('a[data-bs-toggle="modal"][requires-confirmation]').on('click', function (e) {
e.preventDefault();
url = $(this).attr('href'); // Set the 'url' variable here
var hasDataDelete = $(this).is('[data-delete]');
var deleteAction = $(this).attr('data-delete') === 'true';
$('#confirmModal').modal('show');
// Rest of your code...
});
$('#confirmButton').on('click', function (event) {
event.preventDefault();
$.ajax({
url: url, // Use the 'url' variable defined earlier
type: 'POST',
// Rest of your code...
});
});
});
By defining url
in a higher scope, it becomes accessible in both event handlers, allowing you to send the request to the server only when the user clicks the confirm button after opening the modal.
英文:
In the js code below, when the user clicks a link they should be given a confirmation modal to approve the action.
However, there is a bug where if the user clicks a link, the confirmation modal is shown, then if they click another link another modal appears. If they confirm that modal 2 requests are sent.
How can I remove the click events of other links when a Modal is open?
$(function () {
$.ajaxSetup({ cache: false });
$('a[data-bs-toggle="modal"][requires-confirmation]').on('click', function (e) {
//***************************************
//trying to prevent click event propagation
//***************************************
e.stopPropagation();
e.preventDefault();
//***************************************
var url = $(this).attr('href');
var hasDataDelete = $(this).is('[data-delete]');
var deleteAction = $(this).attr('data-delete') === 'true';
$('#confirmModal').modal('show');
$("#errorContainer").hide();
$('#confirmMessage').show();
$('#confirmButton').show();
if (deleteAction) {
$('#checkboxContainer').show();
$('#confirmCheckbox').prop('checked',false);
$('#confirmButton').prop('disabled', true);
} else {
$('#checkboxContainer').hide();
$('#confirmButton').prop('disabled', false);
}
$('#confirmCheckbox').change(function () {
$('#confirmButton').prop('disabled', !$(this).is(':checked'));
});
$('#confirmButton').click(function (e) {
e.preventDefault();
$.ajax({
url: url,
type: 'POST',
success: function (result) {
if (result.success == 1) {
location.reload();
}
else {
$("#errorContainer").html('<p> Errore:' + result.error + '</p>')
$("#checkboxContainer").hide();
$('#confirmMessage').hide();
$('#confirmButton').hide();
}
},
error: function (xhr, status, error) {
$("#errorContainer").html('<p> Errore:' + error + '</p>')
$("#checkboxContainer").hide();
$('#confirmMessage').hide();
$('#confirmButton').hide();
}
});
});
});
});
View
@using GESTPREF.Models.ViewModels
@using GESTPREF.Models.Enums
@using GESTPREF.Helpers
@model IEnumerable<GruppoDisplayViewModel>
@{
ViewBag.Title = "Elenco gruppi/livelli";
}
<h2>@ViewBag.Title</h2>
@{
var badgeClasses = new Dictionary<StatoRecord, string>()
{
{ StatoRecord.Attivo, "badge bg-success" },
{ StatoRecord.Inattivo, "badge bg-warning text-dark" },
{ StatoRecord.Cancellato , "badge bg-danger" }
};
}
<div class="d-flex justify-content-end align-items-center mb-2">
@Html.BootstrapActionLink("Crea", "Create", "Gruppi", "bi bi-plus-circle", "Crea nuovo gruppo",null, new { @class = "btn btn-primary" })
</div>
<table class="table table-bordered table-sm">
<thead class="table-light text-dark">
<tr>
<td>Gruppo</td>
<td>Livelli</td>
<td>Stato</td>
<td>Azioni</td>
</tr>
</thead>
<tbody>
@foreach (var gruppo in Model)
{
<tr>
<td class="align-top">
<table class="table-sm table-borderless">
<tr>
<td><i>@gruppo.Codice</i></td>
</tr>
<tr>
<td class="fw-bold">@gruppo.Nome</td>
</tr>
</table>
</td>
<td>
<table class="table-sm table-borderless">
@foreach (var livello in gruppo.Livelli)
{
<tr>
<td><i>@livello.Codice</i></td>
<td class="fw-bold">@livello.Nome</td>
</tr>
}
</table>
</td>
<td>
<span class="@badgeClasses[@gruppo.Stato]">@gruppo.Stato.ToString()</span>
</td>
<td>
@if (gruppo.Stato == StatoRecord.Attivo)
{
@Html.BootstrapActionLink("", "Edit", "Gruppi", "bi bi-pencil", "Modifica gruppo",
routeValues: new { id = gruppo.Id },
htmlAttributes: new { @class = "btn btn-primary btn-sm" })
@Html.Raw("&nbsp");
@Html.BootstrapActionLink("", "Disattiva", "Gruppi", "bi bi-toggle-on", "Disattiva gruppo",
routeValues: new { id = gruppo.Id },
htmlAttributes: new
{
@class = "btn btn-outline-warning btn-sm",
data_bs_toggle = "modal",
requires_confirmation = "true"
})
}
else if (gruppo.Stato == StatoRecord.Inattivo)
{
@Html.BootstrapActionLink("", "Attiva", "Gruppi", "bi bi-toggle-off", "Attiva gruppo",
routeValues: new { id = gruppo.Id },
htmlAttributes: new
{
@class = "btn btn-outline-success btn-sm",
data_bs_toggle = "modal",
requires_confirmation = "true",
})
@Html.Raw("&nbsp");
@Html.BootstrapActionLink("", "Cancella", "Gruppi", "bi bi-trash", "Cancella gruppo",
routeValues: new { id = gruppo.Id },
htmlAttributes: new
{
@class = "btn btn-outline-danger btn-sm",
data_bs_toggle = "modal",
requires_confirmation = "true",
data_delete = "true"
})
}
</td>
</tr>
}
</tbody>
</table>
<div id="confirmModal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="confirmModalLabel" aria-hidden="true" data-bs-keyboard="false" data-bs-backdrop="static">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Conferma operazione</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Chiudi"></button>
</div>
<div class="modal-body">
<p id="confirmMessage">Sei sicuro di voler procedere?</p>
<div id="checkboxContainer" style="display: none;">
<p class="text-danger">ATTENZIONE : La cancellazione è un'operazione irreversibile!</p>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="confirmCheckbox">
<label class="form-check-label" for="confirmCheckbox">Ho capito e confermo</label>
</div>
</div>
<div id="errorContainer"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Annulla</button>
<button type="button" class="btn btn-primary" id="confirmButton" disabled>Conferma</button>
</div>
</div>
</div>
</div>
@section scripts
{
<script src="~/Scripts/confirm-modal.js"></script>
}
I'he changed my code as below:
$(function () {
$.ajaxSetup({ cache: false });
$('a[data-bs-toggle="modal"][requires-confirmation]').on('click', function (e) {
//e.stopPropagation();
e.preventDefault();
var url = $(this).attr('href');
var hasDataDelete = $(this).is('[data-delete]');
var deleteAction = $(this).attr('data-delete') === 'true';
$('#confirmModal').modal('show');
$("#errorContainer").hide();
$('#confirmMessage').show();
$('#confirmButton').show();
if (deleteAction) {
$('#checkboxContainer').show();
$('#confirmCheckbox').prop('checked',false);
$('#confirmButton').prop('disabled', true);
} else {
$('#checkboxContainer').hide();
$('#confirmButton').prop('disabled', false);
}
$('#confirmCheckbox').change(function () {
$('#confirmButton').prop('disabled', !$(this).is(':checked'));
});
});
$('#confirmButton').on('click',function (event) {
event.preventDefault();
$.ajax({
url: url,
type: 'POST',
success: function (result) {
if (result.success == 1) {
location.reload();
}
else {
$("#errorContainer").html('<p> Errore:' + result.error + '</p>')
$("#checkboxContainer").hide();
$('#confirmMessage').hide();
$('#confirmButton').hide();
}
},
error: function (xhr, status, error) {
$("#errorContainer").html('<p> Errore:' + error + '</p>')
$("#checkboxContainer").hide();
$('#confirmMessage').hide();
$('#confirmButton').hide();
}
});
});
});
This is what I want to have happen:
- user click the link (href has the url for the actionmethod to call)
- The modal confirm dialog is opened
- The request will be sent to the server only if the user clicks the confirm button
With my previous code, if I understand what @Salman said, every time I am adding an event to the same button so there are multiple requests sent.
But now in my new code, obviously, the url vriable is not defined and no request are sent.
答案1
得分: 0
你的问题在这里:
$('#confirmButton').click(function (e) {
每次用户点击链接时,你都会添加一个新的事件监听器,因此最终会在同一个按钮上有很多个点击监听器。
你应该这样做:
$('#confirmButton').off('click').on('click', function (e) {
这将删除先前的点击事件监听器并添加一个新的。
这里有一些关于 off 和 on 的文档。"On" 是添加事件监听器的新/首选方式,因为它更一致。而 off 将移除选定的事件监听器。
英文:
Your problem is here:
$('#confirmButton').click(function (e) {
You are adding a new event listener every time the user clicks a link, so you end up with many click listeners on the same button.
You should do something like this:
$('#confirmButton').off('click').on('click', function (e) {
This will remove the previous click event listener and add a new one.
Here's some docs on off and on. 'On' is just the new/preferred way to add event listeners since it is more consistent. And off will remove the selected event listener.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论