Ionic 4.Beta 12 - View sometimes doesn't update on data change

I am getting a very weird error in Ionic 4 where my view doesn’t update automatically when the data changes. But when I click on the html then it updates.

The issue with the error is very inconsistent and hard to replicate. But it now has happened twice to me when migrating my components.

A bit of background I have a component that displays the role hierarchy of an organisation. Below is what the data object looks like. It is a nested objects.

let obj1: OrganisationRoleChart = {
      id: "59f4d75d-5dd3-401c-a313-572efb266aec",
      organisation: {id: "e36d1d62-c7ab-498d-8fc9-c674b7eb6b23", name: "ABCCOMPANY", organisation_type: {id: 10, name: "SUPPLIER"}, default_folder: null},
      role: {id: 2, name: "CEO", description: "Head of finance", is_protected: false},
      description: null,
        children: [{id: "c1688286-2eeb-4c32-901e-f00788b31b5d",
           organisation: {id: "e36d1d62-c7ab-498d-8fc9-c674b7eb6b23", name: "ABCCOMPANY", 
           organisation_type: {id: 10, name: "SUPPLIER"}, default_folder: null},
           role: {id: 3, name: "Accountant", description: "Account dept", is_protected: false},
           description: null,
          children: []}]
    }

When I make a change like removing a role, it performs the action and the calls an API which is part of shared service to retrieve the updated role chart as below.

/*
  ** name: Set Record
  ** desc: 
  */
  setRecord(): void {
    this.isLoad = true;
    this.presentLoading('Fetching...');
    console.log('Fetching role chart...');
    this.roleResourceService.getOrganisationRolesChartsHttp(this.id)
    .subscribe(
      data => { 
        console.log('Role charts fetched!', data);
        if (data.length > 0) {
          this.record = data[0];
        } else {
          this.record = null;
        }      
        this.dismissLoading();
        this.isLoad = false;
      },
      err => {
        this.events.publish('alert:server-error', err);              
        this.dismissLoading();
        this.isLoad = false;
      },
      () => console.log('Request Complete')
    );
  }
<div *ngIf="record && !isLoad">
  <app-zoom *ngIf="record.children.length>0" [value]="zoom" (onUpdate)="zoom = $event" [isPrint]="true"></app-zoom>
  <div id="printArea" [style.height.px]="500" scrollX="true" scrollY="true" style="position:relative">
      <div fxFlex fxLayout="horizontal" [style.zoom.%]="zoom">
          <div fxFlex></div>
          <div style="position: relative;text-align: center">
              <ion-card class="card" style="display:inline-block;" padding>  
                  <div fxFlex fxLayout="horizontal">   
                      <div fxFlex fxLayout="vertical">
                          <div>{{record.role.name}}</div>     
                          <div>{{record.description?record.description:record.role.description}}</div>                       
                      </div>
                      <div>
                          <ion-button (click)="presentActionSheet(record)" fill="clear" >
                              <ion-icon name="more"></ion-icon>
                          </ion-button>
                      </div>    
                  </div>
              </ion-card>
              <!--Vertical Line-->
              <hr class="hr" *ngIf="record.children.length>0">
              <app-chart-node [isLarge]="isLarge" [mode]="'role'" [records]="record.children" (onChild)="child($event)"  (onDelete)="delete($event)"></app-chart-node>
          </div>
          <div fxFlex></div>
      </div>
  </div>
</div>

The issue is when the new data is retrieved the view doesn’t update with the new hierarchy. But the weird thing is when I click on the component area in the html view it then updates with the latest changes.

I did some further testing and made a simple button which manually changes the record. This works and the view updates as expected.

test(): void {
    let obj1: OrganisationRoleChart = {
      id: "59f4d75d-5dd3-401c-a313-572efb266aec",
      organisation: {id: "e36d1d62-c7ab-498d-8fc9-c674b7eb6b23", name: "ABCCOMPANY", organisation_type: {id: 10, name: "SUPPLIER"}, default_folder: null},
      role: {id: 2, name: "CEO", description: "Head of finance", is_protected: false},
      description: null,
      children: [{id: "c1688286-2eeb-4c32-901e-f00788b31b5d",
      organisation: {id: "e36d1d62-c7ab-498d-8fc9-c674b7eb6b23", name: "ABCCOMPANY", organisation_type: {id: 10, name: "SUPPLIER"}, default_folder: null},
      role: {id: 3, name: "Accountant", description: "Account dept", is_protected: false},
      description: null,
      children: []}]
    }
    this.record = obj1;
  }

Finally here is my ionic info:

Ionic:

   ionic (Ionic CLI)          : 4.2.0 (/usr/local/lib/node_modules/ionic)
   Ionic Framework            : @ionic/angular 4.0.0-beta.12
   @angular-devkit/core       : 0.9.0-beta.3
   @angular-devkit/schematics : 0.9.0-beta.3
   @angular/cli               : 6.1.5
   @ionic/ng-toolkit          : 1.1.0
   @ionic/schematics-angular  : 1.0.7

Cordova:

   cordova (Cordova CLI) : 7.1.0
   Cordova Platforms     : none
   Cordova Plugins       : no whitelisted plugins (5 plugins total)

System:

   ios-deploy : 1.9.1
   NodeJS     : v10.10.0 (/usr/local/bin/node)
   npm        : 6.4.1
   OS         : macOS High Sierra

So I am absolutely lost why is this happening, is as if the view component is loosing focus when it is does the API call. Has anyone else run into a similar issue? Appreciate any help on this.

3 Likes

Same problem here. I am capturing the image with camera and showing it on the screen. It doesn’t appear until I click on the page.

1 Like

To manually check for changes: add this to your code:

import { ChangeDetectorRef } from '@angular/core'

constructor(private changeRef: ChangeDetectorRef)

this.changeRef.detectChanges();

15 Likes

Thanks buddy your solution worked. It is a weird issue I’ve never came across in Ionic 3 but you have saved made me massive headaches doing the migration to Ionic 4.

Just for clarification to anyone having the same issue I imported ChangeDetectorRef into my component and added it to the constructor. Each time I make a data change (which should update in the view) I fire the falling command:

this.changeRef.detectChanges();

This should force update the view.

In this instance it was my setRecord funtion:

setRecord(): void {
    this.isLoad = true;
    this.presentLoading('Fetching...');
    console.log('Fetching role chart...');
    this.roleResourceService.getOrganisationRolesChartsHttp(this.id)
    .subscribe(
      data => { 
        console.log('Role charts fetched!', data);
        if (data.length > 0) {
          this.record = data[0];
        } else {
          this.record = null;
        }      
        this.dismissLoading();
        this.isLoad = false;
        this.changeRef.detectChanges();
      },
      err => {
        this.events.publish('alert:server-error', err);              
        this.dismissLoading();
        this.isLoad = false;
      },
      () => console.log('Request Complete')
    );
  }
1 Like

thanks MattE your save my life… :grinning:

Thanks MattE. I have the same issue. My page is not rendered even data change and this work beautifully for me. I’m using Ionic V3.

1 Like

I am also facing same issues and getting following warning on tab changes

Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()

Since the courses of updates since this post, I found the change data detection has improved where I rarely have to use this.changeRef.detectChanges();

This worked for me, but I later also found what caused the non-working change detection:

I had this on my malfunctioning page: <ion-button disabled="parameter === wantedvalue">

I discovered that when I fixed that to include [brackets], as it should since it’s an evaluated condition: <ion-button [disabled]="parameter === wantedvalue">… , change detection suddenly worked.

I ONLY had change detection issues in native android, web change detection DID work. Interestingly, I saw the console.log()ed events in android logcat, but the UI wasn’t updated. The UI DID update when interacting with buttons on the page. The missing updates to UI were only on server-generated (firestore onSubscribe()) events.

we have same issue.
<ion-button [disabled]=“check_function()”

and in ts file
we just return true or false, but it works very first time, and second time it not works, so when i click another button or resize current screen using F12 then it again works, so have you found any solutions ?

Here is ionic info

Ionic:
Ionic CLI : 6.3.0 (C:\Users\himansu\AppData\Roaming\npm\node_modules\@ionic\cli)
Ionic Framework : @ionic/angular 5.0.7
@angular-devkit/build-angular : 0.803.25
@angular-devkit/schematics : 9.0.6
@angular/cli : 8.3.25
@ionic/angular-toolkit : 2.2.0
Cordova:
Cordova CLI : 8.0.0
Cordova Platforms : not available
Cordova Plugins : not available
Utility:
cordova-res : not installed
native-run : not installed
System:
NodeJS : v12.16.1 (C:\Program Files\nodejs\node.exe)
npm : 6.13.4
OS : Windows 7

Thanks in advance

I have the same issue now, interestingly UI updates on one of my android devices but not on my iphone and other android device, go figure. So do I have to use detectChanges() on every component I subscribe to data on Firestore ? holly molly

1 Like

apparently my issue was caused because some bug in Angular, date pipe and number pipe doesn’t work on ios, safari and on some huawei devices and it caused my firestore data not to show up in template

Thank you so much mate, I was struggling to make this work, and already tried so many solution but nothing worked, your this line of code did the magic, may I know the reason what would possible causing the issue ?

It’s hard to say without knowing what the source of the data change is, but generally speaking, it’s a sign of a fairly serious issue involving (typically a third-party library) that is not Angular-aware.