[RC0] custom component with *ngIf can't use [navPush]


#1

I’m using a custom component that is dynamically enabled via *ngIf (or generated by *ngFor). The expression of *ngIf becomes true some time after the page has been initialized (some time after ngOnInit()) – for example after a network request or a setTimeout.

The custom component only contains a link to another page <a [navPush]="myPage"> but throws an “Expression has changed after it was checked.” exception.

This doesn’t happen when I’m setting the expression of *ngIf to true inside ngOnInit() without a timeout.

The following is a simple test case.

Custom Component

component.html

<a [navPush]="myPage">MyPage</a>

component.ts

import { Component } from '@angular/core';
import { SomePage } from '../some/page';

@Component({
    selector: 'my-component',
    templateUrl: 'component.html'
})
export class MyComponent {

    public myPage = SomePage;

    constructor() { }

}

Page

page.html

<ion-header>
    <ion-navbar>
        <ion-title>Page</ion-title>
    </ion-navbar>
</ion-header>

<ion-content>
    <my-component *ngIf="isEnabled"></my-component>
</ion-content>

page.ts

import { Component } from '@angular/core';

@Component({
    templateUrl: 'page.html'
})
export class Page {

    public isEnabled = false;

    ngOnInit() {
        // this would work
        // this.isEnabled = true;

        // this doesn't work
        window.setTimeout(() => {
            this.isEnabled = true;
        }, 2000);
    }

}

The component throws:

Expression has changed after it was checked. Previous value: ‘undefined’. Current value: ‘#’.

The async function and [navPush] together are causing the problem.

Using a native angular thing like {{ myPage }} instead of <a [navPush]="myPage">MyPage</a> works without any problems.


#2

I would try hiding the my-component instead of using *ngIf to completely blast it out of the DOM.


#3

That’s a good idea for a temporary workaround, thanks. But it doesn’t work when using *ngFor.

Another possible workaround might be to use (click)="callNavPushInMyComponentCode(myPage)", but that’s less readable, more code and also a slightly different behavior compared to [navPush].

I’ve created an issue on GitHub: https://github.com/driftyco/ionic/issues/8563