Problem with Duplicate Change Events in DataTables After Copying a Record
Problem with Duplicate Change Events in DataTables After Copying a Record
Problem:
We have built a feature in DataTables that allows users to copy an existing record. This feature lets users edit only the required fields (approximately 20+ fields) assuming that the majority of the data remains the same. However, this requires the user to change at least 4 to 5 dropdown fields at a minimum on the "copied" record.
The copy function works fine, but after a successful copy, the dropdown change events are being triggered twice. This means each field that we change takes twice as long to process. You can imagine if there are 5 or 6 fields that require changes, this can take more than an acceptable amount of time.
Example Change Event Code:
Change Event 1: Selection of “entity” field triggering data fetching for “function” field
javascript
Copy code
$(document).on('change', '#DTE_Field_entity', function (e) {
var entity = $(this).val();
if (entity) {
clearErrorMessage('entity');
updateFunctionDropdown(entity);
}
});
Change Event 2: Selection of “function” field triggering other subsequent change events
javascript
Copy code
$(document).on('change', '#DTE_Field_function', function (e) {
var department = $(this).val();
if (department) {
clearErrorMessage('function');
updateFunctionalRoleDropdown(department);
updateOfficeLocationDropdown(department);
}
});
Copy Feature Code:
javascript
Copy code
editor.inlineCreate('start', {
cancelTrigger: 3,
cancelHtml: '<i class="fa fa-times"/>',
submitTrigger: 2,
submitHtml: '<i class="fa fa-floppy-o"/>'
});
var tr = $(this).closest("tr");
var row = table.row(`#${$(tr).attr("id")}`).data();
var fields = editor.displayed();
for (var i = 0; i < fields.length; i++) {
editor.field(fields[i]).val(row[fields[i]]);
}
Question:
Is there a way to prevent the change events from being triggered twice? Is there an alternative to the editor.inlineCreate function that might help avoid this issue?
Any guidance on the above would be greatly appreciated.
Edited by Kevin: Syntax highlighting. Details on how to highlight code using markdown can be found in this guide
Replies
Its difficult to understand your code structure with just the code snippets. I suspect that the
change
events are being created when calling the copy function. Move thechange
events outside the function so they execute only once. Or use jQuery off() to turn off the event before recreating it.If this doesn't help then please post a link to a test case replicating the issue so we can help debug.
https://datatables.net/manual/tech-notes/10#How-to-provide-a-test-case
Kevin
Thanks for the quick response. The change events are currently outside of the Copy function. We tried using jQuery.off()to remove the event handlers, but the problem still persists.
Just some additional information that we missed in the original post:
We are using the editor.inline function, which is working perfectly fine and only triggers the change event once. Here is the code for the editor.inline function:
However, the editor.inlineCreate function is triggering the change event twice. The code for "editor.inlineCreate" function is mentioned in the original message above.
Any guidance on how to prevent this double triggering issue would be greatly appreciated.
Edited by Kevin: Syntax highlighting. Details on how to highlight code using markdown can be found in this guide
I built a test case for you.
https://live.datatables.net/guwafemu/538/edit
Now I see what you mean regarding the events executing twice. @allan can comment on this. One option might be to use jQuery one() instead of jQuery on() and move the events inside the click event. Something like this:
https://live.datatables.net/subucaca/1/edit
Kevin
https://live.datatables.net/guwafemu/539/edit
I've added a check to see if
inlineCreate()
should be called or not. Previously it was being called when clicking into the text fields to create a new row, which was making text entry impossible.I'm also seeing the
change
event being triggered twice on the input elements. I'm not immediately sure why that would be happening.I'll look into that when I'm back in the office next week and let you know what I find.
Allan
Hello Allan/Kthorngren,
Unfortunately, the inlineCreate() method did not work. Below is our code:
The code below uses the editor.inlineCreate method to create the "new" record and subsequently copy the data within the "new" record:
Javascript Code:
There are two issues happening with the above code:
The "copy" record is created as the first row/record instead of "inserting" it right below the "parent" record (i.e., the record that it is copying). This is cumbersome for the user. For example, if the user is copying the 75th record, they have to drag the scroll all the way to the top to make edits/changes.
The "Input Events" and "Change Events" are triggering twice, resulting in 2x processing time.
We tried a different approach outlined below, but it did not work as well. Below is the summary of the approach:
Fetch the data from the clicked copy row
Add the record in the datatable
Trigger the editor.inline method
Below is the code for the above approach:
Our Observation from the above code
In the above approach, we expected that the "Cancel" for the "Copy" feature would work as "delete." However, it is working as "Cancel" when "editing" a record.
It appears that the above approach can work if we have a "click event" for the "Cancel" feature. This will allow us to write logic to delete the record from the datatable.
Below are the requirements from end-user perspective for the “Copy” feature:
Req# 1 (Works): When the user clicks Copy, create a duplicate record.
Req# 2 (Works): When the user clicks Copy and Saves without editing the record, a message box pops up stating “Record already exist”.
Req# 3 (Works): When the user clicks Copy, edits the data (in dropdown or input field) and saves the record, the record should successfully save.
Req# 4 (DOES NOT WORK): When the user clicks Copy and then "Cancel" the record with or without editing the record, the "Cancel" button for the "Copy" feature should work like the "Cancel" button of the "New" feature. However, it seems the "Cancel" click is not triggering.
Below is the javascript code for event triggering for cancel on copy.
We tried the above two approaches. Is there something we need to change in our approach, or is there any new approach to achieve the "Copy" functionality?
The inline creation row is a "ghost". It doesn't (yet) exist, and therefore it cannot take part in the filtering or ordering that is applied to the DataTable. Indeed, if you consider this example, when you click on "Create" and it shows the new row, it now has 11 rows on that page, rather than 10 as the pagination for the table suggests it should.
At the moment
inlineCreate()
has options only to show the new row at the start or the end of the table body. There is no option to show it next to an existing row. To be honest, this is the first time I've come across that requirement, and I think it is a good point. It does seem like a useful thing forinlineCreate()
to be able to do.I've added that to my list of things to add and I would hope to get that into Editor for the 2.4 release. A workaround would be to shuffle the DOM elements around after
inlineCreate()
has been called.I've yet to look into that. I'll report back once done.
Allan
Thanks, Allan!
We will try the workaround and report back with our findings. We appreciate you looking into the “triggering twice” issue.
Could you also please let us know your thoughts on our alternative approach mentioned above, where Requirement #4 is not working? Repasting the code below:
// Handle the click event on the cancel icon within the copied row
$('#<datatable id> span.cancel').click(function (e) {
e.stopPropagation(); // Prevent event bubbling
var tr = $(this).closest('tr');
var rowId = $(tr).attr("id");
if (rowId == copiedRowId) {
// Remove the row from the DataTable
table.row(
#${rowId}
).remove().draw();}
});
The positive aspect of the above code is that it resolves both the row positioning and “triggering twice” issues. It also meets Requirements # 1 to 3 mentioned above. However, it does not meet Requirement #4. If we can find a solution for Requirement #4, this approach could serve as a good workaround until you operationalize release 2.4.
has context menu
has context menu
Hi,
Been looking into this and indeed the
inlineCreate()
code is calling theset
action twice, which is what is causing thechange
event to happen twice. I've committed a fix for this which will be in the next release of Editor.If you'd like to hot fix the code, find:
and change to be:
Apologies, I'm having a hard time picturing this. This is referring to the
cancelTrigger
button that is setup byinlineCreate()
? When you click on the element / column specified bycancelTrigger
the inline create row should just disappear. Is that not what is happening? It does appear to work in this little example: https://live.datatables.net/guwafemu/543/edit (final column does a cancel.Thanks,
Allan
when will you release the above requirement?
With the next release of Editor. I'm not yet sure if that will be a patch or moving on to 2.4. I'll look at the changes and I think there is a good chance I'll do a patch release next week.
Allan