Click event in column header never fired
Click event in column header never fired
I'm having a bizarre problem where I'm using identical code for two tables to retrieve the column index when the column header is clicked to change the sort. I'm doing this so I can display the sort field name in a printout. In one table it works perfectly and in the other the code for the event is never executed, as I've confirmed in the debugger. I'm using code that I found in this discussion:
https://datatables.net/forums/discussion/24593/retreive-column-idx-when-clicking-on-header. Is there something I'm not seeing here that would cause this issue?
First table (works perfectly):
$('#tblHerbs').on( 'click', 'thead th', function () {
var i;
i = dtHerbs.column(this).index();
switch (i) {
case 0: HerbSort = 'Herb Code'; break;
case 1: HerbSort = 'Herb Name'; break;
case 2: HerbSort = 'Gram Cost '; break;
case 3: HerbSort = 'Inventory'; break;
case 4: HerbSort = 'Low Inv.'; break;
case 5: HerbSort = 'Notes'; break;
}
});
Second table (nothing happens on click; this code is never reached):
$('#tblPatients').on( 'click', 'thead th', function () {
var i;
i = dtPatients.column(this).index();
switch (i) {
case 0: PatientSort = 'Name'; break;
case 1: PatientSort = 'Formula'; break;
case 2: PatientSort = 'Prescription Date'; break;
}
});
This question has an accepted answers - jump to answer
Answers
Your code works for me:
http://live.datatables.net/miyoqoqi/1/edit
Was doing some other testing with two tables so I copied your code into my test (made a couple changes to match my config) and it works.
Kevin
Yes, it should work in both cases! But on my page only the first one works. It's completely baffling.
Can you post a test case showing the issue or a link to your page?
Your snippets of code aren't enough to help troubleshoot.
Kevin
The page is at http://galcott.com/herbpharmacy.com/test.html. Thanks for checking this out.
I get the following error when trying to access the page:
Kevin
Sorry, bad link. Leave out the .com after herbpharmacy
Ok, I figured out your test URL, removed the
.com
fromherbpharmacy.com
.Looks like you are using jQuery UI tabs. I'm no expert but I suspect the problem is the Patients table does not exist when the click event is initialized. I think you will need to execute the click event init code when you active the Patients tab. Then you may need to execute the Herb click event when clicking back to and activating the Herbs tab.
Kevin
No, it has nothing to do with the tabs. If you look at the code that's not working you'll see that it comes after the table is initialized. I did it the same way for the Herbs table, which works perfectly. All of that is done before the tabs are created.
Executing the click event when the Patients tab is activated wouldn't work. It needs to be executed on the actual click when they're in the Patients table. The whole purpose of it is to display the sort order in the printout produced when they click "Print List" on that tab so it has to show the actual current sort order.
This isn't even really that important but it's just driving me crazy because it makes no sense.
right now, I can't get past alert('#tblPatients').order[0][0].toString();
alerts cannot be chained
Sorry, I was just testing some stuff. That code is gone now.
Maybe you need to delegate the click event to a parent element. Maybe something like this:
To replace this:
Kevin
That's certainly not something I ever would have thought of, but I tried it and it never got executed either.
You might have hit a DataTables bug here.
The second table has
scrollY: false
. For some reason that is dropping DataTables into a rendering mode that displays the table suitable for scrolling.I'm not 100% certain that it is a bug since the documentation for
scrollY
doesn't say that it can be a booleanfalse
value that is given. However, it probably is a good idea to allow for that case - I'll make that change.In the mean time, remove
scrollY: false
(andscrollX: false
) and it should work as expected.Allan
Thank you so much! That fixed it. But why would rendering it in a way suitable for scrolling have any effect on the column header click event?
Because the table gets split into three different table elements in order to be able to display the scrolling display correctly. The original table (with the id attribute) is the scrolling table body. The header is a cloned table with the
thead
moved into it. There is, therefore, no way to click on something that would match the selector used.Its a pain that split process - it adds a lot of code to DataTables, but I've not found a better way to handle it yet.
Allan
So just for future reference, that means that in any table with scrolling enabled there's no way to get the current sort column index? Or is there another way to do it?
Sure - use the API:
order()
will tell you want the current sort condition is.Allan
Hmmm. This seems like a bug ...
The same problem occurs when either the scrollX = true or scrollY = true options are included.
See issue here ... clicking on header does not trigger index, which is what galcott experienced.
See working correctly here, commenting out scroll option.
This is a bit of an issue for me because I was using it to work around the current complex header and colReorder incompatibility.
c
The issue is that you are selecting elements using:
But when scrolling is enabled, the table has to be split into parts (header, body and footer), so the header is no longer inside the
#example
element. You can usetable().header()
to get thethead
element, regardless of if scrolling is enabled or not.Allan
OK, good. Thank you.
So, I can see the thead element via
table.table().header();
It's
[object HTMLTableSectionElement]
and in this case:
innerHTML gives:
<tr role="row"><th class="sorting_asc" tabindex="0" aria-controls="example" rowspan="1" colspan="1" style="width: 158px;" aria-sort="ascending" aria-label="Name: activate to sort column descending">Name</th><th class="sorting" tabindex="0" aria-controls="example" rowspan="1" colspan="1" style="width: 244px;" aria-label="Position: activate to sort column ascending">Position</th><th class="sorting" tabindex="0" aria-controls="example" rowspan="1" colspan="1" style="width: 112px;" aria-label="Office: activate to sort column ascending">Office</th><th class="sorting" tabindex="0" aria-controls="example" rowspan="1" colspan="1" style="width: 47px;" aria-label="Age: activate to sort column ascending">Age</th><th class="sorting" tabindex="0" aria-controls="example" rowspan="1" colspan="1" style="width: 109px;" aria-label="Start date: activate to sort column ascending">Start date</th><th class="sorting" tabindex="0" aria-controls="example" rowspan="1" colspan="1" style="width: 94px;" aria-label="Salary: activate to sort column ascending">Salary</th></tr>
But how do we get the column index of a particular cell in the header? Which was what started this thread.
In 2014 you wrote:
To get the column index when clicking in the header you could use:
$('#example').on( 'click', 'thead th', function () {
var index = table.column( this ).index();
} );
But that does not work when scrollX or scrollY is enabled. Instead of '#example' what element do we specify for onclick to work for 'thead th'?
c
See if this code works for you:
Kevin
Yes! Thank you kthorngren!
As does this basic jQuery (without the datatable function):
See working version with scroll here.
c
Worth noting that won't work as expected if you use column visibility, since the visible index won't match the data index. Kevin's approach is the one I would recommend.
Allan
Yes, thank you Allan. I understand. I've updated the working version with Kevin's approach here.
One more thing ...
I find colReorder will work with a special form of complex headers, where there is no colspan ... just say a double row header like <thead><tr></tr><tr></tr><thead>.
See working version here. The columns move correctly without throwing the errors we see when there is colspan, as seen here. I'm presuming that is because colReorder keys on the bottom row in this example.
But, can I get the column index on-click for the top row in the header? Using Kevin's approach, the index comes back correctly for the second (bottom) header row, but "undefined" in top row. See again here.
Trying to create a work-around for the current incompatibility between complex headers and colReorder.
c
I do find this generic code works:
Working demo here.
But wanted to do within dt if possible.
c
The code you have on your page appears to work for me, although I'd suggest you simply use the
table
variable rather than$('#example').DataTable()
.If it does, then its fluke. ColReorder is not designed for multiple row headers at the moment I'm afraid. Indeed, the DataTables API as a whole is a bit lacking in its support for multiple headers which is why you'd need a bit of a workaround, similar to what you have done, to make it work, since DataTables isn't really "aware" of the second row in the header.
Allan