What is the best way to update multiple data tables using TypeScript?

In my Angular 7 project, I am utilizing TypeScript to implement two data tables on a single page. Each table requires a rerender method in order to incorporate a search bar functionality. While the data tables come with built-in search bars, the sheer volume of rows in the data arrays significantly hampers the performance. By filtering the array through a search bar, I can enhance the speed and efficiency of the data tables.

For a single table, I have successfully implemented the rerender process using dtElement, dtInstance.destroy(), and dtTrigger.next(). However, when attempting to extend this functionality to two tables, I encountered an error referencing DataTables: "Cannot reinitialize DataTable." This error led me to a forum where I found code that relied on jQuery, which I am not using. Here is the problematic code snippet:

This representation illustrates Table 1:

<input type="text" class="form-control" placeholder="Search for a code from SAT catalog" (change)="searchCodeProdServ()" [(ngModel)]="searchCodeProdServ">         
<div class="table-responsive table-wrapper-scroll-y">
    <table id="tableCodeProdServ" datatable [dtOptions]="dtOptions['new']" [dtTrigger]="dtTrigger['new']" class="table table-hover">
        <thead>
            <tr>
                <th scope="col">Code</th>
                <th scope="col">Description</th>
            </tr>
        </thead>
        <tbody>   
            <tr class="pointer" *ngFor="let item of listCodeProdServ;">
                <td scope="col">{{item.code}}</td>
                <td scope="col">{{item.description}}</td>
            </tr>
        </tbody>
    </table>
</div> 

This illustration represents Table 2 (nearly identical, except for the data array used):

<input type="text" class="form-control" placeholder="Search for a code from SAT catalog" (change)="searchUnitCode()" [(ngModel)]="searchUnitCode">     
<div class="table-responsive table-wrapper-scroll-y">
    <table id="tableUnitCode" datatable [dtOptions]="dtOptions['new']" [dtTrigger]="dtTrigger['new']" class="table table-hover">
        <thead>
            <tr>
                <th scope="col">Code</th>
                <th scope="col">Description</th>
            </tr>
        </thead>
        <tbody>   
            <tr class="pointer" *ngFor="let item of listUnitCodes;">
                <td scope="col">{{item.code}}</td>
                <td scope="col">{{item.description}}</td>
            </tr>
        </tbody>
    </table>
</div> 

Here is a snippet from my TypeScript file:

export class FrmRegisterProductComponent implements AfterViewInit, OnDestroy, OnInit {

  //data arrays
  listCodeProdServ: Array<GenericModel>;
  listUnitCodes: Array<GenericModel>;

  //search terms
  searchCodeProdServ: string;
  searchUnitCode: string;

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

  constructor(private lists: GenericList) {
  }    

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

  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();    
      });
    });
  }

  //search methods
  searchCodeProdServ():void{
    this.listCodeProdServ = this.lists.CodeProductService.filter(o => o.description.includes(this.searchCodeProdServ));
    this.rerender();
  }
  searchUnitCode():void{
    this.listUnitCodes = this.lists.UnitCode.filter(o => o.description.includes(this.searchUnitCode));
    this.rerender();
  }
}

I also attempted surrounding dtTrigger with setTimeout(()=>{...}); without success.

If anyone could offer assistance, I would greatly appreciate it. Thank you for reading this far.

Answer №1

By setting up individual triggers for each table, I ensure a more organized approach:

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

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

To refresh the tables, the following method is employed:

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

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

Achieving success through proper table management!

Answer №2

I managed to fix the issue by including destroy:true in the datatable options section. Make sure to add this line 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 // This allows the datatable to be destroyed
    };
    this.listaClaveProdServ = [];
    this.listaClaveUnidad = [];
  }

Answer №3

I encountered a similar issue, but luckily I stumbled upon the solution on GitHub

According to l-lin

The key is to utilize @ViewChildren instead of @ViewChild:

Here is an example code snippet

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) => {
        // Perform necessary actions
      });
    });
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

A guide on refreshing the dependencies list within Angular's node modules and package.json files

A close friend sent me the angular src folder, which I used to create a new Angular project. However, when I replaced my newly created src folder with my friend's and tried running the application using npm start, I encountered errors related to missi ...

Tips for stopping TypeScript code blocks from being compiled by the Angular AOT Webpack plugin

Is there a way to exclude specific code from Angular's AOT compiler? For instance, the webpack-strip-block loader can be utilized to eliminate code between comments during production. export class SomeComponent implements OnInit { ngOnInit() { ...

Error message in Docker: "Command /bin/sh: 1: ng: not found; please make sure Angular

While attempting to create a docker image for my Angular app, I encountered an issue where it crashes on RUN ng build --prod and the error message displayed is: /bin/sh: 1: ng: not found The command '/bin/sh -c ng build --prod' returned a non-ze ...

Unable to transfer data through Ionic popover

I've encountered an issue when trying to pass data to my popover component, as the data doesn't seem to be sent successfully. Code HTML <div class="message" id="conversation" *ngFor="let message of messages.notes"> <ion-row class= ...

"Utilize an Angular button to upload a locally stored JSON file and populate a data

Hey everyone, I'm looking to use a button to load a local file and convert the file data into a jsonObject. The HTML structure: <div class="uuidLableLeft"> <b>Do you want to import your previous file (.json)?</b> <input style ...

Want to learn how to integrate React-pdf (@react-pdf/renderer) with TypeScript on NodeJS and Express JS?

I am encountering difficulties running React-Pdf (@react-pdf/renderer) with TypeScript on an Express JS server. I have attempted to use babel but encountered errors that I cannot resolve. build error error error You can find the Github repository for t ...

Trying to automatically select a checkbox upon page load in Angular 6

When the page loads, I want to automatically check a checkbox. Here is my component: var user = ViewprojectComponent.featuresList1; this.rules_id = user[0]; for(let i = 0; i <= this.rules_id.length; i++) { var checkedOn1 = this.rules_id[i]; this.Ru ...

Tips for effectively using ngOnChanges in Angular 2 to validate inputs without causing the 'Expression has changed after it was checked' error

I attempted to create my own custom component with basic validation using regex that can be passed as input to the component. There are two scenarios to consider: one where the form is initially empty (new item form) and another where data is already prese ...

When in development mode, opt for the unminified version of the library in Web

My TypeScript project utilizes a forked version of the apexcharts npm package. When building the project with webpack in development mode, I want to use the unminified version of the apex charts library. However, for production, I prefer to stick with the ...

The category 'Moment' cannot be assigned to the category 'Date'. The characteristic 'toDateString' is not present in the category 'Moment'

I recently integrated moment into my Angular2 application, and encountered an issue when attempting to assign the date of this week's Saturday to a variable of type date, case "weekend": this.fromDate = moment().startOf('week ...

Bringing in Chai with Typescript

Currently attempting to incorporate chai into my typescript project. The javascript example for Chai is as follows: var should = require('chai').should(); I have downloaded the type definition using the command: tsd install chai After refere ...

Unlock the power of TypeScript by linking together function calls

I am looking for a way to create a type that allows me to chain functions together, but delay their execution until after the initial argument is provided. The desired functionality would be something like this: const getStringFromNumber = pipe() .then ...

"NODEJS: Exploring the Concept of Key-Value Pairs in Object

I am facing a challenge with accessing nested key/value pairs in an object received through a webhook. The object in req.body looks like this: {"appId":"7HPEPVBTZGDCP","merchants":{"6RDH804A896K1":[{"objectId&qu ...

Adjust text size based on device orientation changes

I'm struggling to dynamically change the font size based on screen orientation and width. How can I adjust the font size when switching between landscape and portrait mode? I attempted using an event listener, but it's not updating the font size. ...

Troubleshooting issue with image dimensions in Angular within CKEditor content

One issue I am facing is with CKEditor, where images inserted into Rich Text Fields have their height and width attributes set in a CSS style tag. For example: <img alt="" src="https://something.cloudfront.net/something.jpg" style="height:402px; ...

Troubles arise with a Web API ASP .NET / Angular2 Session hosted on Azure

Hello, this is my first question here so please let me know if something doesn't fit. Currently, we are working on developing a Web API using C# and Angular2. One of the features requires the session to be efficient, but despite going through numerou ...

Arrange objects in dropdown menu to line up

I'm currently working on a dropdown menu and I have a specific requirement – the menu should always be split into two columns and be able to span multiple lines. However, I've encountered an issue where the columns are not aligned properly, cau ...

The final position of the Angular increment animation does not hold

Is there a way to trigger an animation when the value of countAllOrders changes? Specifically, I am attempting to adjust the margin of a list using keyframes in an Angular animation. Here is my HTML code: <ul class="digits" [@ordersValue]=&q ...

What is the best way to target changing elements displayed by *ngIf?

Trying to access a dynamic element generated by ngIf in the code below has proven to be challenging. I attempted two different methods: Using ElementRef and querySelector Component template: `<div class="test" *ngIf="expr"> <a id="b ...

Changing the selection in the Angular Mat-Select dropdown causes the dropdown's position to shift

Issue with dropdown position: The dropdown should display below the select element, but when selecting the second value, it appears on top of the select element. I have removed any relevant CSS to troubleshoot, but the problem persists. See screenshots for ...