So I've been learning and using Signals in Angular, and it's exciting. However, there are some use cases where I feel there's some friction. I can't figure out a good pattern when you have a component with input signals
, and you want to trigger a re-fetch of data whenever some input value changes.
computed
is obviously not the way to go since they can't be async. And effect
, according to the docs, shouldn't modify component state. So that seems like a no-go as well. And ngOnChanges is being deprecated (long term) in favor of Signals-based components and zoneless.
Consider the following component:
@Component()
export class ChartComponent {
dataSeriesId = input.required<string>();
fromDate = input.required<Date>();
toDate = input.required<Date>();
private data = signal<ChartData | null>(null);
}
Whenever one of the input signals gets a new value, I want to trigger a re-fetch of data, and update
the value of the private data
signal.
How would one go about this? What's the best practice? Effect and bypass the rule to modify state?
I use Angular's rxjs-interop
to convert the id input signal to an Observable
, then switchMap
to fetch the results and then convert the result back to a signal, like this:
import { toObservable, toSignal } from '@angular/core/rxjs-interop';
@Component({
selector: 'app-chart',
standalone: true,
template: `
{{data()}}
`,
})
export class ChartComponent {
dataSeriesId = input.required<string>();
data = toSignal(
toObservable(this.dataSeriesId).pipe(switchMap((id) => this.fetchData(id))),
{
initialValue: null,
}
);
private fetchData(id: string) {
return of('Example data for id ' + id).pipe(delay(1000));
}
}
Working example on StackBlitz