2

I have an Angular component with badges on some icons. The numbers for the badges come from an api that I call when entering the page, in ionViewWillEnter(). When the api returns, the result is assigned to a local variable, that's then referenced in the markup. In Chrome desktop, it all works fine. In Chrome android, the badge doesn't appear until I touch the screen. Why might changes to a local variable not immediately be reflected in the markup? I've tried putting the whole routine in an NgZone, but to no avail. I've also worked through the suggestions in this post, ChangeDetectorRef.detectChanges() and markForCheck(), ApplicationRef.tick()

Update 2: The data gets passed down to a child component, as an object, then again to a grandchild, as a primitive, via @Input properties. If I also display the info directly in the markup of the parent, then both the parent and grandchild component update as expected when the call to the service returns. If I try to trick the system by putting display:none on the parent, my problem returns and I have to touch the screen to see the change in the child.

Here is my .ts code...

// declaration
pastilles: Pastilles = { nbFraisCarte: 0, nbFraisRefuse: 0, nbJustificatifs: 0 };

async ionViewWillEnter(){
  this.ngZone.run(async () => {
    await this._myService
      .pastilles()
      .toPromise()
      .then((resp) => {
        if ((resp.status = 'success')) {
          this.pastilles= resp.sData;
        }
      });
  });
}

In the child component, I have...

@Input()
pastilles: Pastilles;

then in the markup...

<tne-round-button
  (click)="createFraisFrom.emit('justificatif')"
  icon="image"
  [pastille]="pastilles.nbJustificatifs"
></tne-round-button>

then in the tne-round-button grandchild, much the same thing...

@Input()
pastille: number;

and markup...

<div class="pastille" *ngIf="pastille">
  <div class="pastille-text">{{ pastille }}</div>
</div>

What have I missed?

bbsimonbb
  • 27,056
  • 15
  • 80
  • 110

2 Answers2

0

Because pastilles is an object, and Angular can't tell that the object has changed because it's reference is still the same, try doing this.

this.pastilles = { ...resp.sData }

or this

Object.assign(this.pastilles, resp.sData);

I would try them out of the NgZone. Let me know if it works!

maury844
  • 1,210
  • 15
  • 25
  • The object reference is actually being changed when doing `this.pastilles= resp.sData;` – sebaferreras Nov 25 '20 at 15:51
  • 1
    I think you're right, but I've had similar issues and those two tools have worked for me in the past, but now I don't really know how to "justify" dropping those code snippets – maury844 Nov 25 '20 at 15:53
0

Ok so this nearly broke my heart. It turns out the issue was that the data was used in a child component, and the update was simply never made it to the child. The workaround was to also use the data directly in the template of the component that receives it, so triggering the refresh. I have added an invisible div to the parent template, like this...

<div style="visibility: hidden;">{{pastilles.nbJustificatifs}}</div>

...and the badges, still handled in my child component, magically appear. It's ugly, but I'm moving on!

bbsimonbb
  • 27,056
  • 15
  • 80
  • 110
  • That sounds like a change detection problem in the child component. Would you mind adding some of the code of that child component? :) – sebaferreras Nov 26 '20 at 19:25
  • I'm interested to follow this to the bottom. I've updated the question if you have any light to shed ! – bbsimonbb Nov 27 '20 at 09:14