Jquery .change() event not firing for hidden pagination

Jquery .change() event not firing for hidden pagination

jamesjw007jamesjw007 Posts: 35Questions: 0Answers: 0

Here is a jsfiddle of what I am trying to state. Change the value in any markup input box, then double click it, you'll see it works perfectly until you switch to a different page.

https://jsfiddle.net/jamesjw007/hvk30q5w/

I have an input field that when double clicked updates every single input field in that column with the value that was double clicked. This part of the code works perfectly.

I then find that input value and call the .change() event on it as I have code needed to run to update the retail input box. This works for the current page only.

When I double click the current page I am looking at updates and the .change() event is called and the mate correctly updates. However when I switch to the next page in the table, I can still see the value was updated but the math doesn't add up which means the .change() event never fired for these input boxes. What am I missing?

Here is the table object

//create table
    var table = $('.table').dataTable({
        //dom: "<'row'<'col-md-8'B<<'pull-right ctoolbar'>>><'col-md-4'<'pull-right'l>>>frtip", // custom toolbar buggy in smaller displays
        dom: "<'row'<'col-md-8'B><'col-md-4'<'pull-right'l>>>frtip",
        buttons: [
        {
            extend: 'colvisGroup',
            text: 'Condense Info',
            show: [2, 3, 4, 5, 8],
            hide: [6, 7]
        },
        {
            extend: 'colvisGroup',
            text: 'Show all',
            show: [6, 7]
        }
        ],
        "columnDefs": [
        { "targets": [0, 1], "visible": false }
        ],
        "paging": true,
        "ordering": false,
        "info": true,
        "language": {
            "emptyTable": "Sorry it appears no plans are available for the vehicle.",
            "info": "Showing _START_ to _END_ of _TOTAL_ Plan Options",
            "lengthMenu": "Show _MENU_ Plan Options"
        }
    });

The below code is what is called when you double click on the input within the datatable

// Global Markup double click
    table.on('dblclick', '[name="markupControl"]', function () {
        var value = parseFloat($(this).val()).toFixed(2);

        table.api().column(7).nodes().to$().find('input').val(value).change();

    });

This code is needed so it can update the retailControl which is what updates the correct price.

//  Markup Control Input Boxes
    //  The markup boxes need to update the retail boxes.
    table.on('change', '[name="markupControl"]', function () {
        // Get the rate id from this element
        var rateid = $(this).data('rateid');

        // Pricing variables
        var cost = parseFloat($('div[name="costControl"][data-rateid="' + rateid + '"]').text().replace("$", '').replace(",", ''));
        var markup = parseFloat($(this).val());

        // Update the Retail price for the correct plan retail box
        var retailControl = $('input[name="retailControl"][data-rateid="' + rateid + '"]');
        var newRetail = parseFloat(cost + markup).toFixed(2);
        retailControl.val(newRetail);

        // Force this control to go back to 2 decimals
        $(this).val(markup.toFixed(2));

        // Needed for later so we can call the change event on the retail control
        retailControl.change();
    });

The above code works, but only for the current page I am on in the table. How do I get this code to run for all of the other pages within the table?

markupControl and retailControl are both input boxes.

Replies

  • allanallan Posts: 61,930Questions: 1Answers: 10,154 Site admin

    As far as I can see, that looks like it should work! You are using delegated events from the table node (since you are using the $().dataTable() form to create the table).

    Can you link to the page showing the issue so I can debug it please.

    Allan

  • jamesjw007jamesjw007 Posts: 35Questions: 0Answers: 0

    It's a protected page, let me see if I can get you a user to the dev side. If I can may I send the temp username/password to your inbox?

  • jamesjw007jamesjw007 Posts: 35Questions: 0Answers: 0

    Sending over account information now.

  • allanallan Posts: 61,930Questions: 1Answers: 10,154 Site admin

    Got it - thanks for the link!

    The issue is related to how DataTables handles rows for paging and also the way the event handler as been attached for the change event. You've used a change delegated event handler:

    table.on('change', '[name="markupControl"]', function () {

    which is good in most cases, but here it doesn't work. The reason for that is how delegated event handlers work - they listen for the event (change in this case) on the originally selected element (the table here) and then check to see if the event's original source element was the one defined in the event selector ([name="markupControl"] in this case). If it matches, it triggers the callback, otherwise it doesn't. This works because DOM events "bubble" - i.e. the are triggered first on the original element, then their parent, etc (until they bubble all the way up or they are stopped).

    With that knowledge, add in the fact that when DataTables doesn't need rows for the current view it removes them from the DOM and we have the issue.

    The hidden rows are not in the table, therefore their change event cannot bubble to the table element and thus jQuery event listener on the table never sees them and cannot trigger!

    The only way I can think of to address this is to apply the change event directly to the input elements, rather than to the table (i.e. use a static event handler rather than a delegated one).

    The createdRow or columns.createdCell methods could be used to do that.

    Regards,
    Allan

  • jamesjw007jamesjw007 Posts: 35Questions: 0Answers: 0

    Maybe I am over complicating it at this point. Is it possible to use the table api and do math from that?

    table.api().column(7).nodes().to$().find('input').val(value).change();
    

    That sets the value of every single input in column(7) to what ever 'value' is. Is it possible via the API to check every single row and set column(9) to whatever column(6) + (7) are?

    I'll have to look through the API I'm guessing it might be possible in something like rows.every or something. That does help me think in a different way knowing what is not working tho, thank you!

  • allanallan Posts: 61,930Questions: 1Answers: 10,154 Site admin

    Yes, but you'd need to use a loop to do that - cells().every() might be the most appropriate here. Use a selector that will get the cells you need (i.e. table.cells( null, 7 ).every( ... );.

    Allan

This discussion has been closed.