I have the following simple code on my component:
import {Component, effect, signal, WritableSignal} from '@angular/core';
import {AppService} from "../app.service";
import {toSignal} from "@angular/core/rxjs-interop";
@Component({
selector: 'app-parent',
templateUrl: './parent.component.html',
styleUrls: ['./parent.component.css']
})
export class ParentComponent {
translations: WritableSignal<{data: {}}> = signal({data: []});
constructor( private appService: AppService) {
this.translations = toSignal(this.appService.getTranslations());
effect(() => {
console.log('translation API:', this.translations());
});
}
changeValue(): void {
this.translations.set({data: {hello: 'hallo'}})
}
}
FYI: this.appService.getTranslations()
returns an observable
I'm trying out the new features released with Angular v16, and how to convert Observables to Signals.
What I wanted to do on the above code is, I change the value of the WritableSignal Object and log its value on change.
I'm getting the following error:
TS2739: Type 'Signal ' is missing the following properties from type 'WritableSignal{ data: {}; }>': set, update, mutate, asReadonly
Help please.
Observables are "read-only", and thus unsuitable for a
WritableSignal
. You can subscribe to them, but not call a method likenext
to push new data.Subjects could potentially be converted to a
WritableSignal
, but there is no utility method as far as I know.What the error you get means is that the object
Signal
, which is returned bytoSignal
, is missing properties/methods fromWritableSignal
, all the "write" ones;Signal
is the "read-only" version ofWritableSignal
.For this case, you should subscribe to your observable, and set the signal in the callback.
If
AppService
usesHttpClient
behind the scenes, no need to unsubscribe since it is done automatically on the first success callback.If it's not using
HttpClient
, and you only want to retrieve the data one time on construction, use thefirst()
RxJS operator.If it's not using
HttpClient
, and you need to get regular updates, you have to unsubscribe on destroy.Since you are testing the Angular 16 developer preview, you can use the new
DestroyRef
for this rather than theOnDestroy.ngOnDestroy
hook.And finally, if you still want to use
toSignal
, yourtranslations
field has to be of typeSignal
. But then, yourchangeValue
method will no longer work asSignal
does not have a methodset
.