I’m trying to track click events on an element in my Angular template using the viewChild
signal and the fromEvent
operator from RxJS:
@Component({
selector: "app-example",
standalone: true,
template: `
<button #myButton>click me</button>
Last clicked: {{ lastClick() }}
`,
})
export class ExampleComponent {
buttonRef = viewChild("myButton", { read: ElementRef });
buttonEl = computed(() => this.buttonRef()?.nativeElement);
lastClick = toSignal(
fromEvent(this.buttonEl(), "click").pipe(map(() => Date.now()))
);
}
But I’m getting the following error: TypeError: target is undefined
.
How can I make sure that the value of this.buttonEl()
is not undefined
?
I can’t use static: true
in the viewChild
signal’s options, like I could with the @ViewChild
decorator. I also can’t use viewChildFn()
outside of an injection context.
You can use toObservable
from @angular/core/rxjs-interop
to convert the viewChild
signal to an Observable
and then use the switchMap
operator to switch to listening for the click event once you have the element.
import { Component, ElementRef, computed, viewChild } from "@angular/core";
import { toObservable, toSignal } from "@angular/core/rxjs-interop";
import { fromEvent, map, switchMap } from "rxjs";
@Component({
selector: "app-example",
standalone: true,
template: `
<button #myButton>click me</button>
Last clicked: {{ lastClick() }}
`,
})
export class ExampleComponent {
buttonRef = viewChild("myButton", { read: ElementRef });
buttonEl = computed(() => this.buttonRef()?.nativeElement);
lastClick = toSignal(
toObservable(this.buttonEl).pipe(
switchMap((el) => fromEvent(el, "click").pipe(map(() => Date.now())))
)
);
}