最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

jquery - Javascript - Change event trigger multiple times - Stack Overflow

programmeradmin5浏览0评论

I have the following table.

<table class="table invoice-items-table">
    <thead>
        <tr>
            <th>Item</th>
            <th>Quantity</th>
            <th>Price</th>
            <th>Amount</th>
        </tr>
    </thead>
    <tbody>
        <tr class="invoice-item-row">
            <td>
                <select class="selectpicker invoice-item-select" title="Select an Item">
                    <option value="1">PHP Development</option>
                </select>
            </td>
            <td class="text-right">
                <input class="form-control invoice-item-quantity" value="1" type="text">
            </td>
            <td class="text-right">
                <input class="form-control invoice-item-price" value="0.00" type="text">
            </td>
            <td class="text-right" style="padding-top:18px!important;">
                <span class="invoice-item-amount">0 </span>
                <span class="invoice-currency">₹</span>
            </td>
        </tr>
        <tr class="invoice-item-add-row">
            <td colspan="7">
                <a href="#" class="link invoice-item-add text-center">
                    <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
                    Add an Item
                </a>
            </td>
        </tr>
    </tbody>
</table>

For on-click event of a.invoice-item-add I append more table rows tr to the table, here is the code for that.

$('.invoice-item-add').on('click', function() {
    var itemRowClone = $('.invoice-item-row').last().clone();
    itemRowClone.find('input, textarea').val('');
    itemRowClone.find('.bootstrap-select').replaceWith(function() { return $('select', this); });
    itemRowClone.find('.selectpicker').selectpicker();
    $('.invoice-item-add-row').before(itemRowClone);
    return false;
});

This works perfectly fine, until I want to trigger select.invoice-item-select, here is how I trigger it.

$(document).on('change', '.invoice-item-select', function() {
    // Code here...
});

my problem is, this on-change gets fired multiple times based on the number of elements added dynamically, if there is one tr.invoice-item-row it gets fired twice, if there are two tr.invoice-item-row it gets fired four times, basically it fires times two.

I understand that the tr.invoice-item-row are added dynamically and we are using $(document).on('change', '.invoice-item-select', function()... to listen to the trigger.

How do I make sure this on-change event is fired only once?

Thanks.

I have the following table.

<table class="table invoice-items-table">
    <thead>
        <tr>
            <th>Item</th>
            <th>Quantity</th>
            <th>Price</th>
            <th>Amount</th>
        </tr>
    </thead>
    <tbody>
        <tr class="invoice-item-row">
            <td>
                <select class="selectpicker invoice-item-select" title="Select an Item">
                    <option value="1">PHP Development</option>
                </select>
            </td>
            <td class="text-right">
                <input class="form-control invoice-item-quantity" value="1" type="text">
            </td>
            <td class="text-right">
                <input class="form-control invoice-item-price" value="0.00" type="text">
            </td>
            <td class="text-right" style="padding-top:18px!important;">
                <span class="invoice-item-amount">0 </span>
                <span class="invoice-currency">₹</span>
            </td>
        </tr>
        <tr class="invoice-item-add-row">
            <td colspan="7">
                <a href="#" class="link invoice-item-add text-center">
                    <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
                    Add an Item
                </a>
            </td>
        </tr>
    </tbody>
</table>

For on-click event of a.invoice-item-add I append more table rows tr to the table, here is the code for that.

$('.invoice-item-add').on('click', function() {
    var itemRowClone = $('.invoice-item-row').last().clone();
    itemRowClone.find('input, textarea').val('');
    itemRowClone.find('.bootstrap-select').replaceWith(function() { return $('select', this); });
    itemRowClone.find('.selectpicker').selectpicker();
    $('.invoice-item-add-row').before(itemRowClone);
    return false;
});

This works perfectly fine, until I want to trigger select.invoice-item-select, here is how I trigger it.

$(document).on('change', '.invoice-item-select', function() {
    // Code here...
});

my problem is, this on-change gets fired multiple times based on the number of elements added dynamically, if there is one tr.invoice-item-row it gets fired twice, if there are two tr.invoice-item-row it gets fired four times, basically it fires times two.

I understand that the tr.invoice-item-row are added dynamically and we are using $(document).on('change', '.invoice-item-select', function()... to listen to the trigger.

How do I make sure this on-change event is fired only once?

Thanks.

Share Improve this question asked Mar 30, 2017 at 8:56 Ibrahim Azhar ArmarIbrahim Azhar Armar 25.7k36 gold badges135 silver badges212 bronze badges 1
  • That’s to be expected. Every time you add something to the DOM, the document is changing. Do you mean only once per row or once per event? – Manngo Commented Mar 30, 2017 at 9:14
Add a comment  | 

4 Answers 4

Reset to default 7

I ended up using this solution

$(document).on('change', '.invoice-item-select', function(e) {
    if (e.handled !== true) {
        e.handled = true;
        return;
    }
    // Code here
});

Although this does not stop from multiple firing of events, I can at-least stop the code execution for subsequent triggers.

$(document).on('change') event should called once on page load. No need to add document change on row add.

OR

You can first unbind event then bind again like

$(document).off('change','.invoice-item-select').on('change', '.invoice-item-select', function() {
    // Code here...
});

Below code save my time. Your code should run inside the 'if' function and element's 'click' event. Then you can avoid the item duplication.

$(document).on('click', '.selectpicker', function(e) {
        if (e.handled !== true) 
        {
            e.handled = true;

            // Your code here

            return;
        }
    });

You can try in alternative way like this,

$('.invoice-item-select.bootstrap-select').on('changed.bs.select', function(){
// your code
});

bootstrap-select class should be applied after loading DOM into the browser.

I hope this will solve your problem.

发布评论

评论列表(0)

  1. 暂无评论