如何移除点击事件处理程序?

huangapple go评论111阅读模式
英文:

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:

  1. user click the link (href has the url for the actionmethod to call)
  2. The modal confirm dialog is opened
  3. 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) {

这将删除先前的点击事件监听器并添加一个新的。

这里有一些关于 offon 的文档。"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.

huangapple
  • 本文由 发表于 2023年7月13日 21:14:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/76679779.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定