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 likenextto 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;Signalis the "read-only" version ofWritableSignal.For this case, you should subscribe to your observable, and set the signal in the callback.
If
AppServiceusesHttpClientbehind 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
DestroyReffor this rather than theOnDestroy.ngOnDestroyhook.And finally, if you still want to use
toSignal, yourtranslationsfield has to be of typeSignal. But then, yourchangeValuemethod will no longer work asSignaldoes not have a methodset.