Hello to all friends.
I use datatables searchbuilder in my project.
In searchbuilder, after selecting the field that is the date type, a datepicker is displayed. But event clicking on the date and time buttons of the datepicker will not fire.
I'm sure the selector I chose is correct. Because with this selector I can change the buttons in the css background color. But with the same selector, the jquery event click is not fired.
How can I know why this happened?
Part of Dom:
...
...
<td class="selectable">
<button class="dt-datetime-button" type="button">
<span>23</span>
</button>
</td>
...
...
None of the following events will be fired:
$('td.selectable').on('click', function () {
console.log(1);
});
$('td.selectable').click(function () {
console.log(2);
});
$(document).on('click', 'td.selectable', function () {
console.log(3);
});
$(document).click('td.selectable', function () {
console.log(4);
});
Of course, none of the above events work for all three possible selectors. That means the following three selectors:
'td.selectable'
'td.selectable button.dt-datetime-button'
'td.selectable button.dt-datetime-button span'
With these selectors I can change the background-color. But jquery events do not fire!!
td.selectable {
background-color: red;
}
Is it possible that the datatables searchbuilder library itself forcibly disables my events? If so, how can I be sure? How can I prevent my events from being disabled?
If the problem is from somewhere else, thank you for guiding me.
thanks a lot.
The reason is that your <td> datepicker's elements are inserted into the DOM only when the datepicker is actually displayed (and indeed the same happens for the whole datepicker's calendar table and the input element as well).
When the datepicker is closed, the whole calendar table - along with its <td> elements - is removed from the DOM (together with their possible event listeners).
So, you need to attach the listeners every time the datepicker is displayed, and only AFTER it's visible. Otherwise, no event listener will be attached.
I'd suggest, in cases like this, to use the event delegation pattern to bind the listener to the parent element and check the actual target that triggered the event.
Look at this snippet where I attach a 'mouseup' event to the parent .dtsb-searchBuilder container:
const data = [
{date: "2021-10-06", name: "Thomas", position: "Developer"},
{date: "2020-05-03", name: "James", position: "IT Manager"},
{date: "2018-03-19", name: "Barney", position: "CEO"},
{date: "2020-04-22", name: "Thomas", position: "Junior Developer"}
];
$(function() {
$('#myTable').DataTable({
data: data,
columns: [
{data: "date", title: "Date"},
{data: "name", title:"Name"},
{data: "position", title:"Position"},
],
autoWidth: false,
searchBuilder: {
// configutation
},
dom: 'Qfrtip'
})
// attach event listener to parent element (event delegation)
$('.dtsb-searchBuilder').on('mouseup', function(event) {
const parentIdentifier = event.target.closest('td.selectable'); // identify closest td.selectable
if(parentIdentifier) {
console.log(`You clicked on this day: ${parentIdentifier.innerText}`);
}
})
})
body {
width: 80%;
margin: auto
}
#myTable td {
text-align: center
}
<script src="https://cdn.datatables.net/v/dt/jq-3.6.0/dt-1.11.5/date-1.1.2/sb-1.3.2/datatables.js"></script>
<link href="https://cdn.datatables.net/v/dt/jq-3.6.0/dt-1.11.5/date-1.1.2/sb-1.3.2/datatables.min.css" rel="stylesheet"/>
<table id='myTable'>
<thead></thead>
<tbody></tbody>
</table>
You are using an td element outside a table So the browser removes that element from the DOM. Use some other tag like div and it will work.
$('div.selectable').on('click', function() {
console.log(1);
});
$('div.selectable').click(function() {
console.log(2);
});
$(document).on('click', 'div.selectable', function() {
console.log(3);
});
$(document).click('div.selectable', function() {
console.log(4);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="selectable">
<button class="dt-datetime-button" type="button">
<span>23</span>
</button>
</div>