diff --git a/package-lock.json b/package-lock.json
index af6df0d..e7eb995 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2126,6 +2126,22 @@
"schema-utils": "^2.7.0"
}
},
+ "@ngrx/effects": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/@ngrx/effects/-/effects-11.0.1.tgz",
+ "integrity": "sha512-FJa0WVr0PcPgFXCv8i//RDAVV26pl0ieOLH3yDnZN0BH6/cDeUcKtWsWv+IAiJ63dFm9VedgNgwVo0I7CP9G+g==",
+ "requires": {
+ "tslib": "^2.0.0"
+ }
+ },
+ "@ngrx/store": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/@ngrx/store/-/store-11.0.1.tgz",
+ "integrity": "sha512-ULk+z7fXg1S0mbSXatHplvg8Rqj9Hglo6pVugaDgLdFR3DD5Wpl0cefvLBscaeZF9DGrLBoPZVlFq/LACRr6tA==",
+ "requires": {
+ "tslib": "^2.0.0"
+ }
+ },
"@ngtools/webpack": {
"version": "11.1.4",
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-11.1.4.tgz",
diff --git a/package.json b/package.json
index 5ce7ca6..f4443ac 100644
--- a/package.json
+++ b/package.json
@@ -51,6 +51,8 @@
"@angular/core": "~11.2.0",
"@angular/platform-browser": "^11.2.3",
"@angular/platform-browser-dynamic": "^11.2.3",
+ "@ngrx/effects": "^11.0.1",
+ "@ngrx/store": "^11.0.1",
"rxjs": "~6.6.0",
"tslib": "^2.0.0",
"zone.js": "~0.11.0"
diff --git a/projects/example-app/src/app/app.component.css b/projects/example-app/src/app/app.component.css
index 7c0e12a..999a045 100644
--- a/projects/example-app/src/app/app.component.css
+++ b/projects/example-app/src/app/app.component.css
@@ -1,4 +1,8 @@
.container {
display: grid;
- grid-template-columns: repeat(3, 1fr);
+ grid-template-columns: repeat(2, 1fr);
+}
+
+.container > * {
+ height: 300px;
}
diff --git a/projects/example-app/src/app/app.component.html b/projects/example-app/src/app/app.component.html
index 2fb04bc..9dbfddb 100644
--- a/projects/example-app/src/app/app.component.html
+++ b/projects/example-app/src/app/app.component.html
@@ -3,4 +3,5 @@
Example App
+
diff --git a/projects/example-app/src/app/app.module.ts b/projects/example-app/src/app/app.module.ts
index d5ce437..ca0c23f 100644
--- a/projects/example-app/src/app/app.module.ts
+++ b/projects/example-app/src/app/app.module.ts
@@ -8,6 +8,11 @@ import { LoadableComponentExampleComponent } from './components/loadable-compone
import { LoadingSpinnerComponent } from './components/loading-spinner/loading-spinner.component';
import { JsonErrorComponent } from './components/json-error/json-error.component';
import { SimpleLoadableComponentExampleComponent } from './components/simple-loadable-component-example/simple-loadable-component-example.component';
+import { NgrxExampleComponent } from './components/ngrx-example/ngrx-example.component';
+import { StoreModule } from '@ngrx/store';
+import { responseReducer } from './components/ngrx-example/reducer';
+import { EffectsModule } from '@ngrx/effects';
+import { LoadEffects } from './components/ngrx-example/effects';
@NgModule({
declarations: [
@@ -17,9 +22,14 @@ import { SimpleLoadableComponentExampleComponent } from './components/simple-loa
LoadableComponentExampleComponent,
LoadingSpinnerComponent,
JsonErrorComponent,
+ NgrxExampleComponent,
],
imports: [
BrowserModule,
+ StoreModule.forRoot({
+ response: responseReducer,
+ }),
+ EffectsModule.forRoot([LoadEffects]),
LoadableModule.forRoot({
defaultComponents: {
loading: LoadingSpinnerComponent,
diff --git a/projects/example-app/src/app/components/ngrx-example/actions.ts b/projects/example-app/src/app/components/ngrx-example/actions.ts
new file mode 100644
index 0000000..235bf90
--- /dev/null
+++ b/projects/example-app/src/app/components/ngrx-example/actions.ts
@@ -0,0 +1,16 @@
+import { createAction, props } from '@ngrx/store';
+
+export const load = createAction(
+ '[Ngrx Example] Load',
+ props<{ id: number; error: boolean }>()
+);
+
+export const loadSuccess = createAction(
+ '[Ngrx Example] Load success',
+ props<{ response: unknown }>()
+);
+
+export const loadError = createAction(
+ '[Ngrx Example] Load error',
+ props<{ error: unknown }>()
+);
diff --git a/projects/example-app/src/app/components/ngrx-example/effects.ts b/projects/example-app/src/app/components/ngrx-example/effects.ts
new file mode 100644
index 0000000..eb99558
--- /dev/null
+++ b/projects/example-app/src/app/components/ngrx-example/effects.ts
@@ -0,0 +1,23 @@
+import { Injectable } from '@angular/core';
+import { Actions, createEffect, ofType } from '@ngrx/effects';
+import { of } from 'rxjs';
+import { map, mergeMap, catchError } from 'rxjs/operators';
+import { LoadService } from '../../load.service';
+import { load, loadError, loadSuccess } from './actions';
+
+@Injectable()
+export class LoadEffects {
+ load$ = createEffect(() =>
+ this.actions$.pipe(
+ ofType(load),
+ mergeMap((action) =>
+ this.loadService.load(action.id, action.error).pipe(
+ map((response) => loadSuccess({ response })),
+ catchError((error) => of(loadError({ error })))
+ )
+ )
+ )
+ );
+
+ constructor(private actions$: Actions, private loadService: LoadService) {}
+}
diff --git a/projects/example-app/src/app/components/ngrx-example/ngrx-example.component.html b/projects/example-app/src/app/components/ngrx-example/ngrx-example.component.html
new file mode 100644
index 0000000..04cdbf3
--- /dev/null
+++ b/projects/example-app/src/app/components/ngrx-example/ngrx-example.component.html
@@ -0,0 +1,7 @@
+Ngrx example
+
+
+
+ Loaded
+ {{ loadable.value | json }}
+
diff --git a/projects/example-app/src/app/components/ngrx-example/ngrx-example.component.ts b/projects/example-app/src/app/components/ngrx-example/ngrx-example.component.ts
new file mode 100644
index 0000000..ccd2f88
--- /dev/null
+++ b/projects/example-app/src/app/components/ngrx-example/ngrx-example.component.ts
@@ -0,0 +1,18 @@
+import { Component } from '@angular/core';
+import { Store } from '@ngrx/store';
+import { load } from './actions';
+import { selectResponse } from './selector';
+
+@Component({
+ selector: 'app-ngrx-example',
+ templateUrl: './ngrx-example.component.html',
+})
+export class NgrxExampleComponent {
+ loadable$ = this.store.select(selectResponse);
+
+ constructor(private store: Store) {}
+
+ load(id: number, error: boolean): void {
+ this.store.dispatch(load({ id, error }));
+ }
+}
diff --git a/projects/example-app/src/app/components/ngrx-example/reducer.ts b/projects/example-app/src/app/components/ngrx-example/reducer.ts
new file mode 100644
index 0000000..4ea442c
--- /dev/null
+++ b/projects/example-app/src/app/components/ngrx-example/reducer.ts
@@ -0,0 +1,23 @@
+import { Action, createReducer, on } from '@ngrx/store';
+import {
+ errored,
+ idle,
+ loaded,
+ loading,
+} from 'projects/ngx-loadable/src/lib/loadable.constructors';
+import { Loadable } from 'projects/ngx-loadable/src/lib/loadable.type';
+import { load, loadError, loadSuccess } from './actions';
+
+const reducer = createReducer(
+ idle as Loadable,
+ on(load, (_) => loading),
+ on(loadSuccess, (_, { response }) => loaded(response)),
+ on(loadError, (_, { error }) => errored(error))
+);
+
+export function responseReducer(
+ state: Loadable | undefined,
+ action: Action
+): Loadable {
+ return reducer(state, action);
+}
diff --git a/projects/example-app/src/app/components/ngrx-example/selector.ts b/projects/example-app/src/app/components/ngrx-example/selector.ts
new file mode 100644
index 0000000..66db8aa
--- /dev/null
+++ b/projects/example-app/src/app/components/ngrx-example/selector.ts
@@ -0,0 +1,6 @@
+import { createFeatureSelector } from '@ngrx/store';
+import { Loadable } from 'projects/ngx-loadable/src/lib/loadable.type';
+
+export const selectResponse = createFeatureSelector>(
+ 'response'
+);