0
# Module Setup and Providers
1
2
Integration capabilities for NgRx Effects with Angular's module system and standalone applications, providing flexible setup options for different application architectures.
3
4
## Capabilities
5
6
### EffectsModule Class
7
8
NgModule for setting up effects in module-based Angular applications with support for root and feature-level configuration.
9
10
```typescript { .api }
11
/**
12
* NgModule for integrating effects into module-based Angular applications
13
*/
14
class EffectsModule {
15
/**
16
* Configure root-level effects for the application
17
* @param effects - Array of effect classes to register at root level
18
* @returns ModuleWithProviders for root effects configuration
19
*/
20
static forRoot(effects: Type<any>[]): ModuleWithProviders<EffectsRootModule>;
21
22
/**
23
* Configure feature-level effects for lazy-loaded modules
24
* @param effects - Array of effect classes to register at feature level
25
* @returns ModuleWithProviders for feature effects configuration
26
*/
27
static forFeature(effects: Type<any>[]): ModuleWithProviders<EffectsFeatureModule>;
28
}
29
30
class EffectsRootModule {}
31
class EffectsFeatureModule {}
32
```
33
34
**Usage Examples:**
35
36
```typescript
37
import { NgModule } from "@angular/core";
38
import { EffectsModule } from "@ngrx/effects";
39
import { StoreModule } from "@ngrx/store";
40
41
// Root module setup
42
@NgModule({
43
imports: [
44
StoreModule.forRoot({}),
45
EffectsModule.forRoot([
46
AppEffects,
47
RouterEffects,
48
AuthEffects
49
])
50
],
51
// ...
52
})
53
export class AppModule {}
54
55
// Feature module setup
56
@NgModule({
57
imports: [
58
StoreModule.forFeature('books', bookReducer),
59
EffectsModule.forFeature([
60
BookEffects,
61
BookSearchEffects
62
])
63
],
64
// ...
65
})
66
export class BooksModule {}
67
68
// Lazy-loaded feature module
69
@NgModule({
70
imports: [
71
RouterModule.forChild(routes),
72
StoreModule.forFeature('admin', adminReducer),
73
EffectsModule.forFeature([AdminEffects])
74
],
75
// ...
76
})
77
export class AdminModule {}
78
```
79
80
### provideEffects Function
81
82
Provider function for registering effects in standalone Angular applications and with the new provider-based configuration.
83
84
```typescript { .api }
85
/**
86
* Provides effects for standalone applications or provider-based configuration
87
* @param effects - Array of effect classes or effect creation functions
88
* @returns EnvironmentProviders for effects registration
89
*/
90
function provideEffects(...effects: Array<Type<unknown> | Record<string, FunctionalEffect>>): EnvironmentProviders;
91
92
type FunctionalEffect<Source extends () => Observable<unknown> = () => Observable<unknown>> =
93
Source & CreateEffectMetadata;
94
```
95
96
**Usage Examples:**
97
98
```typescript
99
import { bootstrapApplication } from "@angular/platform-browser";
100
import { provideStore } from "@ngrx/store";
101
import { provideEffects } from "@ngrx/effects";
102
103
// Standalone application bootstrap
104
bootstrapApplication(AppComponent, {
105
providers: [
106
// Store setup
107
provideStore({}),
108
109
// Effects setup with classes
110
provideEffects(
111
AppEffects,
112
UserEffects,
113
NotificationEffects
114
),
115
116
// Mix of classes and functional effects
117
provideEffects(
118
AuthEffects, // class
119
loadUserEffect, // functional effect
120
syncDataEffect // functional effect
121
)
122
]
123
});
124
125
// Feature route configuration
126
export const ADMIN_ROUTES: Route[] = [
127
{
128
path: '',
129
providers: [
130
provideStore(adminFeature),
131
provideEffects(AdminEffects, AuditEffects)
132
],
133
children: [
134
// ... child routes
135
]
136
}
137
];
138
139
// Testing setup with provideEffects
140
beforeEach(() => {
141
TestBed.configureTestingModule({
142
providers: [
143
provideStore(testReducer),
144
provideEffects(TestEffects),
145
provideMockActions(() => actions$)
146
]
147
});
148
});
149
```
150
151
### mergeEffects Function
152
153
Utility function for combining multiple effects into a single observable stream, useful for complex effect compositions.
154
155
```typescript { .api }
156
/**
157
* Merges multiple effects into a single observable stream
158
* @param effects - Array of observables or functions returning observables
159
* @returns Function returning merged observable of actions
160
*/
161
function mergeEffects(...effects: Array<Observable<Action> | (() => Observable<Action>)>): () => Observable<Action>;
162
```
163
164
**Usage Examples:**
165
166
```typescript
167
import { mergeEffects } from "@ngrx/effects";
168
169
// Combine multiple effect streams
170
const combinedUserEffects = mergeEffects(
171
// Observable streams
172
userLoadEffect$,
173
userUpdateEffect$,
174
175
// Effect functions
176
() => userDeleteEffect$,
177
() => userValidationEffect$
178
);
179
180
// Use in provider setup
181
bootstrapApplication(AppComponent, {
182
providers: [
183
provideStore({}),
184
provideEffects(
185
AuthEffects,
186
combinedUserEffects, // Merged effects as single provider
187
NotificationEffects
188
)
189
]
190
});
191
192
// Complex merging with conditional logic
193
const dynamicEffects = mergeEffects(
194
baseEffects$,
195
featureFlag.enabled ? advancedEffects$ : empty(),
196
development ? debugEffects$ : empty()
197
);
198
199
// Testing merged effects
200
const testEffects = mergeEffects(
201
mockEffect1$,
202
mockEffect2$,
203
() => mockEffect3$
204
);
205
```
206
207
### Effect Sources Management
208
209
Internal services for managing effect sources and lifecycle.
210
211
```typescript { .api }
212
/**
213
* Service managing effect source instances and conversion to action streams
214
*/
215
class EffectSources extends Subject<any> {
216
/**
217
* Add effect instances to the sources
218
* @param effectSourceInstance - Effect class instance to add
219
*/
220
addEffects(effectSourceInstance: any): void;
221
222
/**
223
* Convert effect sources to a stream of actions
224
* @returns Observable stream of all effect-generated actions
225
*/
226
toActions(): Observable<Action>;
227
}
228
229
/**
230
* Service responsible for running and managing effect lifecycle
231
*/
232
class EffectsRunner {
233
/**
234
* Start the effects runner and begin processing effects
235
*/
236
start(): void;
237
}
238
```
239
240
### Advanced Setup Patterns
241
242
**Conditional Effects Loading:**
243
244
```typescript
245
// Load effects based on feature flags
246
const effectsToLoad = [
247
CoreEffects,
248
...(featureFlags.newUserFlow ? [NewUserEffects] : []),
249
...(featureFlags.analytics ? [AnalyticsEffects] : [])
250
];
251
252
bootstrapApplication(AppComponent, {
253
providers: [
254
provideStore({}),
255
provideEffects(...effectsToLoad)
256
]
257
});
258
```
259
260
**Dynamic Effect Registration:**
261
262
```typescript
263
// Service for dynamically registering effects
264
@Injectable()
265
export class DynamicEffectsService {
266
constructor(private effectSources: EffectSources) {}
267
268
registerEffects(effectClass: Type<any>) {
269
const effectInstance = this.injector.get(effectClass);
270
this.effectSources.addEffects(effectInstance);
271
}
272
}
273
```
274
275
**Testing with Multiple Effect Sources:**
276
277
```typescript
278
describe('Feature Effects', () => {
279
let actions$: Observable<any>;
280
281
beforeEach(() => {
282
TestBed.configureTestingModule({
283
providers: [
284
provideStore(testReducer),
285
provideEffects(
286
FeatureEffects,
287
SharedEffects
288
),
289
provideMockActions(() => actions$)
290
]
291
});
292
});
293
});
294
```
295
296
## Injection Tokens
297
298
```typescript { .api }
299
/** Token for user-provided effects arrays */
300
const USER_PROVIDED_EFFECTS: InjectionToken<any[][]>;
301
302
/** Internal token for root-level effects */
303
const _ROOT_EFFECTS: InjectionToken<any[]>;
304
305
/** Internal token for feature-level effects */
306
const _FEATURE_EFFECTS: InjectionToken<any[]>;
307
```