Reputation: 311
I'm working with signals in Angular 17 and I want to update the value of a signal, but it throws this 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.
I've been looking for information about it but haven't found anything useful.
Basically what I'm trying to do is update the signal value after a condition, this is all called from the Effect method:
Component:
export class LibGridViewComponent {
private _libSubjectsGiproService = inject(LibSubjectsGiproService)
constructor() {
effect(() => {
this.getValuesBySearchSignal()
});
}
getValuesBySearchSignal(displaySource?: any): any[] {
let testArr = [
{
"name": "B179 HEPATITIS VIRAL AGUDA NO ESPECIFICADA",
"value": "B179"
},
{
"name": "B980 HELICOBACTER PYLORI [H.PYLORI] COMO LA CAUSA DE ENFERMEDADES CLASIFICADAS EN OTROS CAPITULOS",
"value": "B980"
},
{
"name": "C799 TUMOR MALIGNO SECUNDARIO - SITIO NO ESPECIFICADO",
"value": "C799"
},
]
let searchTerm = this._libSubjectsGiproService.getSearchTerm()
let foundSource:any = []
if (searchTerm && searchTerm != '') {
foundSource = testArr.filter(i => i.name.toLowerCase().includes(searchTerm));
let currentSource = this.initialDisplaySource.value;
this.initialDisplaySource.next([...currentSource, ...foundSource]);
this._libSubjectsGiproService.setSearchTerm('')
} else {
this.initialDisplaySource.next([])
}
return this.initialDisplaySource.value
}
}
Service:
export class LibSubjectsGiproService {
searchTerm: WritableSignal<any> = signal<any>('');
setSearchTerm(value: any) {
this.searchTerm.set(value);
}
getSearchTerm() {
return this.searchTerm();
}
}
UPDATE: I'm gonna try to add more context to what I'm trying to do, I have a grid view and one of its columns is a Select with the option to search for the item based on user input. It is possible to add more rows to the table, but the entry with which the elements are searched remains with the previously entered value, the idea is that each time a new row is added the signal is empty, therefore initialDisplaySource should also be empty until the user starts typing.
Upvotes: 2
Views: 3158
Reputation: 933
Warning: effect is currently in developer preview
Code sample about how to enable the flag of "allowSignalsWrite":
constructor() {
effect(() => {
this.getValuesBySearchSignal()
}, { allowSignalWrites: true } );
}
It isn't recommended and is not enabled by default because calling a signal could create a cycle that causes the browser to freeze.
This could result in a significant issue that is hard to detect as the application grows.
Update 10/07/2024 Communicate of angular:
Upvotes: 1
Reputation: 57696
Although this can be done with effect
this might not be the best solution, since updating the signal will trigger the effect and you have to do the additional work of setting the signal again, which in the docs is frowned upon, instead go for the html events that happen only when the user changes the input.
If you are certain you want the effect method, then go for the other suggestion in my answer.
Basically we trigger the function getValuesBySearchSignal
when the user types on the select, since you have not shared the HTML, we can use (ngModelChange)
, (change)
, (input)
this events can trigger the function and you can reset the signal and do anything else.
<input [(ngModel)]="" (ngModelChange)="getValuesBySearchSignal()"/>
We can just use allowSignalWrites
as true in the effect options.
constructor() {
effect(() => {
this.getValuesBySearchSignal()
}, {
allowSignalWrites: true
});
}
Just be aware of the downsides of allowSignalWrites as stated in the documentation
Upvotes: 1