2

I have a Angular application with a simple CRUD functionality. I have tested my data with a static HTML table and this works. Now I am using a data table framework called Angular data table.

Link: https://l-lin.github.io/angular-datatables/#/welcome

I can Create, Read and Delete a record but after this action I get a error like:

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

I have tried several solutions like the link it provided and other stack overflows post like this:

Getting error in Angular 5 Datatables: cannot reinitialise DataTable

https://l-lin.github.io/angular-datatables/#/basic/angular-way

https://l-lin.github.io/angular-datatables/#/advanced/rerender

This is my code in car-component.js and I use a car-services.js for all my HTTP calls.

import { Component, OnInit } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { CarService } from '../services/carservices/car.service';
import { CarVM } from '../viewmodels/car/car-vm';
import { Subject } from 'rxjs';
import { DataTableDirective } from 'angular-datatables';

@Component({
  selector: 'app-car',
  templateUrl: './car.component.html',
  styleUrls: ['./car.component.css']
})
export class CarComponent implements OnInit {

  FormCar: any;
  countrecords: any;
  Carid: number = 0;
  dtTrigger: Subject<any> = new Subject();
  dtElement: DataTableDirective;
  allCars: CarVM[];
  dtOptions: DataTables.Settings = {};

  constructor(private formbuilder: FormBuilder, private carservice: CarService) { }

  ngOnInit() {

    this.dtOptions = {
      pagingType: 'full_numbers',
      pageLength: 5,
    };

    this.GetCar();
    this.GetCarCount();

    this.FormCar = this.formbuilder.group({
      CarId: ['', Validators.required],
      Brand: ['', Validators.required],
      Model: ['', Validators.required],
      Color: ['', Validators.required],
      TopSpeed: ['', Validators.required],
    });
  }

  AddCar(CarVM: CarVM) {
    CarVM.CarId = this.Carid;
    this.carservice.CreateCar(CarVM).subscribe(() => {
      this.GetCar();
      this.GetCarCount();
      this.Reset();
      this.Carid = 0;
    })
  }

  GetCar() {
    this.carservice.getAllCars().subscribe(res => {
      this.allCars = res;
      this.dtTrigger.next();
    })
  }

  GetCarCount() {
    this.countrecords = this.carservice.getCount();
  }

  EditCar(car: CarVM) {
    this.carservice.updateCar(car).subscribe(Response => {
      this.Carid = Response.CarId;
      this.FormCar.controls['Brand'].setValue(Response.Brand);
      this.FormCar.controls['Model'].setValue(Response.Model);
      this.FormCar.controls['Color'].setValue(Response.Color);
      this.FormCar.controls['TopSpeed'].setValue(Response.TopSpeed);
    })
  }

  DeleteCar(CarId: string) {
    if (confirm("Are you sure?")) {
      this.carservice.deleteCar(CarId).subscribe(() => {
        this.GetCar();
        this.GetCarCount();
      })
    }
  }

  Reset() {
    this.FormCar.reset();
  }
}

And this is my HTML page from car:

<table datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger" class="row-border hover">
  <thead>
    <tr>
      <th>Id</th>
      <th>Brand</th>
      <th>Model</th>
      <th>Color</th>
      <th>Speed</th>
      <th>Action</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let car of allCars">
      <td>{{car.carId}}</td>
      <td>{{car.brand}}</td>
      <td>{{car.model}}</td>
      <td>{{car.color}}</td>
      <td>{{car.topSpeed }}</td>
      <td>
        <button type="button" class="btn btn-danger mr-1" (click)="DeleteCar(car.carId)">Delete</button>
      </td>
    </tr>
  </tbody>
</table>

NOTE:

I used the Angular version not the JQuery version!

Can someone point me in the right direction?

3 Answers 3

5

You need to destroy datatable instance before triggering it again.

You can create a function like this:

import { DataTableDirective } from 'angular-datatables';

dtElement: DataTableDirective;

isDtInitialized:boolean = false

  GetCar() {
    this.carservice.getAllCars().subscribe(res => {
      this.allCars = res;

      if (this.isDtInitialized) {
        this.dtElement.dtInstance.then((dtInstance: DataTables.Api) => {
          dtInstance.destroy();
          this.dtTrigger.next();
        });
      } else {
        this.isDtInitialized = true
        this.dtTrigger.next();
      }
    })
  }

Using this, for the first time it will go to the else block and trigger datatable directly. After that when you refresh, it will first destroy the datatable and then trigger.

Sign up to request clarification or add additional context in comments.

18 Comments

Thanks for you time! Do I need to call this function in my constructor?
Edited the answer, do it in getCar()
I initialized the Boolean variable and used your method. Then I call it on the ngOnInit() this.getCar(); when I refresh I get the same error instantly. After I click okay my data is loading.
Please show your function in the comment, or better if you can create a stackbiltz. I had faced the same thing and fixed it by destroying dtInstance
delete the line ` this.dtTrigger.next();` after the line ` this.allCars = res;`, the 3rd line in GetCar()
|
4

The above answer @Adrita Sharma was not working for me, it was throwing this error.

core.js:9110 ERROR TypeError: Cannot read property 'dtInstance' of undefined

So I added

@ViewChild(DataTableDirective, {static: false})

and it worked

import { Component, ViewChild, OnInit } from '@angular/core';
import { DataTableDirective } from 'angular-datatables';

export class AttendancePage implements OnInit {

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

isDtInitialized:boolean = false;

And inside function where i initialized my datatable

if (this.isDtInitialized) {
    this.dtElement.dtInstance.then((dtInstance: DataTables.Api) => {
        dtInstance.destroy();
        this.dtTrigger.next();
    });
} else {
    this.isDtInitialized = true;
    this.dtTrigger.next();
}

Comments

0

HTML

<div class="table-responsive">
                                            <table datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger" 
                                                style="width: 99.5% !important;" class="table table-responsive-sm table-bordered table-striped table-sm">
                                            <thead>
                                                <tr>
                                                <th>Client ID</th>
                                                <th>Client Name</th>
                                                <th>Client Phone</th>
                                                <th>Join Date</th>
                                                <th>Email</th>
                                                <th>Is Active</th>
                                                <th>Operation</th>
                                                </tr>
                                            </thead>
                                            <tbody *ngIf="modelList && modelList?.length != 0">
                                                <tr *ngFor="let m of modelList">
                                                <td>{{ m.ClientID }}</td>
                                                <td>{{ m.ClientName }}</td>
                                                <td>{{ m.ClientPhone }}</td>
                                                <td>{{ m.JoinDate | date : "MMM d, y" }}</td>
                                                <td>{{ m.Email}}</td>
                                                <td>
                                                        <div class="btn-group project-list-ad" *ngIf="m.IsActive">
                                                                <button class="btn btn-white btn-xs">Active</button>
                                                        </div>

                                                        <div class="btn-group project-list-ad-rd" *ngIf="!m.IsActive">
                                                                <button class="btn btn-white btn-xs">Unactive</button>
                                                        </div>
                                                </td>
                                                <td>
                                                    <button class="btn btn-pill btn-dark" type="button" (click)='editbuttonClick(m.ClientID)'>
                                                    <i class="fa fa-file-o fa-sm mt-1"></i>&nbsp;Edit
                                                    </button>
                                                </td>
                                                </tr>
                                            </tbody>
                                            <tbody *ngIf="!modelList || modelList?.length == 0">
                                                <tr>
                                                <td colspan="3" class="no-data-available">No data!</td>
                                                </tr>
                                            <tbody>
                                            </table>
                                        </div>

Type Script Code For Angular 8

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

dtOptions: DataTables.Settings = {};
dtTrigger: Subject<ClientList> = new Subject();

implements AfterViewInit on classs

loadAllData() {

const that = this;


this.dtOptions = {
  pagingType: 'full_numbers',
  pageLength: 10,
  serverSide: true,
  processing: true,
  ajax: (dataTablesParameters: any, callback) => {
    that._http
      .post<DataTablesResponse>(
        //'https://angular-datatables-demo-server.herokuapp.com/',
        this.env.apiUrl + 'api/setup/ClientList_SelectAll_Grid',
        dataTablesParameters, {}
      ).subscribe(resp => {
        //console.log(dataTablesParameters);
        that.modelList = resp.data;


        callback({
          recordsTotal: resp.recordsTotal,
          recordsFiltered: resp.recordsFiltered,
          data: []
        });
      });
  },
  columns: [{ data: 'ClientID' }, { data: 'ClientName' }, { data: 'ClientPhone' }, { data: 'JoinDate' }, { data: 'Email' }, { data: 'IsActive' }, { defaultContent: '', orderable: false }]
};



 }

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



 rerender(): void {

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


}

full example of Angular DataTables Server side pagination & Sorting

2 Comments

when calling render function, after adding new data , its only showing last added record. Not showing all records. Can you please help ? How can I fix to show all records including newly added record. -- Thanks
i got success to fix it. Thanks for reply.

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.