Datatables really destroy?
Datatables really destroy?

This is more of a question but does datatables really destroy? Why doesn't destroy return the table to it's original state?
Example:
Original State:
<able class="table table-striped listsTbl width100Percent" id="recentsTbl" style="width:100%">
<thead>
<tr>
<th>Part #</th>
<th>Description</th>
<th>Stock</th>
<th>Price</th>
<th>UOM</th>
<th>Qty</th>
<th>Add to<br>Cart</th>
</tr>
</thead>
<tbody>
<tr>
<td class="col-xs-2"><a class="color-rust au-target" click.delegate="sendToDetails(recentItem.inv_mast_uid, recentItem.item_id, recentItem.display_desc, recentItem, $index, 'Recent')" href.bind="recentItem.itemURL" au-target-id="889">GL SSU</a></td>
<td class="col-xs-3">Box CVR w/Switch</td>
<td class="textAlignCenter col-xs-2"><a class="color-rust au-target" click.delegate="buildContent(recentItem, recentItem.inv_mast_uid, 'Recent')" mouseover.delegate="buildContent(recentItem, recentItem.inv_mast_uid, 'Recent') & debounce:600" mouseenter.trigger="recentItem.hasMouse=true" mouseleave.trigger="recentItem.hasMouse=false" show.bind="recentItem.stock_status" data-toggle="popover" data-trigger="manual" au-target-id="892" id="itemPopoverRecent1655743" title="Stock Status for GL SSU">In Stock <span class="fa fa-stack"><i class="fa fa-circle fa-stack-1x fa-lg"></i><i class="fa fa-info fa-stack-1x color-wht"></i></span></a></td>
<td class="textAlignCenter">
<!--anchor--><span show.bind="showPricing" class="au-target" au-target-id="895"><span textcontent.bind="'$'" class="au-target" au-target-id="896">$</span><span class="shownPrice">0</span><br show.bind="recentItem.bulkPricingFlag == 'Y'" class="au-target aurelia-hide" au-target-id="898"><a class="color-rust au-target aurelia-hide" click.delegate="buildContentBulkPricing(recentItem, recentItem.inv_mast_uid, 'click', 'Recent')" mouseover.delegate="buildContentBulkPricing(recentItem, recentItem.inv_mast_uid, 'mouseover','Recent') & debounce:600" mouseenter.trigger="recentItem.hasMouseBulk=true" mouseout.delegate="closePopoverBulkPricing(recentItem.inv_mast_uid, 'Recent')" mouseleave.trigger="recentItem.hasMouseBulk=false" show.bind="recentItem.bulkPricingFlag == 'Y'" data-toggle="popover" data-trigger="manual" href="#" au-target-id="899" id="itemPopoverBulkPricingRecent1655743" title="Bulk Pricing for GL SSU">Bulk Discount <img show.bind="recentItem.hasMouseBulk==false||recentItem.hasMouseBulk==undefined" alt="Bulk Discount" class="img height20px au-target" au-target-id="900" src="./assets/slakey/global/images/icons/bulkPrice.svg"><img show.bind="recentItem.hasMouseBulk==true" alt="Bulk Discount" class="img height20px au-target aurelia-hide" au-target-id="901" src="./assets/slakey/global/images/icons/bulkPriceHover.svg"></a></span>
</td>
<td class="textAlignCenter col-xs-1">EA</td>
<td class="textAlignCenter"><input type="text" class="form-control displayInline width60 textAlignCenter au-target" change.delegate="orderQtyChanged(recentItem)" value.bind="recentItem.order_qty" onclick="this.focus(),this.select()" au-target-id="903"></td>
<td class="textAlignCenter col-xs-1" id="lastRecent">
<div class="checkbox"><input type="checkbox" class="input-group with-font au-target" model.bind="recentItem" checked.bind="recentItem.checked" change.delegate="setQuantity(recents[$index])" au-target-id="904" id="recent0"><label class="au-target" au-target-id="905" for="recent0"> </label></div>
<promise-resolver resolve.bind="lastItemRenderedRecent" class="au-target" au-target-id="906"></promise-resolver>
<!--anchor-->
</td>
</tr>
<!--anchor-->
</tbody>
</table>
After Destroy:
<table class="table table-striped listsTbl width100Percent" id="recentsTbl" style="width: 100%;" aria-describedby="recentsTbl_info">
<thead>
<tr role="row">
<th data-dt-column="0" class="dt-head-center" rowspan="1" colspan="1" aria-label="Part #: Activate to sort" tabindex="0"><span class="dt-column-title" role="button">Part #</span><span class="dt-column-order"></span></th>
<th data-dt-column="1" class="dt-head-center" rowspan="1" colspan="1" aria-label="Description: Activate to sort" tabindex="0"><span class="dt-column-title" role="button">Description</span><span class="dt-column-order"></span></th>
<th data-dt-column="2" class="dt-head-center" rowspan="1" colspan="1" aria-label="Stock: Activate to sort" tabindex="0"><span class="dt-column-title" role="button">Stock</span><span class="dt-column-order"></span></th>
<th data-dt-column="3" class="dt-head-center" rowspan="1" colspan="1" aria-label="Price: Activate to sort" tabindex="0"><span class="dt-column-title" role="button">Price</span><span class="dt-column-order"></span></th>
<th data-dt-column="4" class="dt-head-center" rowspan="1" colspan="1" aria-label="UOM: Activate to sort" tabindex="0"><span class="dt-column-title" role="button">UOM</span><span class="dt-column-order"></span></th>
<th data-dt-column="5" class="dt-head-center dt-orderable-none" rowspan="1" colspan="1" aria-label="Qty"><span class="dt-column-title">Qty</span><span class="dt-column-order"></span></th>
<th data-dt-column="6" class="dt-head-center dt-orderable-none" rowspan="1" colspan="1" aria-label="Add toCart"><span class="dt-column-title">Add to<br>Cart</span><span class="dt-column-order"></span></th>
</tr>
</thead>
<tbody>
<tr>
<td class="col-xs-2 dt-head-center"><a class="color-rust au-target" click.delegate="sendToDetails(recentItem.inv_mast_uid, recentItem.item_id, recentItem.display_desc, recentItem, $index, 'Recent')" href.bind="recentItem.itemURL" au-target-id="889">GL SSU</a></td>
<td class="col-xs-3 dt-head-center">Box CVR w/Switch</td>
<td class="textAlignCenter col-xs-2 dt-head-center"><a class="color-rust au-target" click.delegate="buildContent(recentItem, recentItem.inv_mast_uid, 'Recent')" mouseover.delegate="buildContent(recentItem, recentItem.inv_mast_uid, 'Recent') & debounce:600" mouseenter.trigger="recentItem.hasMouse=true" mouseleave.trigger="recentItem.hasMouse=false" show.bind="recentItem.stock_status" data-toggle="popover" data-trigger="manual" au-target-id="892" id="itemPopoverRecent1655743" title="Stock Status for GL SSU">In Stock <span class="fa fa-stack"><i class="fa fa-circle fa-stack-1x fa-lg"></i><i class="fa fa-info fa-stack-1x color-wht"></i></span></a></td>
<td class="textAlignCenter dt-head-center">
<!--anchor--><span show.bind="showPricing" class="au-target" au-target-id="895"><span textcontent.bind="'$'" class="au-target" au-target-id="896">$</span><span class="shownPrice">0</span><br show.bind="recentItem.bulkPricingFlag == 'Y'" class="au-target aurelia-hide" au-target-id="898"><a class="color-rust au-target aurelia-hide" click.delegate="buildContentBulkPricing(recentItem, recentItem.inv_mast_uid, 'click', 'Recent')" mouseover.delegate="buildContentBulkPricing(recentItem, recentItem.inv_mast_uid, 'mouseover','Recent') & debounce:600" mouseenter.trigger="recentItem.hasMouseBulk=true" mouseout.delegate="closePopoverBulkPricing(recentItem.inv_mast_uid, 'Recent')" mouseleave.trigger="recentItem.hasMouseBulk=false" show.bind="recentItem.bulkPricingFlag == 'Y'" data-toggle="popover" data-trigger="manual" href="#" au-target-id="899" id="itemPopoverBulkPricingRecent1655743" title="Bulk Pricing for GL SSU">Bulk Discount <img show.bind="recentItem.hasMouseBulk==false||recentItem.hasMouseBulk==undefined" alt="Bulk Discount" class="img height20px au-target" au-target-id="900" src="./assets/slakey/global/images/icons/bulkPrice.svg"><img show.bind="recentItem.hasMouseBulk==true" alt="Bulk Discount" class="img height20px au-target aurelia-hide" au-target-id="901" src="./assets/slakey/global/images/icons/bulkPriceHover.svg"></a></span>
</td>
<td class="textAlignCenter col-xs-1 dt-head-center">EA</td>
<td class="textAlignCenter dt-head-center"><input type="text" class="form-control displayInline width60 textAlignCenter au-target" change.delegate="orderQtyChanged(recentItem)" value.bind="recentItem.order_qty" onclick="this.focus(),this.select()" au-target-id="903"></td>
<td class="textAlignCenter col-xs-1 dt-head-center" id="lastRecent">
<div class="checkbox"><input type="checkbox" class="input-group with-font au-target" model.bind="recentItem" checked.bind="recentItem.checked" change.delegate="setQuantity(recents[$index])" au-target-id="904" id="recent0"><label class="au-target" au-target-id="905" for="recent0"> </label></div>
<promise-resolver resolve.bind="lastItemRenderedRecent" class="au-target" au-target-id="906"></promise-resolver>
<!--anchor-->
</td>
</tr>
</tbody>
<tfoot></tfoot>
</table>
Link to test case:
Debugger code (debug.datatables.net):
Error messages shown:
Description of problem:
Edited by Kevin: Syntax highlighting. Details on how to highlight code using markdown can be found in this guide
This question has an accepted answers - jump to answer
Answers
The reason I ask this is because it appears if you init a datable, destroy it, dynamically change the body data, then reinit the table Aurelia thinks datatables still has a grasp on the table so it throws the "Uncaught TypeError: Cannot read properties of null (reading 'insertBefore')" which is from the repeat.for but I wouldn't say it's Aurelia's issue it just doesn't seem to play well with datatables if you have dynamic tbody data. I have tried cloning the original table and and putting it back after a destroy(true) but couldn't get it to function properly.
It does destroy the table, but it doesn't remove all the attributes / classes that were added to the DataTable. It does remove all event handlers, table controls and the like.
Aurelia isn't something I've played with, I don't know how it is trying to interact and control the DOM I'm afraid. I would say that if you have two things trying to control the table body, then that is always going to end badly.
Possibly a test case showing the issue might enable me to offer some more help, but as I say, I don't know Aurelia.
Allan
Posting back on this one as well because this solution below got me passed my issues.
I was getting the same error message even though I was using if.bind on the custom view leading to the same issue that I started with. My resolution was to use enhance from the templatingEngine. So what I did was create a few custom elements and dynamically add them to the DOM then use templatingEngine to enhance them which basically triggers binding and some lifecycle functions in Aurelia. Below is an example of a custom element named invoice-view.
This would allow me to trigger datatables on attached. When I was done with it I just used Jquery to remove it or call a detached function on the custom element and remove it there. This allowed everything to work for me. One thing that I missed in the documentation is that though Aurelia allows you to create custom elements and use the @customElement you still need to declare your custom element globally to use templatingEngine.enhance.
From the Aurelia docs:
Registering Resources for Enhanced Content
When enhancing content that uses custom elements, attributes, value converters, or binding behaviors, you need to ensure that these resources are registered with Aurelia. The enhanced content will not recognize them if they are not registered globally, leading to binding errors or unexpected behavior.
@allan, the documentation for
destroy()
indicates that it will "Restore the tables in the current context to its original state in the DOM by removing all of DataTables enhancements, alterations to the DOM structure of the table and event listeners." I can easily understand why this question was posed, as I was in the process of posing it before I searched fordestroy()
. Perhaps the documentation can provide some more nuance about whatdestroy()
actually does?Thanks for your time.
Thanks for your comment on this. It prompted me to go back and look at the output above, and apologies for having missed it, I see that there is extra markup that is being left - the header sorting and title
span
elements for example.I've committed a change to fix that, and also to remove some of the other attributes and classes that are added and should be removed (I hadn't updated
destroy()
for some of the more recent changes).Allan
@allan thank you!