Search code examples
angularangular-ng-if

angular 2: ngIf problems


I got an angular 2 project where a canvas class (build in typescript but outside of the actual angular 2 application) triggers an event whenever the current animation on the canvas was finished. This is performed by the following basic event listener/dispatcher structure:

canvas.ts

eventListener = [];

public addListener(name : string, cb : Function) {
        this.eventListener.push({name: name, cb : cb});
}

public dispatchEvent(name : String, event) {
        var scope = this;
        $.each(scope.eventListener, function(key, value){
            if(value.name == name) {
                value.cb(event);
            }
        });
}

The event listener is registered in one component:

component-that-listens.ts

ngOnInit() {
    this.canvasHelper.addEventListener('animationFinished', () => this.handleAnimationEnd());
}

private handleAnimationEnd() {
    this.isPlaying = false;
    this.isPaused = false;
}

As the component the canvas is in and the one the view should be updated when the animation is done are sibling components there is a canvasHelperService handling the communication of those two.

In the listening component there is an ngIf structure to switch the appearance of a button according to the current status of the animation (stopped, finished, paused, running). This is handled by the boolean variables isPaused and isPlaying in a simmilar way to this:

<span *ngIf="!isPlaying" (click)="play()">PLAY ICON</span>
<span *ngIf="isPlaying" (click)="pause()">PAUSE ICON</span>

If these are both reset to false the initial state should be restored. This all actually works just fine. However, it only resets the button to show the play icon as soon as I hover over the canvas and I can't find a reason why this would happen.

How can I force the ngIf to instantly react to the current animation state without me having to hover over the canvas (part of the component dispatching the event)?


Solution

  • I guess change detection works not properly for you. The animationFinished event might not be dispatched in the correct NgZone. To fix this you can use NgZone.run as shown here: https://angular.io/docs/ts/latest/api/core/index/NgZone-class.html

    ngOnInit() {
      this.canvasHelper.addEventListener('animationFinished', () =>
        this._ngZone.run(() => this.handleAnimationEnd()));
      }
    }
    

    Alternatively check that your eventdispatcher is created inside the NgZone (it usually is when it's created through the angular2 dependency injection mechanism).