Imagine standard situation in Angular: You need to fetch data from server for some entity ID. Entity Id is a Signal and you want the fetched data to be signal too.
Something like this feels natural:
@Component({
selector: 'my-app',
standalone: true,
imports: [CommonModule],
template: `
<code>{{roles()}}</code>
`,
})
export class App {
userId: Signal<string> = signal('userA');
roles = computed(() => toSignal(getRoles(this.userId())));
}
//this could be api service sending http request
const getRoles = (userId: string) => {
return userId === 'userA' ? of([1, 2, 3]) : of([1]);
};
but there is a runtime errror in browser console:
Error: NG0203: toSignal() can only be used within an injection context such as a constructor, a factory function, a field initializer, or a function used with `runInInjectionContext`. Find more at https://angular.io/errors/NG0203
UPDATE: I also tried to provide Injector into toSignal
:
constructor(private injector: Injector) {}
userId: Signal<string> = signal('userA');
roles = computed(() =>
toSignal(getRoles(this.userId()), { injector: this.injector })()
);
but then another runtime error:
Error: NG0600: Writing to signals is not allowed in a `computed` or an `effect` by default. Use `allowSignalWrites` in the `CreateEffectOptions` to enable this inside effects.
allowSignalWrites
option forcomputed()
method. I checked the source code, but I couldn't find anything suspicious. You should create a GitHub issue for this since it's a really common use case. Also, this is still in the Developer Preview so these issues are expected I guess. – VerdaverdantSignal<Signal<Roles[]>>
and then have to dereference it twiceroles()()
. – Kelvin