Jquery .change() event not firing for hidden pagination
Jquery .change() event not firing for hidden pagination
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
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
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?
Sending over account information now.
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 achange
delegated event handler: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 (thetable
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
orcolumns.createdCell
methods could be used to do that.Regards,
Allan
Maybe I am over complicating it at this point. Is it possible to use the table api and do math from that?
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!
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