Search code examples
angularangular-routingangular-router

Angular. HTML doesn't update afret re route on page


The problem is as follows. When the page is initialized for the first time, all data is updated correctly. In HTML I am using a simple table:

<mat-table [dataSource]="sumDataSource">

But if, after the first initialization, you go to another page and return back to the original one, the data is no longer updated. Although all events are processed correctly, the server returns new data. In the component itself, the value of the sumDataSource variable also changes, but the old data remains in the HTML.

app-routing.module.ts


const routes: Routes =  ....

@NgModule({
  imports: [RouterModule.forRoot(routes, { relativeLinkResolution: 'legacy' })],
  exports: [RouterModule]
})

export class AppRoutingModule { }

In the component, the data update looks like this


  ngOnInit(): void {

    this.emitter();

    this.conditionDefiner();

    this.initMoneyAct();

    this.mapData();

  }

mapData() {

    if (this.dateCondition) {
      this.homepageService.getMoneyAct().subscribe(res => {

        this.moneyAct = res as MoneyAct;

        if (this.houseCondition) {
          this.mapPeriodTable(this.moneyAct);
        }

        this.mapSumTable(this.moneyAct);

      });
    }


  }
  mapSumTable(moneyAct: MoneyAct) {

    this.sumDataSource = [];

    this.sumDataSource.push(moneyAct.cashBoxSummary);

  }
  mapPeriodTable(moneyAct: MoneyAct) {

    this.periodDataSource = [];

    for (let key in moneyAct.moneyByMonth) {

      this.periodDataSource.push({ group: key });
      for (let index = 0; index < moneyAct.moneyByMonth[key].length; index++) {

        const row: CashBoxDetails = moneyAct.moneyByMonth[key][index];

        this.periodDataSource.push({
          arrival: row.arrival,
          countAdults: row.countAdults,
          countDays: row.countDays,
          costPerDay: row.costPerDay,
          needToPay: row.needToPay,
          received: row.received,
          prePayment: row.prePayment,
          isPaind: row.isPaind,
          phoneNumber: row.phoneNumber
        });
      }
    }

  }

All this only works the first time you visit the page.

Angular CLI: 11.1.4
Node: 14.15.0
OS: win32 x64

Angular: 11.1.2
... animations, common, compiler, compiler-cli, core, forms
... language-service, localize, platform-browser
... platform-browser-dynamic, router
Ivy Workspace: Yes

Package                            Version
------------------------------------------------------------
@angular-devkit/architect          0.1001.1
@angular-devkit/core               10.1.1
@angular/cdk                       10.2.1
@angular/cli                       11.1.4
@angular/fire                      6.0.3
@angular/material                  10.2.1
@angular/material-moment-adapter   11.2.0
@schematics/angular                11.1.4
@schematics/update                 0.1101.4
rxjs                               6.6.3
typescript                         4.0.2

UPDATE

Found where the problem is. But I didn't understand why. Events that change the component model in my case are called in another component. I did it through the Emitter.

Component with event

onHouseChange(id: string) {
    localStorage.setItem(GLOBAL_VARIABLE.SELECTED_HOUSE, id);
    this.eventEmitterService.runMoneyAct();
  }

EventEmitterService

export class EventEmitterService {

  invokeMoney = new EventEmitter();
  subsMoney: Subscription;

  constructor() { }

  sub(subscription: Subscription) {
    if (this.subsHome == undefined) {
      this.subsHome = subscription
    }
  } 
  runMoneyAct(){
    this.invokeMoney.emit();
  }
 

Component where data is updated

 emitter() {
    if (this.eventEmitterService.subsMoney == undefined) {
      this.eventEmitterService.subsMoney = this.eventEmitterService.invokeMoney.subscribe(() => {
        this.ngOnInit();
      });
    }
  }

If you put the event call in the component itself, there is no problem


Solution

  • According to Angular material's official documentation:

    "Since the table optimizes for performance, it will not automatically check for changes to the data array. Instead, when objects are added, removed, or moved on the data array, you can trigger an update to the table's rendered rows by calling its renderRows() method."

    You have to call the renderRows() function for the table to check whether the array has updated or not.