Angular is programmed to detect any alterations

Upon detecting changes, the NgOnChanges function triggers an infinite service call to update the table, a situation that currently perplexes me. Any assistance on this matter would be greatly appreciated. Many thanks.

The TableMultiSortComponent functions as the parent component in my setup, with the output EventEmitter passing along the table data.

The event emitted by the EventEmitter is transmitted to the child component where I utilize parameters like pagesize and pageindex for querying purposes within the dataServiceEvent function.

Subsequently, the request's output, dealsListData, is relayed from the child component back to the parent component as data destined for populating the table.

The intended behavior is for the table to dynamically update when changes occur, which led me to place it under the ngOnchanges method, specifically the initTableMultiSort function. However, the table undergoes repeated updates indefinitely instead of just once following a change.

#Within this.parent component, data transmission towards the child component is facilitated through: this.dataServiceEvent.emit(this.table); given its necessity for attributes like pageindex and size.

#HTML CODE - Parent Component

<mat-card *ngIf="table !== undefined">
  <mat-table mat-table [dataSource]="table.dataSource" matMultiSort (matSortChange)="table.onSortEvent()"> 
    <ng-container *ngFor="let column of table.columns" [matColumnDef]="column.id">
      <mat-header-cell class="table-multi-sort-header" *matHeaderCellDef [mat-multi-sort-header]="column.id"> 
        <div>{{column.name}}</div> 
        <div class="sub-text">{{getColumnSubtitle(column.id)}}</div>
      </mat-header-cell>
      <mat-cell *matCellDef="let row">
          <ng-container *ngIf="column.id !== 'action'; then col; else actionCol"></ng-container>
          <ng-template #col>
            <app-table-multi-sort-cell-default [cellData]="row" [id]="column.id" [subId]="getColumnSubId(column.id)"></app-table-multi-sort-cell-default>
          </ng-template>
          <ng-template #actionCol>
            <app-table-multi-sort-cell-action [rowData]="row" [actions]="getActions(column.id)" (actionClickEvent)="clickTableAction($event,row)"></app-table-multi-sort-cell-action>
          </ng-template>
      </mat-cell>
    </ng-container>
    <mat-header-row *matHeaderRowDef="table.displayedColumns; sticky:true"></mat-header-row>
    <mat-row *matRowDef="let item; columns: table.displayedColumns;"></mat-row>
  </mat-table> 
  <mat-progress-bar *ngIf="isLoading" mode="indeterminate"></mat-progress-bar>
</mat-card>

#ts code- parent component

export class TableMultiSortComponent implements OnInit {
  @Input() tableOptions:any;
  @Input() tableData:any = [];
  @Input() isClientSide:boolean = false;
  @Input() isLoading: boolean = false;
  @Output() tableActionsEvent = new EventEmitter<any>();
  @Output() dataServiceEvent = new EventEmitter<any>() ;
  @ViewChild(MatMultiSort, { static: false }) sort: MatMultiSort;
  
  tableConfig: any = TABLE_MULTI_SORT_OPTIONS.DEFAULT;
  table:TableData<any>;
  displayedColumns: any;
  
  constructor() { }

  ngOnInit(): void {   
    this.initTableMultiSort();
  }

  initTableMultiSort(){
    this.tableConfig = {
      ...this.tableConfig,
      ...this.tableOptions
    }
    
    // Rest of the initialization process goes here...
    
  }

  ngOnChanges(changes: SimpleChanges) {  
    if (changes.tableData && changes.tableData.currentValue){  
      console.log("changes" , changes)
      this.initTableMultiSort()
    }
  }

  getData(){
    // Method logic for getting data...
    
  }

#child component HTML code

  <app-table-multi-sort  (dataServiceEvent)="dataServiceEvent($event)" [tableOptions]="tableOptions" [tableData]="dealsListData" (tableActionsEvent)="tableActions($event)"></app-table-multi-sort>

#child component ts code

   export class DealsTransactionComponent implements OnInit {
  // Child component functionality and methods implementation...

Answer №1

Whenever you call the getData function in the TableMultiSortComponent's ngOnInit lifecycle hook, you emit this.table.

This emission likely triggers a data fetch in the parent component's tableActions method (the implementation of which is not visible in the provided code). The tableActions method probably resembles _pageEventMyList, which retrieves data from the API and assigns it to the dealsListData property of the TableMultiSortComponent (

[tableData]="dealsListData"
).

Subsequently, this triggers the onChange function in

TableMultiSortComponent</code, passing through the <code>if
check validating that the tableData has indeed changed. Upon invoking initTableMultiSort within onChange, this.table gets reinitialized and emitted via
this.dataServiceEvent.emit(this.table);
, creating a recurring cycle.

To avoid triggering unnecessary data reloads, it's advisable to include additional checks to ensure that the table configuration remains unchanged before refetching data.

In essence, the table facilitates access to information such as pageIndex, pageSize, sortParams, and sortDirs. Therefore, preserving the values of these properties while attempting to load data again, comparing them, and fetching data only upon detecting changes is recommended.

  private currentTableConfig: TableData<any>;

  private _pageEventMyList() {
    if (!shouldLoadData(currentTableConfig, this.table)) {
      return;
    }
    this.currentTableConfig = this.table;
    this.searchInput = '';
    this.isLoading = true;
    this.dealService
      .getAllDeals(
        this.accountId,
        this.transaction.id,
        this.table.pageIndex + 1,
        this.table.pageSize,
        this.searchInput,
        this.table.sortParams,
        this.table.sortDirs
      )
      .pipe(finalize(() => (this.isLoading = false)))
      .subscribe({
        error: (err) => this.notificationService.showError(err),
        next: (res) => {
          this.dealsListData = res.totalItemCount;
          this.dealsListData = res.lastItemOnPage;
          this.totalDeals = res.items.length;
          this.dealsListData = res.items;
        },
        complete: noop,
      });
  }

The new shouldLoadData method carries out the necessary comparisons:

private shouldLoadData(oldTableConfig: TableData<any>, tableConfig: TableData<any>): boolean {
  if (!oldTableConfig) {
    return true;
  }
  return oldTableConfig.pageIndex !== tableConfig.pageIndex
    || oldTableConfig.pageSize !== tableConfig.pageSize
    || JSON.stringify(oldTableConfig.sortParams) !== JSON.stringify(tableConfig.sortParams)
    || JSON.stringify(oldTableConfig.sortDirs) !== JSON.stringify(tableConfig.sortDirs);
}

Regarding the use of JSON.stringify:

While functional, it may not be the most efficient approach. If an alternative third-party library like lodash is available, utilizing _.isEqual or an equivalent method for array comparison is recommended.

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

utilizing the active class with react js

Apologies for the question, but I am facing an issue where adding an active class to a button is affecting all buttons when clicked. How can this be fixed? Here is the code snippet: <div className=""> {category.items.length === 0 ? ( ...

Is it necessary to unsubscribe within the subscribe callback function?

I've been searching for a straightforward solution to prevent memory leaks caused by not unsubscribing. Most of the time, I only need one response from the backend and then I want to unsubscribe. So why not call it within the callback? onSubmit(){ ...

Error: The next.config.js file contains invalid options - The root value includes an unexpected property

I recently updated my next version from 10 to 12, and when I run the local development server, I encounter the following error in the terminal. As a result, the code fails to compile. How can I fix this issue? Invalid next.config.js options have been iden ...

Struggling with modifying class in HTML using JavaScript

I've been attempting to replicate a JavaScript code I came across on the internet in order to create a functioning dropdown menu. The concept is quite straightforward - the div class starts as xxx-closed and upon clicking, with the help of JavaScript, ...

Executing the event handler only once

In my React project, I have a button that toggles a boolean state. However, I realized that the button can both set and unset the state due to its toggle functionality. I only want the state to be changed once. Is there a different function I can use ins ...

Is there a way to programmatically emulate Firebug's inspect element feature using JavaScript?

Is there a straightforward method in JavaScript or any popular libraries like YUI or jQuery to allow users to interact with elements on a website, similar to the functionality of Firebug for developers? ...

What is the reason for webpack adding "-es5" and "es2015" to my TypeScript files?

When Webpack converts my typescript files into Javascript files, it appends -es5 to the name. For instance, I expect the file to be named background.js, but it actually generates 4 separate files: background-es5.js background-es5.js.map background-es2015. ...

Having trouble getting tailwind dark mode to work on next.js?

I have set up a custom boilerplate using next.js(10.0.5) with preact(10.5.12), typescript(4.1.3), and tailwind(2.0.2). I am attempting to incorporate a dark mode feature from Tailwind. I followed the instructions from next-themes in order to add the dark ...

Adjust an UpdatePanel with client-side code triggering server-side operations

I am fairly new to asp.net and have been experimenting with it for around a week now. Currently, I have a page that interacts with a web service, continuously checking its progress (shown in an UpdatePanel) until completion. Once the process is completed, ...

Is it possible to trigger multiple button clicks using JQuery simultaneously?

Hello everyone, I am new to StackOverflow and this is my first question here. I hope it's not too silly. Thank you in advance for your help! I am trying to achieve a functionality where one button click triggers the clicks of multiple other buttons u ...

Angular-6 Issue: Default Value Not Displaying in Drop-Down List

I am attempting to bind an array into a list. The binding part is functioning correctly, but the default value of the drop down is not displaying. Initially, the array does not contain any values. Here is the code snippet: <select (change)="select($ev ...

Converting CommonJS default exports into named exports / Unable to load ES module

I've encountered an issue while creating a Discord bot with discord.js using TypeScript. When attempting to run the resulting JavaScript code, I'm facing an error that states: import { Client, FriendlyError, SQLiteProvider } from 'discord.js ...

What causes the issue of Angular 9 routing breaking upon page refresh?

I have deployed my Angular 9 application on Heroku and everything is working perfectly. However, when I refresh the page or copy/paste a link, I get an error message saying "Cannot GET /XXX/XXX". Only the root link seems to work! Initially, I can navigate ...

Error encountered during module parsing: Unexpected token found. To resolve this issue, consider using a suitable loader to process this file format

Currently, I am in the process of learning how to develop .NET Core applications with Angular 4. My current project involves migrating an application from Core 1.1 and Angular 4.1.2 to Core 2.0 and Angular 4.3.6. In the previous version of the project, w ...

Display a hidden div on hover using JQUERY

How can I make a hover popup appear when submitting a form, and have it disappear only when the mouse is out of both the popup div and the submit button? Currently, the hover popup shows up but disappears when entering the popup. Can someone assist me in r ...

Change prompt-sync from require to import syntax

In my Node project, I have integrated the prompt-sync module. const prompt = require('prompt-sync')(); const result = prompt(message); To maintain consistency in my TypeScript code, I decided to switch from using require to import. In order to ...

Retrieving and storing data using jQuery's AJAX caching feature

When utilizing jQuery's $.ajax() method to perform an XHR based HTTP GET request to obtain a partial of HTML from a Ruby on Rails website, I encounter an issue. Specifically, every time a user clicks on tabbed navigation, I refresh an HTML table with ...

Gather information from functions that are continually updated with each React refresh

**import { controls } from "../../../constants/controls"; import { useKeyPress } from "../../../hooks/useKeyPress"; import { useArena } from "./useArena"; const getDamage = (attacker, defender) => { let damage = attacker ...

Error: excessive recursion detected in <div ng-view="" class="ng-scope">

I've recently started learning angularJS and I've encountered an error that I need help with. Below is my index.html file: <body ng-app="myApp"> <div ng-view></div> <a href="table">click</a> <script ...

Encountering an unexpected error with the InvalidCharacterError in IE11 when using VEE Validate in conjunction with Vue.js and babel-p

Encountering an issue in IE11 where I receive an InvalidCharacterError when attempting to validate a form using vee validate in vue.js. It seems like it might be related to a polyfill error, but I'm uncertain. I have tried debugging by removing certai ...