0

I have a function in the Datatables columns like so

{ 'data': 'status',
    'fnCreatedCell': function (nTd, sData, oData, iRow, iCol) {
         if ((oData.status == null) && (oData.status.status != '10Stat') && (oData.id > 100)) {
             var html = '<span class="tipster text-danger" data-toggle="tooltip" data-placement="top" title="Edit branch"><i class="far fa-edit mx-1 text-secondary zindex-tooltip replaceBranch" onclick="replaceBranch(\''+oData.orderId+'\')"></i></span>';
         } else {
             var html = '<i class="far fa-edit mx-1 lightgray zindex-tooltip"></i>';
         }

     $(nTd).html(html);
     }, 'defaultContent': ''
},

The problem is that the replaceBranch() function, which is called with onclick reiterates once more every time one if the icon is clicked, ie. the first time the modal pops up, the ajax call runs once, there is one result. If another icon is clicked, the modal pops up, the ajax call runs twice, there are two results. If another icon is clicked, the modal pops up, the ajax call runs three times, there are three results. And so forth.

function replaceBranch(order) {

    var mainhtml = '<div class="d-flex my-3"><div class="flex-fill"><h5 class="text-secondary text-left">change branch for order '+order+'</h5></div><div class="flex-fill"></div></div><form onSubmit="return false;"><div class="form-group"><select class="custom-select select5" id="change-country"><option value="" selected>Choose a country...</option></select></div>' + '<div class="form-group"><select class="custom-select select5" id="change-region" disabled><option value="" selected>Choose a region...</option></select></div>' + '<div class="form-group"><select class="custom-select select4" id="change-city" disabled><option value="" selected>Choose a city...</option></select></div>' + '<div class="form-group"><select class="custom-select select4 required" id="change-branch" disabled><option value="" selected>Choose a branch...</option></select></div><div class="input-group mb-3"><input id="branch-input" type="text" class="form-control" placeholder="Branch code" value=""><div class="input-group-append"><button class="btn btn-outline-secondary" type="button" id="branch-load">Find</button></div></div></form>' + '<div id="change-packets-row"></div>';

    $.ajaxSetup({
        async: true
    });
    $.ajax({
        type: "GET",
        url: "http://www.example.com/branches.php?branches",
        dataType: "json",
        cache: false,
        success: function (data) {
            $.each(data.countries, function(key, val) {
                var html = '<option value="' + key + '">' + val + '</option>';
                $(html).appendTo('#change-country');
            });
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            console.log(errorThrown);
        }
    });
    $(document).on('change', '#change-country', function() {
        var selectedCountry = $('#change-country option:selected').val();
        $("#change-region").prop("disabled", "disabled");
        $("#change-region").find('option').not(':first').remove();
        $("#change-city").prop("disabled", "disabled");
        $("#change-city").find('option').not(':first').remove();
        $("#change-branch").prop("disabled", "disabled");
        $("#change-branch").find('option').not(':first').remove();
        $("#change-result").remove();

        if (selectedCountry != '') {
            $.ajax({
                type: "GET",
                url: "http://www.example.com/branches.php?branches&country="+encodeURIComponent(selectedCountry),
                dataType: "json",
                cache: false,
                success: function (country) {
                    $.each(country, function(key, value) {
                        var html = '<option value="' + key + '">' + key + '</option>';
                        $(html).appendTo('#change-region');
                    });
                    $("#change-region").removeAttr("disabled");
                    console.log(country);
                },
                error: function(XMLHttpRequest, textStatus, errorThrown) {
                    console.log(errorThrown);
                }
            });
        }
    });
    $(document).on('change', '#change-region', function() {
        var selectedRegion = $('#change-region option:selected').val();
        $("#change-city").prop("disabled", "disabled");
        $("#change-city").find('option').not(':first').remove();
        $("#change-branch").prop("disabled", "disabled");
        $("#change-branch").find('option').not(':first').remove();
        $("#change-result").remove();
        var i = 0;
        if (selectedRegion != '') {
            $.ajax({
                type: "GET",
                url: "http://www.example.com/branches.php?branches&region="+encodeURIComponent(selectedRegion),
                dataType: "json",
                cache: false,
                success: function (region) {
                    $.each(region, function(key, value) {
                        var html = '<option value="' + key + '">' + key;
                        if (value !== null) {
                            html += ' (' + value + ')';
                        }
                        html += '</option>';
                        $(html).appendTo('#change-city');
                    });
                    $("#change-city").removeAttr("disabled");
                    console.log(region);
                    i++;
                    console.log(i);
                },
                error: function(XMLHttpRequest, textStatus, errorThrown) {
                    console.log(errorThrown);
                }
            });
        }
    });
    $(document).on('change', '#change-city', function() {
        var selectedCity = $('#change-city option:selected').val();
        $("#change-branch").prop("disabled", "disabled");
        $("#change-branch").find('option').not(':first').remove();
        $("#change-result").remove();

        if (selectedCity != '') {
            $.ajax({
                type: "GET",
                url: "http://www.example.com/branches.php?branches&city="+encodeURIComponent(selectedCity),
                dataType: "json",
                cache: false,
                success: function (city) {
                    city.sort(function(a, b) {
                        return a.street > b.street;
                    });
                    $.each(city, function(key, value) {
                        var html = '<option value="'+value.id+'">'+value.street+' - '+value.place+'</option>';
                        $(html).appendTo('#change-branch');
                    });
                    $("#change-branch").removeAttr("disabled");
                    console.log(city);
                },
                error: function(XMLHttpRequest, textStatus, errorThrown) {
                    console.log(errorThrown);
                }
            });
        }
    });
    $(document).on('change', '#change-branch', function() {
        var selectedBranch = $('#change-branch option:selected').val();
        $('#change-result').remove();
        $('#branch-input').val(selectedBranch);

        if (selectedBranch != '') {
            $.ajax({
                type: "GET",
                url: "http://www.example.com/branches.php?branches&branch="+encodeURIComponent(selectedBranch),
                dataType: "json",
                cache: false,
                success: function (branch) {
                    var html = '<div class="col mt-2" id="change-result">';
                    html += '<h5>'+branch.place+'</h5>';
                    html += '<p>'+branch.street+', '+branch.city+' '+branch.zip+' (Branch '+branch.id+')</p>';
                    html += '</div>';
                    $(html).appendTo('#change-packets-row').hide().fadeIn(1000);
                    Swal.enableConfirmButton();

                    console.log(branch);
                },
                error: function(XMLHttpRequest, textStatus, errorThrown) {
                    console.log(errorThrown);
                }
            });
        }
    });
    $(document).on('click', '#branch-load', function() {
        var selectedBranch = $('#branch-input').val();
        $('#change-result').remove();

        if (selectedBranch != '') {
            $.ajax({
                type: "GET",
                url: "http://www.example.com/branches.php?branches&branch="+encodeURIComponent(selectedBranch),
                dataType: "json",
                cache: false,
                success: function (branch) {
                    var html = '<div class="col mt-2" id="change-result">';
                    html += '<h5>'+branch.place+'</h5>';
                    html += '<p>'+branch.street+', '+branch.city+' '+branch.zip+' (Branch '+branch.id+')</p>';
                    html += '</div>';
                    $(html).appendTo('#change-packets-row').hide().fadeIn(1000);
                    Swal.enableConfirmButton();
                    console.log(html);
                },
                error: function(XMLHttpRequest, textStatus, errorThrown) {
                    console.log(errorThrown);
                }
            });
        }
    });
    Swal.fire({
        html: mainhtml,
        showCancelButton: true,
        confirmButtonText: 'Choose a branch',
        cancelButtonText: 'Cancel',
        showLoaderOnConfirm: true,
        animation: true,
        focusConfirm: false,
        onOpen: function () {
            Swal.disableConfirmButton();
            $('.select4').select2({
                theme: 'bootstrap4',
                minimumResultsForSearch: 20
            });

            $('.select5').select2({
                theme: 'bootstrap4',
                minimumResultsForSearch: Infinity
            });
        },
        preConfirm: function() {
            var branch = document.getElementById('branch-input').value;
            if (branch) {
                $.ajax({
                    url: 'http://www.example.com/packets.php?changeStore',
                    type: 'GET',
                    data: {
                        orderId: order,
                        newStoreCode: branch
                    },
                    success: function(msg) {
                        Swal.fire({
                            title: 'OK',
                            text: 'Branch changed to '+msg.result,
                            type: 'success'
                        });
                        $('#updateAll').click();
                    },
                    error: function(XMLHttpRequest, textStatus, errorThrown) {
                        Swal.fire({
                            title: 'Error!',
                            html: errorThrown,
                            type: 'error',
                            confirmButtonText: 'Close'
                        })
                    }
                })
            }
        },
        allowOutsideClick: function() {!Swal.isLoading()}
    })
}

The replaceBranch() function is outside jQuery(document).ready(function($) because, iirc, the function did not work if placed inside, since the datatable is usually loaded later than DOM.

I have tried

onclick="replaceBranch(\''+oData.orderId+'\'); return false;"

and also adding

$(".replaceBranch").unbind("click");

at the beginning of the replaceBranch() function. Neither work.

What could be causing the ajax calls to be run multiple times?

4
  • 1
    Please share your replaceBranch() function. Seems like something in the function is adding additional triggers or triggering existing events. Commented Jul 2, 2019 at 14:39
  • Edited to reflect the function. Commented Jul 2, 2019 at 16:54
  • You are binding a new handler on change/click etc. on every click and this is wrong. It ends up creating multiple handlers and it keeps adding. All the .on() should be outside the function, in the document so it is called only once on document load. Commented Jul 2, 2019 at 17:03
  • Thank you. For some reason I thought it had to be part of the function. If you'd like to make an answer, I'll mark it and upvote. Commented Jul 2, 2019 at 17:44

2 Answers 2

2

Change

var html = '<span class="tipster text-danger" data-toggle="tooltip" data-placement="top" title="Edit branch"><i class="far fa-edit mx-1 text-secondary zindex-tooltip replaceBranch" onclick="replaceBranch(\''+oData.orderId+'\')"></i></span>';

to

var html = '<span class="tipster text-danger" data-toggle="tooltip" data-placement="top" data-orderid="'+oData.orderId+'" title="Edit branch"><i class="far fa-edit mx-1 text-secondary zindex-tooltip replaceBranch" ></i></span>';

then add

$("#someStaticContainer").on("click",".tipster",function() {
 replaceBranch($(this).data("orderid")) 
});

where someStaticContainer is likely the table where nTd lives

Sign up to request clarification or add additional context in comments.

2 Comments

@editor - I kept the code on multiple lines on purpose
While this didn't resolve the problem, the code is better than the original one so I added an upvote.
1

You are binding a new handler on change/click etc. on every click and this is wrong. It ends up creating multiple handlers and it keeps adding. All the .on() should be outside the function, in the document so it is called only once on document load.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.