How do I prevent/manage my input event handler getting unbound when data changes?
How do I prevent/manage my input event handler getting unbound when data changes?
I am currently attempting to create a table in which certain cells are filled with input fields containing that cell's data. When a user triggers an input
event against this field, the data from the row's inputs should be collected and placed as the row's data.
Currently, this only works for the first time the user performs an input. Once the data of the row is set, the input
event listener is unbound. Attempting to rebind this event listener fails.
I am currently unable to obtain the Editor library due to red tape.
Table as rendered in HTML.
<table id="myTable">
<thead>
<tr>
<th scope="col"></th> <!--Empty for control buttons. -->
<th scope="col">Item Description.</th>
<th scope="col">Item Count</th>
<!--Item Id - not editable or visible-->
</tr>
</thead>
<tbody>
<tr>
<td>
<button class="remove-item-button">Remove Item</button>
</td>
<td>Motor Oil</td>
<td>5</td>
<td>9999</td>
</tr>
</tbody>
</table>
JavaScript to turn table into DataTable:
$(document).ready(function(){
$("#myTable").DataTable({
columnDefs: [
//Item Description
{
targets: 1,
className: "item-description-cell",
render: function(data, type, row, meta) {
var result = $(document.createElement('input'))
.on('input',function (e) {updateDescriptionData(e) })
.attr("value",data)
.prop('outerHTML');
return result;
}
},
//Item Count
{
targets: 2,
className: "item-count-cell",
render: function(data, type, row, meta) {
var result = $(document.createElement('input'))
.on('input',function (e) {updateCountData(e) })
.attr("value",data)
.prop('outerHTML');
return result;
}
},
//Item Id - Invisible.
{
targets: 3,
visible: false,
searchable: false
}
]
})
})
Functions to retrieve and set data:
function updateDescriptionData(e) {
let $table = $(e.currentTarget).closest("table").DataTable();
let $row = $table.row( $(e.currentTarget).closest("tr") );
//1. Get data for the current row.
let newData = $row.data();
//2. Update the element at index 1 - the item's description, with the value in the input field.
newData[1] = $(e.currentTarget).val();
//3. Put data back into the table.
// For some reason, doing so destroys the 'input' event listener on the input element.
$row.data(newData);
//4. Attempting to re-add the event listener does nothing.
$(e.currentTarget).on('input', function(e) { updateDescriptionData(e) });
}
//....Similar code for updateCountData cut for brevity...
So far I have attempted to re-up the event handler after setting the data, as you see above, and I have tried attaching the input
event handler as part of the render
option's result. Both have still resulted in the input handler disappearing. How do I prevent this handler from vanishing?
This question has an accepted answers - jump to answer
Answers
The
columns.render
function can run multiple times which will keep adding event handlers for the inputs each time it runs. Best practice is to use delegated events like this example. They only need created once.Kevin
I changed my code to remove the
.on()
function fromrender
, and instead place it after theDataTable
object was completed. No dice.The
input
event handler on my fields still vanishes after$row.data(newData);
is executed.Try:
That uses a delegated handler, like Kevin suggested.
Allan
Not sure what
$table
is but it does't seem like you set up the delegated events correctly. Maybe try something like this:``js
$('#example tbody").on('input', '.item-description-input', function (.....
```
See the jQuery delegated events tutorial for more info.
If you still need help please provide a simple test case we can take a look at to help debug.
https://datatables.net/manual/tech-notes/10#How-to-provide-a-test-case
Kevin
Thanks Allan. That seems to have...mostly fixed it. The input event handler is no longer vanishing, and data is getting set properly.
However, the
input
element is now losing focus after the user types a single character. Any ideas on how to prevent that?If
updateDescriptionData
is triggering a redraw of the table, then that would cause what you are seeing. The only way to address that would be to wait until the full data has been entered (perhaps a delay of 1000mS after input, or wait for a return key press).Allan