9

I am working on the angular based project. I am using datatables to display data. When I try to do some modifications on the table, I get the following error.

DataTables warning: table id=DataTables_Table_0 - Cannot reinitialise DataTable. For more information about this error, please see http://datatables.net/tn/3

8 Answers 8

14

I think it is because you are using [dtTrigger]="dtTrigger" in Angular DataTables and rerendering the table on the same page. If you have this problem you should use the following trick to handle dtTrigger

<table datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger" class="table">

Make sure you do not use this.dtTrigger.next() on ngOnInit()

ngAfterViewInit(): void {
    this.dtTrigger.next();
}

Rerender it when you use the second time

rerender(): void {
  this.dtElement.dtInstance.then((dtInstance: DataTables.Api) => {
     dtInstance.destroy();
     this.dtTrigger.next();     
  });
}
Sign up to request clarification or add additional context in comments.

6 Comments

Yes, This solution is working. For more info visit this link l-lin.github.io/angular-datatables/#/advanced/rerender
The destroy causes the table to flicker. It is making me crazy to get this to work angular way
@ppumkin yeah. the flicker is annoying. it is because you are using [dtTrigger]="dtTrigger" Why is this the problem?
The problem is unfortunately data tables it self. Destroy literally removes the DOM and the browser garbage collects, then DT redraws from fresh. (This causes the flicker and I have not found an elegant [emphasis on elegant - I found a few hacky ways and I hated it] solution to bypass this) I have since moved on to Material and using their DataTable.. Much easier to work with in Angular 6 to be honest. I think Datatables is falling behind which is a shame because I loved it so much.
@PiotrKula I'm stuck angular-datatables and the destroy method, the flickering is terrible, would you mind sharing the hacks you used?
|
4

I solved this problem by removing the following code in *.ts file:

dtOptions: DataTables.Settings = {};
 this.dtOptions = {
};

3 Comments

How did you make it work by removing those lines? Mine still does it
@Code Lover: Not working with your solution. Could you share some snippet?
how it is supposed to work after removing those lines? These are the main config, isn't it? Please share some code
1

I am using DataTable in Angular7 and Bootstrap4

Step1: Install the package

npm i angular-datatables@6 [email protected] [email protected] --save

Step2: In angular.json

"styles": [ "./node_modules/datatables.net-dt/css/jquery.dataTables.css" ], "scripts": [ "node_modules/datatables.net/js/jquery.dataTables.js" ],

Step3: Inside app.module.ts

import { DataTablesModule } from 'angular-datatables';
imports: [
    .......
    DataTablesModule
]

Step4: Inside html

<table datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger" >...</table>

Step5: Inside ts

import { Component, OnInit, AfterViewInit, OnDestroy, ViewChild  } from '@angular/core';
declare var jQuery:any;
import { DataTableDirective } from 'angular-datatables';
import { Subject } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { environment } from '../../environments/environment';


export class YourComponent implements OnInit, AfterViewInit, OnDestroy {
    @ViewChild(DataTableDirective) dtElement: DataTableDirective;
    dtOptions: DataTables.Settings = {};
    dtTrigger: Subject<any> = new Subject();
    ajxrequrl: string = environment.hostUrl + '/api/userList'; 
    start: number = 0; length: number = 10; draw: number = 1;
    postparams = {};

    constructor( private _http: HttpClient ) { }

    getListData(filterData, t) {
        //console.log(filterData);
        var zone = (filterData.zone != undefined ) ? filterData.zone : 0 ;
        var state = (filterData.state != undefined ) ? filterData.state : 0 ;
        var studentType = (filterData.studentType != undefined ) ? filterData.studentType : 0 ;
        var status = (filterData.status != undefined ) ? filterData.status : 0 ;
        var grade = (filterData.grade != undefined ) ? filterData.grade : 0 ;
        var startDate = (filterData.startDate != undefined ) ? filterData.startDate : 0 ;
        var endDate = (filterData.endDate != undefined ) ? filterData.endDate : 0 ;

        const that = this;
        this.dtOptions = {
            pagingType: 'full_numbers',
            pageLength: this.length,
            displayStart: this.start,
            autoWidth: false,
            serverSide: true,
            processing: true,
            searching: true,
            order: [],
            columnDefs: [ {
                'targets': [0], /* column index [0,1,2,3]*/
                'orderable': false, /* true or false */
            }],

            ajax: (dataTablesParameters: any, callback) => {
                var orderColumn = ''; var orderBy = ''; var order = 0;
                if(dataTablesParameters.order.length) {
                    var sortarr = ['classId', 'full_name', 'age', 'status', 'grade',  'zone', 'state', 'type', ... <all columns>];
                    orderColumn = sortarr[dataTablesParameters.order[0].column]; 
                    orderBy = dataTablesParameters.order[0].dir;
                    order = 1;
                }   

                /* Sending data through GET */
                /* 
                that.getparams = "?start="+dataTablesParameters.start
                +"&length="+dataTablesParameters.length
                +"&order="+order
                +"&orderColumn="+orderColumn
                +"&orderBy="+orderBy
                +"&zone="+zone
                +"&state="+state
                +"&studentType="+studentType
                +"&status="+status
                +"&grade="+grade
                +"&startDate="+startDate
                +"&endDate="+endDate;
                //+"&search="+encodeURI(dataTablesParameters.search.value);

                that._http.get(that.ajxrequrl + that.getparams, {}).subscribe(resp => {
                */

                /* Sending data through POST */
                that.postparams = {
                    start: dataTablesParameters.start, 
                    length: dataTablesParameters.length, 
                    order: order, 
                    orderColumn: orderColumn, 
                    orderBy: orderBy, 
                    search: dataTablesParameters.search,
                    //filterData: filterData
                    zone: zone,
                    state: state,
                    studentType: studentType,
                    status: status,
                    grade: grade,
                    startDate: startDate,
                    endDate: endDate
                };

                //jQuery('.dataTables_filter label input').attr("placeholder", "CL Contract ID or Customer Name or Case No");
                //jQuery('.dataTables_filter label input').css({'width': '350px', 'display': 'inline-block'});

                this._http.post( that.ajxrequrl, that.postparams, {} ).subscribe(
                    resp => {
                        that.listData = resp['data'];
                        that.start = resp['start'];
                        callback({
                            recordsTotal: resp['recordsTotal'],
                            recordsFiltered: resp['recordsFiltered'],
                            data: []
                        });
                    }, 
                    error => {
                        console.log(error);
                    }   
                );
            }
        };

        if(t == 1) {        
            this._othercaseService.filterList(filterData).subscribe(
            (resp) => {
                this.rerender();
                this.listData = resp['data'];
                if(resp['status'] == 0) {
                    //this.resetForm();
                }
            });
        }
    }

    ngOnDestroy(): void {
        // Do not forget to unsubscribe the event
        this.dtTrigger.unsubscribe();
    }

    rerender(): void {
        this.dtElement.dtInstance.then((dtInstance: DataTables.Api) => {
            // Destroy the table first
            dtInstance.destroy();
            // Call the dtTrigger to rerender again
            this.dtTrigger.next();
        });
    }   

    ngAfterViewInit() {
        this.dtTrigger.next();

        this.dtElement.dtInstance.then((dtInstance: DataTables.Api) => {
            dtInstance.on( 'draw.dt', function () {
                if(jQuery('.dataTables_empty').length > 0) {
                    jQuery('.dataTables_empty').remove();
                }
            });
        });
    }

    onSubmit(formData: NgForm) { // This function is called after a filter form searched
        this.getListData(formData, 1);
    }

    resetForm(pageStart: number = 1) {
        if(!pageStart) this.start = 0;
    }

    deleteUser(pkId) {
        /* After Delete code */
        this.getListData({}, 0);
    }
}

Step6: Inside your controller api call

module.exports.userList = (req, res, next) => {
    let reqData = req.body;

    var sql = 'SELECT .... FROM ....';
    /* ----- started changes for filter (just example)----- */
    sql = (reqData.grade) ? sql + ' AND grade = "' + reqData.grade + '"' : sql;
    sql = (reqData.status) ? sql + ' AND status = "' + reqData.status + '"' : sql;
    ............    

    /* ----- end of changes for filter ----- */


    /* ----- started changes for pagination ----- */

    sql = (!reqData.orderColumn || !reqData.orderBy) ? sql + ' ORDER BY pkId DESC' : sql+ ' ORDER BY ' + reqData.orderColumn + ' ' + reqData.orderBy;

    var start = (reqData.start) ? reqData.start : 0;
    var length = (reqData.length) ? reqData.length : 10;

    /* ----- end of changes for pagination ----- */



    mysql.conn.query(sql, (err, rows) => {
        if(err) {
            res.json({'status': 1, 'data': [], 'message': 'No result found'});
        }
        var len = rows.length;
        if(len) {
            sql += ' LIMIT ' + start + ',' + length;
            mysql.conn.query(sql, (err, rows1) => {
                if (!err) {
                    res.json({'status': 0, 'data': rows1, 'recordsTotal': len, 'recordsFiltered': len, 'start': start, 'draw': 1});
                } else {
                    res.json({'status': 1, 'data': [], 'message': 'No result found'});
                }
            });
        } else res.json({'status': 1, 'data': [], 'message': 'No result found'});
    });
}

Comments

0

I have tried this in angular 7 and it worked.. runtime datatable changed

.Ts file

    import { Component, AfterViewInit, OnDestroy, OnInit, ViewChild } from '@angular/core';
    import { DataTableDirective } from 'angular-datatables';
    
    @Component({
      selector: 'app-selector',
      templateUrl: 'app-selector.component.html'
    })
    export class CustomRangeSearchComponent implements AfterViewInit, OnDestroy, OnInit {
      @ViewChild(DataTableDirective, {static: false})
      datatableElement: DataTableDirective;
      dtOptions: DataTables.Settings = {};
      tableData = [];
    
      ngOnInit(): void {
        this.dtOptions = {
          destroy: true,
          ordering: true,
          pagelength: 10,
          pagingType: "full_numbers",
          columnDefs: [{ 
            targets: 0,
            checkboxes:{
            selectRow: true,
            selected: true
          }]
        };
      }
    
      ngOnDestroy(): void {
        $.fn['dataTable'].ext.search.pop();
      }

      ngAfterViewInit(): void {
        this.dtTrigger.next();
      }
    
      getdata(){
    
        //... get your response
        this.tableData = response; //this should be in array

        setTimeout(() => {
          this.datatableElement.dtInstance.then((dtInstance: DataTables.Api) => {
            dtInstance.draw();
          });
        });
      }
    }

.HTML file

<button class="btn btn-primary" (click)="getData()">Filter by ID</button>
<table datatable [dtOptions]="dtOptions" class="row-border hover"></table>

Comments

0

i have removed this below function and it worked for me. please follow below steps

  1. in you angular project go to this location 'node_modules\datatables.net\js'.
  2. there you can see one js file called 'jquery.datatable.js' file.

enter image description here

  1. open file and search term '_fnLog' . the _fnLog is a function.
  2. just comment _fnLog function whole code and save your file. your issue will be solved. enter image description here

Comments

0

I had a similar issue and the only thing I needed to add is:

  ngAfterViewInit() {
    this.dtTrigger.next();
  }

As in the constructor I had:

this.options = {
  multiple: true,
};

In the Html declaration:

<table aria-describedby="Some interesting description" datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger"
<tbody>
<tr *ngFor="let item of data">
 <td>{{ item }}</td>
</tr>
</tbody> 
</table>

In the method that will get the data:

  someDataMethod(): void {
     this.dataAjaxService.someMethod(id).subscribe((data: any) => {
        this.data = data;
      }, error => {
        //handle error
      });
 }

Comments

0

It' Easy.

onDestroy(){
  this.dtElements.forEach((dtElement: DataTableDirective,index:number) => {
    dtElement.dtInstance.then((dtInstance: any) => {       
        dtInstance.destroy();  // Before destroy
        this.dtTrigger.next(); // Again trigger of method. 
               });
    });
}

dtOptions:

this.dtOptions["new"] = {
      paging: true,
      fixedColumns: true,
      order: [[1, "asc"]],
      autoWidth: true,
      language: {
        "url": "assets/json/Turkish.json"
      },
      select: false,
      responsive: true,
      pagingType: 'full_numbers',
      pageLength: 10, 
      retrieve:true, **This is important**                                };

HTML

<table datatable [dtOptions]="dtOptions['new']" [dtTrigger]="dtTrigger" class="row-border hover fixed_header"
              style="width:100%">
<table datatable [dtOptions]="dtOptions['new']" [dtTrigger]="dtTrigger2" class="row-border hover fixed_header"
              style="width:100%">

The biggest battle is the war against ignorance.!

Comments

0

Give id (id="my-table-id") to table tag in html. Like below

HTML

<table  id="my-table-id" class="table table-hover table-sm" datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger">

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.