4

I am using Angular Datatables to show some tabular data. I have added an *ngIf condition to the table, so that it will not be visible until the data is loaded completely. The table code looks like the following :

<table class="table" id="releaseDatatable" datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger" *ngIf="!loading">

The loading variable I am setting from my component and then calling this.dtTrigger.next(). I have the following code to set loading.

set loading(loading: boolean) {
        this._loading = loading;
       setTimeout(()=>{
            this.dtTrigger.next();
       }, 100);
    }

Now for the first time, everything is working fine. But when I try to re-load the table (after edit or delete), it it is showing the following error :

ERROR ObjectUnsubscribedErrorImpl {message: "object unsubscribed", name: "ObjectUnsubscribedError"} 

and this.dtTrigger has null as observers. How this can be fixed ? I tried to re-render the table, but it is also not working.

Happy Coder
  • 4,255
  • 13
  • 75
  • 152

3 Answers3

4

You can use [ngClass] and hide rather than using ngIf

<table class="table" id="releaseDatatable" datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger" [ngClass]="loading">

in component make loading attribute as "hide" or "show";

in css hide it

.hide{
   display:none;
}

For render again I use destroy and and trigger next

import

  import { DataTableDirective } from 'angular-datatables';

  @ViewChild(DataTableDirective, {static: false})  
   datatableElement: DataTableDirective;

to render

rerender(){
        this.datatableElement.dtInstance.then((dtInstance: DataTables.Api) => {
            dtInstance.destroy();
            this.dtTrigger.next();
        });       
    }

call this rerender method

set loading(loading: boolean) {
       setTimeout(()=>{
            this.rerender();
       }, 100);
    }
mr. pc_coder
  • 16,412
  • 3
  • 32
  • 54
  • The `this` context is already captured by the arrow function, no need for `self` variable – Drenai Jul 17 '20 at 05:56
  • I think the issue is that `ngIf` removes the table from DOM and so for the second time, It is not able trigger the table reload. But no idea how to fix it. – Happy Coder Jul 17 '20 at 05:59
  • 1
    @HappyCoder yes you are right. You can use class rather than ngIf as a way . I update answer with this approach – mr. pc_coder Jul 17 '20 at 06:14
  • That also will not work. It is showing `DataTables warning: table id=releaseDatatable - Cannot reinitialise DataTable. For more information about this error, please see http://datatables.net/tn/3` – Happy Coder Jul 17 '20 at 06:18
  • This is rerender problem . I updated answer to rerender table . I firstly destroy then I trigger next @HappyCoder – mr. pc_coder Jul 17 '20 at 06:34
  • Unfortunately, it is also not working It shows `Cannot read property 'then' of undefined ` – Happy Coder Jul 17 '20 at 07:33
  • Did you import import { DataTableDirective } from 'angular-datatables'; in component – mr. pc_coder Jul 17 '20 at 07:35
  • Can you check this rerender https://l-lin.github.io/angular-datatables/#/advanced/rerender – mr. pc_coder Jul 17 '20 at 07:49
2

This is a known problem with how Angular Datatables re-renders

You can find more details and workarounds from the GitHub issues list e.g. https://github.com/l-lin/angular-datatables/issues/1241

Some of the comments suggest using [hidden] instead of *ngIf

Drenai
  • 11,315
  • 9
  • 48
  • 82
  • Any workaround ? I tried to use the `hidden` mentioned there, but it is showing error `DataTables warning: table id=releaseDatatable - Cannot reinitialise DataTable. For more information about this error, please see http://datatables.net/tn/3` – Happy Coder Jul 17 '20 at 06:15
  • Did you follow the docs link that the warning message provides? – Drenai Jul 17 '20 at 06:23
  • Yes. But don't have any idea how to fix this. – Happy Coder Jul 17 '20 at 07:58
  • 1
    That component library is using jQuery under the hood, thats partly the reason there's so many open issues and rendering problems (it doesn't follow Angular component lifecycle in the recommended manner). Have you considered `ag-grid` as an alternative - if you're not already heavily invested in this one that is – Drenai Jul 17 '20 at 08:03
0

It's better to add a wrapper div for your table like <div *ngIf="!loading"><table></table></div>

Angular v2 doesn't support more than one structural directive on the same element.

Miqdad Ali
  • 6,129
  • 7
  • 31
  • 50