-
Notifications
You must be signed in to change notification settings - Fork 26.5k
Description
Which @angular/* package(s) are relevant/related to the feature request?
core
Description
First, we implemented a model (with validation logic and so on) with signals. Howver, since a signal/effect cannot be created anywhere (must be in injection context and outside of reactive context), we opted out and decided to use rxjs instead. This is fine, since the model is actually independent of Angular itself.
Additionally, we have a component that consists of pages. Each page can display validation errors found on that given page. The validation errors come from the model stated above.
Previously, while the model used signals, we were able to take advantage of the lazyness of the signal read operations. Consider the following simplified example:
// model class
readonly errors = computed<string[]>(() => ...);
// page class
readonly model = input.required<Model>();
readonly visited = signal(false);
readonly pageErrors = computed(() => this.visited() ? this.model().errors() : []);
So when we used (read) the pageErrors
we only evaluated the model's errors
if the page were ever visited.
Using signals in components is comfortable so we used the toSignal
from rxjs-interop, something like this:
// model class
readonly errors$: Observable<string[]> = ...
// page class
readonly modelErrors = toSignal(model.errors$, { initialValue: [] });
readonly pageErrors = computed(() => this.visited() ? this.modelErrors() : []);
However, the toSignal
call has a non-trivial consequence that it subscribes immediately, losing the lazy-evaluation aspect. The other way around (toObservable
) is pretty much the same, maybe even worse (since it uses effect
in its implementation that always runs at least once).
Proposed solution
I think the toSignal
and toObservable
should get a deeper integration, allowing us to avoid use-cases like this. It would be the best if all computed signal properties (lazy + memoized) could be kept when using toSignal
- only subscribe when the signal value is read, and unsubscribe when the signal's refcount becomes 0 (all its listeners are unsubscribed).
Alternatives considered
Currently there is no appropriate workaround, at least we could not find any. We could opt-out of using signals, but it has its advantages that we'd like to keep.