I have an Angular 20 application with a Component that fetches logs from a bookService based on a required Input. The service returns an Observable.
I tried to transform the Observable from the service with toSignal(), like this:
export class HistoryComponent {
private readonly bookService = inject(BookService);
public readonly bookId = input.required<string>();
public logs = toSignal(
this.bookService.getLogs(this.bookId()),
{initialValue: []}
);
}
But this gives me the following error:
RuntimeError: NG0950: Input "bookId" is required but no value is available yet. Find more at https://angular.dev/errors/NG0950
at _HistoryComponent.inputValueFn [as bookId] (core.mjs:61:19)
at <instance_members_initializer> (history.component.ts:21:55)
at new _HistoryComponent (history.component.ts:16:7)
It seems that toSignal() requires a value of the input signal to be available at construction. My options now seem to be as follows:
- Use
toSignal()in thengOnInitlifecycle-hook to be sure to have a value for thebookIdinput signal. But there I have no Injection context available (which is needed fortoSignal), so I would needwithInjectionContext()which would be a bit hacky. - Make the
bookIdinput not required, and handle empty values to not make the service call. This doesn't feel right, as I can make sure the input is always set by the parent component, so it should berequired. - Use
effect()instead oftoSignal(), see below.
The first two solutions feel very wrong, so I went with the effect() - currently I have the following working solution:
export class HistoryComponent {
private readonly bookService = inject(BookService);
public readonly bookId = input.required<string>();
public logs: BookLogs[] = [];
public constructor() {
effect(() => this.bookService.getLogs(this.bookId())
.subscribe(logs => this.logs = logs));
}
}
Is this really current best practice? I hope there's a better solution which uses toSignal().
resourcepattern but it requires 19.0 and relies on a still "experimental" API.