4

I'm using typescript in angular 7, I want to have two data tables in one page, and I want a rerender method for each one so I can use a search bar, I know data tables already have a search bar, but I need to assign the data arrays in each search because the data's have thousand of rows that make the data tables ultra slow, so with a search I filter the array making it faster.

I already know how to rerender if I have one table, using dtElement, dtInstance.destroy(); and dtTrigger.next(); but I can't make it work using two tables. I found this code in a forum but gives me this error, and I don't know what to do because I'm not using JQuery: DataTables warning: table id=tablaClaveProdServ - Cannot reinitialize DataTable. For more information about this error, please see http://datatables.net/tn/3

This is table 1

<input type="text" class="form-control" placeholder="Busque una clave del catalogo SAT" (change)="buscarClaveProdServ()" [(ngModel)]="busquedaClaveProdServ">         
<div class="table-responsive table-wrapper-scroll-y">
    <table id="tablaClaveProdServ" datatable [dtOptions]="dtOptions['new']" [dtTrigger]="dtTrigger['new']" class="table table-hover">
        <thead>
            <tr>
                <th scope="col">Clave</th>
                <th scope="col">Descripción</th>
            </tr>
        </thead>
        <tbody>   
            <tr class="pointer" *ngFor="let dato of listaClaveProdServ;">
                <td scope="col">{{dato.clave}}</td>
                <td scope="col">{{dato.descripcion}}</td>
            </tr>
        </tbody>
    </table>
</div> 

This is table 2 (almost same table, changes the data array)

<input type="text" class="form-control" placeholder="Busque una clave del catalogo SAT" (change)="buscarClaveUnidades()" [(ngModel)]="busquedaClaveUnidad">     
<div class="table-responsive table-wrapper-scroll-y">
    <table id="tablaClaveUnidad" datatable [dtOptions]="dtOptions['new']" [dtTrigger]="dtTrigger['new']" class="table table-hover">
        <thead>
            <tr>
                <th scope="col">Clave</th>
                <th scope="col">Descripción</th>
            </tr>
        </thead>
        <tbody>   
            <tr class="pointer" *ngFor="let dato of listaClaveUnidades;">
                <td scope="col">{{dato.clave}}</td>
                <td scope="col">{{dato.descripcion}}</td>
            </tr>
        </tbody>
    </table>
</div> 

This is my typescript file

export class FrmCatRegistroProductoComponent implements AfterViewInit, OnDestroy, OnInit {

  //data arrays
  listaClaveProdServ: Array<GenericModel>;
  listaClaveUnidad: Array<GenericModel>;

  //words to search
  busquedaClaveProdServ:string;
  busquedaClaveUnidad:string;

  @ViewChildren(DataTableDirective)
  dtElements: QueryList<DataTableDirective>;
  dtOptions: DataTables.Settings[] = [];
  dtTrigger: Subject<any>[] = [];

  constructor(
    private listas: GenericList) {
  }    

  ngOnInit(): void {
    this.dtTrigger["new"] = new Subject<any>();
    this.dtOptions['new'] = {
      pagingType: 'full_numbers',
      language: this.listas.dtEspanol,
      searching: false
    };
    this.listaClaveProdServ = [];
    this.listaClaveUnidad = [];
  }

  ngAfterViewInit(): void {
      this.dtTrigger['new'].next();    
  }
  ngOnDestroy(): void {
      this.dtTrigger['new'].unsubscribe();    
  }
  rerender():void{
    this.dtElements.forEach((dtElement: DataTableDirective) => {
      dtElement.dtInstance.then((dtInstance: DataTables.Api) => {
        dtInstance.destroy();
        this.dtTrigger['new'].next();    
      });
    });
  }

  //the search methods
  buscarClaveProdServ():void{
    this.listaClaveProdServ = this.listas.ClaveProductoServicio.filter(o => o.descripcion.includes(this.busquedaClaveProdServ));
    this.rerender();
  }
  buscarClaveUnidades():void{
    this.listaClaveUnidad = this.listas.ClaveUnidad.filter(o => o.descripcion.includes(this.busquedaClaveUnidad));
    this.rerender();
  }
}

I also tried sourrounded dtTrigger with setTimeout(()=>{...}); unsuccessfully.

Hope someone can help me, very thanks if you read this far.

3 Answers 3

4

I define separate triggers on each table:

<table #table1 datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger1">...

<table #table2 datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger2">...

Then rerender like so:

  dtTrigger1: Subject<any> = new Subject();
  dtTrigger2: Subject<any> = new Subject();

  rerender(): void {     
    this.dtElements.forEach((dtElement: DataTableDirective) => {
      if(dtElement.dtInstance)
        dtElement.dtInstance.then((dtInstance: DataTables.Api) => {
          dtInstance.destroy();          
      });
    });
    this.dtTrigger1.next(); 
    this.dtTrigger2.next();    
  }

Profit!

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

Comments

1

By adding destroy:true in datatable options has solved my problem. Inside your ngOnInit()

ngOnInit(): void {
    this.dtTrigger["new"] = new Subject<any>();
    this.dtOptions['new'] = {
      pagingType: 'full_numbers',
      language: this.listas.dtEspanol,
      searching: false,
      destroy:true //Add to allow the datatable to destroy
    };
    this.listaClaveProdServ = [];
    this.listaClaveUnidad = [];
  }

Comments

0

I was also having the same issue. And then I found this answer Here in GitHub

As per l-lin

You need to use @ViewChildren instead of @ViewChild:

Sample Code

import { AfterViewInit, Component, OnInit, ViewChildren, QueryList } from '@angular/core';
import { DataTableDirective } from 'angular-datatables';
import { Subject } from 'rxjs/Rx';

@Component({
  selector: 'app-rerender',
  templateUrl: 'rerender.component.html'
})
export class RerenderComponent implements OnInit, AfterViewInit {
  @ViewChildren(DataTableDirective)
  dtElements: QueryList<DataTableDirective>;

  // ...

  rerender(): void {
    this.dtElements.forEach((dtElement: DataTableDirective) => {
      dtElement.dtInstance.then((dtInstance: DataTables.Api) => {
        // Do your stuff
      });
    });
  }
}

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.