Reputation: 122
Usually you would use effect(() => ...)
to react to a signal change.
Unfortunately it seems like effects only run as soon as the component is fully initialized and therefore during/after ngAfterViewInit
.
In our case we have to sync component's input data to a scoped service as soon as the input is set and want to use it inside ngAfterViewInit
already which does not work with signal-inputs.
The way with "classic" @Input
s has been to create a setter that runs before/during ngOnChanges
. Therefore the data is already available during ngAfterViewInit
.
Lifecycle order:
constructor
transform-method of signal-inputs
@Input setter
ngOnChanges
ngOnInit
ngAfterViewInit
Execution of inline defined effects (e.g. private signalEffect = effect(() => ...)
)
Execution of constructor-defined effects
So far, I have not been able to think of a better way to transport the data of a signal input to the service than using effect.
However, this will execute only after ngAfterViewInit.
Regarding (mis)using a signal's transform-method it would feel totally wrong. Nevertheless it would be executed at the expected time on setting the input. However, this is likely to cause problems with a risk that I cannot currently assess and it might also be not comprehensible for future development.
Using the @Input setter, on the other hand, is a tried and tested variant that processes data at the earliest possible point in time. However, deviating from the signal input for this is of course annoying.
I have not yet found a source online as to whether the problem should be approached differently. Unfortunately, an effect cannot be configured in this respect.
Converting a signal into an Observable + Subscribe does not change anything, as an effect is also used by the toObservable under the hood.
What are other people's thoughts on this? Should I just rely on the "classic" @Input
+ set
or is there an unknown approach with signals?
Upvotes: 2
Views: 1273
Reputation: 122
As commented by @m-g the way to go with signals seems to be falling back to ngOnChanges
. It's maybe just a little less concise than Input-setters but should not have any negative effects on performance.
See also https://dev.to/angular/angular-setters-vs-ngonchanges-which-one-is-better-4f2b
So the final solution for propagating signals' changes apart from the (for the usecase of propagating data) unrecommended effect
would look like this:
myData = input<ValueType>();
ngOnChanges({ myData } : {myData?: SimpleChange & { currentValue: ValueType }}){
if (myData !== undefined){
this.service.sync(myData.currentValue)
}
}
Upvotes: 2