Search code examples
angulartypescriptionic-frameworkionic5

After ChangeDetectionStrategy.OnPush enabled UI doesn't update


According to translation change:

     setTranslation(): void {
        this.translateService.stream(['Client.Dashboard', 'Client.Active-
Orders']).subscribe(res => {

          const sideMenu: SideMenuModel = {
            dashboard: res['Client.Dashboard'],
            activeOrders: res['Client.Active-Orders'],

          };

          this.setSideMenu(sideMenu); // here it calls
        });
      }

I hope this is due to immutability issue here. i.e. this.sideMenu. Could you give me any hint here?

setSideMenu(sideMenu: SideMenuModel): void {

    this.sideMenu = [
      {
        title: sideMenu.dashboard,
        url: '/dashboard',

      },
      {
        title: sideMenu.activeOrders,
        url: '/active-orders',

      },
]

I have enabled changeDetection: ChangeDetectionStrategy.OnPush,. After that, UI doesn't update properly.

Note: I have removed unwanted template code here.

 <ion-menu-toggle auto-hide="false" *ngFor="let s of sideMenu; let i = index">

    <ion-item (click)="selectedIndex = i" routerDirection="root" [routerLink]="[s.url]">

    </ion-item>

  </ion-menu-toggle>

Solution

  • As I mentioned in my question this is a problem with data mutation. So I have used BehaviorSubject with async pipe. Now it is working fine without any hacks.

    Great article about that: https://blog.angular-university.io/onpush-change-detection-how-it-works/

    html

    <ion-menu-toggle *ngFor="let s of sideMenuChanged$ |async; let i = index">
    
    
      </ion-menu-toggle>
    

    .ts

      private sideMenuSubject$: BehaviorSubject<any> = new BehaviorSubject<any>(null);
      sideMenuChanged$: Observable<any> = this.sideMenuSubject$.asObservable();
    
      constructor(private translateService: TranslateService, ) { }
    
    ngOnInit(): void {
      this.setTranslation();
    }
    
     setTranslation(): void {
        this.translateService.stream(['Client.Dashboard', 'Client.Active-Orders']).subscribe(res => {
    
          const sideMenu: SideMenuModel = {
            dashboard: res['Client.Dashboard'],
            activeOrders: res['Client.Active-Orders'],
           };
    
          this.setSideMenu(sideMenu);
        });
      }
    
    setSideMenu(sideMenu: SideMenuModel): void {
    
        this.sideMenu = [
          {
            title: sideMenu.dashboard,
            url: '/dashboard',
            src: '../assets/images/client/dashboard-side-menu.png'
          },
          {
            title: sideMenu.activeOrders,
            url: '/active-orders',
            src: '../assets/images/common/active-orders.png',
            isActiveOrder: true
          },
         ];
    
        this.sideMenuSubject$.next(this.sideMenu);
      }