@rx-signals/angular-provider
You can use this lib for an opinionated rx-signals integration into your Angular application.
It features Angular providers for rx-signals store and/or child-stores.
In addition, it features some pipes and directives to work with validation and optional-lenses.
Installation
npm install --save @rx-signals/angular-provider@3.0.0-rc14
If you have not yet installed the rx-signals store, please see @rx-signals/store documentation on how to install the latest 3.x version of that peer-dependency.
License
MIT
Usage
Modern usage without NgModule
In your bootstrapApplication
, just use provideStore()
.
This will provide a Store
singleton everywhere (so even lazy-loaded routes will receive the same store instance).
If you have functions performing setup with the store ((store: Store) => void
), you can pass 0 to N of those setup-functions as arguments to provideStore()
.
Optionally using child-stores on child-routes
If you're really sure a child-route should use its own child-store, you can do so by using provideChildStore()
in the corresponding routes providers array.
Make sure to read the documentation on child-stores.
Also, be aware that store-lifecycles might be a better option for your use-case.
Usage with classic NgModule
In the topmost module that should use the store (AppModule, SharedModule, CoreModule, or whatever it is for you), you can just import RxSignalsStoreModule
.
This will provide a Store
singleton everywhere (so even lazy-loaded feature-modules will receive the same instance).
Instead, if you have functions performing setup with the store ((store: Store) => void
), you can use RxSignalsStoreModule.withRootStore()
, passing as many of those setup-functions as arguments as you like.
You can also use RxSignalsStoreModule.withRootStore()
in your feature-modules (whether lazy or not) to pass corresponding setup-functions of those feature-modules.
You might be used to modules that come with forRoot()
and forFeature()
functions.
These names make no sense in case of the RxSignalsStoreModule, because the standard-case is to use a single store-instance in all your modules and thus, all these modules should call withRootStore()
.
See the next section on use-cases for withChildStore()
.
Optionally using child-stores
If you are really sure that you have a feature-module where you want to use a child-store (derived from the root-store that you get with RxSignalsStoreModule
or RxSignalsStoreModule.withRootStore()
), then you can do so by importing RxSignalsStoreModule.withChildStore()
.
Make sure to read the documentation on child-stores.
Also, be aware that store-lifecycles might be a better option for your use-case.
Setup effects
If you read about the concept about side-effect-isolation with the store, you know that the only side-effect that the functions passed to RxSignalsStoreModule.withRootStore()
and/or RxSignalsStoreModule.withChildStore()
are allowed to do is calling methods of the passed store.
All the signals being setup in this process should be free of side-effects (allowing you to call the setup-functions in your tests without any need of mockup).
Consequently, the side-effects must be injected to the store by corresponding calls to store.addEffect
.
In your unit-tests, you would then just mock the effects themselves by store.addEffect(effectId, () => someMockupReturn)
(so no need to mock anything else).