Mr Robot
Mr Robot

Reputation: 897

JQuery ajax executing multiple times on switch toggle

I have a table list of all the outlets, I have a materialize CSS button to activate or deactivate the outlet,

@foreach($outlets as $outlet)
<tr>
    <td>
        <div class="switch m-b-md" data-id="{{$outlet->id}}">
            <label>
                @if($outlet->status == 'active')
                    <input id="agent-status" type="checkbox" checked="">
                @else
                    <input id="agent-status" type="checkbox">
                @endif
                <span class="lever"></span>
            </label>
        </div>
    </td>
</tr>
@endforeach

the issue is when I click on .switch ajax is executing multiple times, if I keep toggling the switch it is executing more than 5 to 10 times

$(document).on("click", ".switch", function() {

    var outlet_id = $(this).data('id');

    $(".switch").find("input[type=checkbox]").on("change",function() {

        var status = $(this).prop('checked');

        if(status == true) {
            status = "active";
        } else {
            status = "inactive";
        }

        $.ajax ({
            url: '/manager/outlets/'+outlet_id+'/status',
            type: 'POST',              
            data: {"id": outlet_id, "status": status, "_token": '{{ csrf_token() }}'},
            success: function(data)
            {   
                if(data.status==true) {
                    swal("Updated", "Status updated successfully", "success");
                } else if(data.status==false) {
                    swal("Failed", "Fail to update status try again", "error");
                }
            },
            error: function(error)
            {
                swal("Failed", "Fail to update status try again", "error");
            }
        });

    });

});

thank you

Upvotes: 1

Views: 1799

Answers (3)

MysterX
MysterX

Reputation: 2378

You need just separate your event listeners and use outlet_id as closure to have access to it from both listeners. See below:

    var outlet_id;

    $(document).on("click", ".switch", function() {

        outlet_id = $(this).data('id');

    });

    $(".switch").find("input[type=checkbox]").on("change",function() {

        var status = $(this).prop('checked');

        if(status == true) {
            status = "active";
        } else {
            status = "inactive";
        }

        $.ajax ({
            url: '/manager/outlets/'+outlet_id+'/status',
            type: 'POST',
            data: {"id": outlet_id, "status": status, "_token": '{{ csrf_token() }}'},
            success: function(data)
            {
                if(data.status==true) {
                    swal("Updated", "Status updated successfully", "success");
                } else if(data.status==false) {
                    swal("Failed", "Fail to update status try again", "error");
                }
            },
            error: function(error)
            {
                swal("Failed", "Fail to update status try again", "error");
            }
        });

    });

Upvotes: 2

Munzer
Munzer

Reputation: 2318

it is happening because each time a switch is clicked, a listener is added, you shouldn't have this nested listeners,

what i would do is add delegate function for checkbox change on all input type checkbox, i would give these inputs a class to simplify my selection

$(".switch").on('change','.CheckBoxClass', function(){
var theid = $(this).parent('.switch').data('id');
var status = $(this).prop('checked');
//add the rest of your code
});

Upvotes: 1

Gulmuhammad Akbari
Gulmuhammad Akbari

Reputation: 2034

Your loop creates multiple div with the same class switch, when you click on the class, all div with switch class calls for ajax post. therefore, please id for each of your div in your loop.

<div class="switch m-b-md" id="div_{{$outlet->id}}" onclick="callAjax('div_{{$outlet->id}}')">

Your ajax:

function callAjax(divid){

   //do your ajax call here.....

}

Upvotes: 1

Related Questions