@ViewChild is undefined

2019-09-06 19:44发布

问题:

I am trying to toggle a @ViewChild element with an *ngIf and then after this, call a native event.

This is my html element, adorned with #audioPlayer so I can extract the element via @ViewChild.

<audio 
    #audioPlayer     
    *ngIf="conversationIsRunning"    
    [src]='activeConversation?.clips[activeConversation.activeClipId].audio.blob'
    (ended)="audioComplete($event)" 
    autoplay controls preload="auto" >
</audio>

In my typescript I have the following:

@ViewChild('audioPlayer') audioPlayer;
private conversationIsRunning: boolean;

ngOnInit() {
    this.conversationIsRunning = false;
}

ngOnChanges() {
    console.log("ngOnChanges");
    this.conversationIsRunning = true;       
    console.log(this.audioPlayer); // undefined
    this.audioPlayer.nativeElement.play(); // error
}

The error disappears if I remove the *ngIf from the audio element. However I really want this functionality in place where the element is destroyed when I don't need it.

I saw in this answer that you can use a setter on @ViewChild so I implemented that, however to no success...

private privAudioPlayer: ViewContainerRef;
@ViewChild('audioPlayer') set audioPlayer(audioPlayer: ViewContainerRef) {
    this.privAudioPlayer = audioPlayer;
    console.log('audioPlayer set called >> ', audioPlayer, this.privAudioPlayer);
};

...however this always outputs audioPlayer set called >> undefined undefined

I have also tried splitting the this.conversationIsRunning = true; from its current location and putting into a variety of different ng lifecycle hooks, and then also changing ngOnChanges to other lifecycle hooks as well to no avail.

Do I have to wait until next frame or something? And why does that set audioPlayer mutator recieve undefined?

回答1:

In the first code example, you should use ngAfterViewInit() instead of ngOnChanges().