I have a problem with angular 17 signal effect. I try to reset a form in the effect when the facilities signal is updated.
I have this message error in the browser console:
NG0600: Writing to signals is not allowed in a
computedor aneffectby default. UseallowSignalWritesin theCreateEffectOptionsto enable this inside effects.
If I remove from the effect the this_form. Reset, no error in the console. If I add the effect option to allowSignalWrites it works, but I don't understand why as I don't write a signal, I just reset a form.
formResetEffect = effect(() => {
if (this.facilities()) {
this._form.reset({
disabled: false,
value: null
});
}}, {allowSignalWrites: true});
Could you help me to understand this behavior?
Thanks
UPDATE:
It appears that the issue appear only when I use the p-dropdown component from PrimeNG. I've examined the code of the p-dropdown in the GitHub repository, and this component now uses signals.
primeng dropdown github
Do you think the signal writing into the p-dropdown component could be the cause of the problem?
Here a stackblitz to reproduce the problem: stackblitz
Do you think the signal writing into the p-dropdown component could be the cause of the problem?
Yes. At least from my understanding. effect() works as intended.
Why?
effect() (as well as computed()) magically check deep down all function-calls if there is a any interaction with signals. Even if it's "hidden" in some functions.
I assume that FormGroup.reset() calls Dropdown() which triggers the set() of signals (see line 861-865 of primeng dropdown github).
Imagine it likes this:
- effect() // ✅ no signals
-- FormGroup.reset() // ✅ no signals
--- Dropdown() // ❌ calls "set()" of signals
Here as a example which makes it clear:
mySignal = signal("");
effReturn = effect(()=>{
this.method1();
}); // ❌ throws NG0600 without {allowSignalWrites: true}
method1(): void {
this.method2();
}
method2(): void {
mySignal.set("hello world");
}
So, again: effect() works as intended and allowSignalWrites flag has to be set here.
Some could ask now: why isn't allowSignalWrites flag set to true by default in the first place?
What I think: angular-devs want to (a) manual signal-sets as small as possible (rather use computed() to calculate signals) because (b) signals-sets will decrease readability your code.
In other words: calling set() within effect() should be the exception!
Anyways, in your example I think it's totally fine using effect() with allowSignalsWrites.
By the way:
The if-condition of the dropdown-basic-demo.ts:25 in your stackblitz-example is obsolete. cities() is always set per definition.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With