diff --git a/angular.json b/angular.json
index 561d26b..e011b83 100644
--- a/angular.json
+++ b/angular.json
@@ -34,7 +34,7 @@
}
}
},
- "angular-redux-demo": {
+ "angular-redux-simple-demo": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
@@ -64,25 +64,25 @@
"skipTests": true
}
},
- "root": "projects/angular-redux-demo",
- "sourceRoot": "projects/angular-redux-demo/src",
+ "root": "projects/angular-redux-simple-demo",
+ "sourceRoot": "projects/angular-redux-simple-demo/src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"options": {
- "outputPath": "dist/angular-redux-demo",
- "index": "projects/angular-redux-demo/src/index.html",
- "browser": "projects/angular-redux-demo/src/main.ts",
+ "outputPath": "dist/angular-redux-simple-demo",
+ "index": "projects/angular-redux-simple-demo/src/index.html",
+ "browser": "projects/angular-redux-simple-demo/src/main.ts",
"polyfills": ["zone.js"],
- "tsConfig": "projects/angular-redux-demo/tsconfig.app.json",
+ "tsConfig": "projects/angular-redux-simple-demo/tsconfig.app.json",
"assets": [
{
"glob": "**/*",
- "input": "projects/angular-redux-demo/public"
+ "input": "projects/angular-redux-simple-demo/public"
}
],
- "styles": ["projects/angular-redux-demo/src/styles.css"],
+ "styles": ["projects/angular-redux-simple-demo/src/styles.css"],
"scripts": []
},
"configurations": {
@@ -113,10 +113,79 @@
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
- "buildTarget": "angular-redux-demo:build:production"
+ "buildTarget": "angular-redux-simple-demo:build:production"
},
"development": {
- "buildTarget": "angular-redux-demo:build:development"
+ "buildTarget": "angular-redux-simple-demo:build:development"
+ }
+ },
+ "defaultConfiguration": "development"
+ },
+ "extract-i18n": {
+ "builder": "@angular-devkit/build-angular:extract-i18n"
+ }
+ }
+ },
+ "angular-redux-injector-demo": {
+ "projectType": "application",
+ "schematics": {},
+ "root": "projects/angular-redux-injector-demo",
+ "sourceRoot": "projects/angular-redux-injector-demo/src",
+ "prefix": "app",
+ "architect": {
+ "build": {
+ "builder": "@angular-devkit/build-angular:application",
+ "options": {
+ "outputPath": "dist/angular-redux-injector-demo",
+ "index": "projects/angular-redux-injector-demo/src/index.html",
+ "browser": "projects/angular-redux-injector-demo/src/main.ts",
+ "polyfills": [
+ "zone.js"
+ ],
+ "tsConfig": "projects/angular-redux-injector-demo/tsconfig.app.json",
+ "assets": [
+ {
+ "glob": "**/*",
+ "input": "projects/angular-redux-injector-demo/public"
+ }
+ ],
+ "styles": [
+ "projects/angular-redux-injector-demo/src/styles.css"
+ ],
+ "scripts": []
+ },
+ "configurations": {
+ "production": {
+ "budgets": [
+ {
+ "type": "initial",
+ "maximumWarning": "500kB",
+ "maximumError": "1MB"
+ },
+ {
+ "type": "anyComponentStyle",
+ "maximumWarning": "2kB",
+ "maximumError": "4kB"
+ }
+ ],
+ "outputHashing": "all"
+ },
+ "development": {
+ "optimization": false,
+ "extractLicenses": false,
+ "sourceMap": true
+ }
+ },
+ "defaultConfiguration": "production"
+ },
+ "serve": {
+ "builder": "@angular-devkit/build-angular:dev-server",
+ "configurations": {
+ "production": {
+ "buildTarget": "angular-redux-injector-demo:build:production"
+ },
+ "development": {
+ "buildTarget": "angular-redux-injector-demo:build:development"
}
},
"defaultConfiguration": "development"
diff --git a/projects/angular-redux-demo/public/favicon.ico b/projects/angular-redux-injector-demo/public/favicon.ico
similarity index 100%
rename from projects/angular-redux-demo/public/favicon.ico
rename to projects/angular-redux-injector-demo/public/favicon.ico
diff --git a/projects/angular-redux-injector-demo/src/app/app.component.ts b/projects/angular-redux-injector-demo/src/app/app.component.ts
new file mode 100644
index 0000000..bd9a80f
--- /dev/null
+++ b/projects/angular-redux-injector-demo/src/app/app.component.ts
@@ -0,0 +1,27 @@
+import { Component, EnvironmentInjector, inject } from '@angular/core';
+import { injectSelector, injectDispatch } from '@reduxjs/angular-redux';
+import { incrementByRandomNumber } from './store/counter-slice';
+import { AppDispatch, RootState } from './store';
+
+@Component({
+ selector: 'app-root',
+ standalone: true,
+ template: `
+
+
{{ count() }}
+ @if (isLoading()) {
+ Loading...
+ }
+ `,
+})
+export class AppComponent {
+ injector = inject(EnvironmentInjector);
+ count = injectSelector((state: RootState) => state.counter.value);
+ isLoading = injectSelector((state: RootState) => state.counter.isLoading);
+ dispatch = injectDispatch();
+ incrementByRandomNumber = () => {
+ this.dispatch(incrementByRandomNumber({ injector: this.injector }));
+ };
+}
diff --git a/projects/angular-redux-demo/src/app/app.config.ts b/projects/angular-redux-injector-demo/src/app/app.config.ts
similarity index 100%
rename from projects/angular-redux-demo/src/app/app.config.ts
rename to projects/angular-redux-injector-demo/src/app/app.config.ts
diff --git a/projects/angular-redux-injector-demo/src/app/services/random-number.service.ts b/projects/angular-redux-injector-demo/src/app/services/random-number.service.ts
new file mode 100644
index 0000000..1fc4506
--- /dev/null
+++ b/projects/angular-redux-injector-demo/src/app/services/random-number.service.ts
@@ -0,0 +1,12 @@
+import { Injectable } from '@angular/core';
+
+@Injectable({ providedIn: 'root' })
+export class RandomNumberService {
+ getRandomNumber() {
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ resolve(Math.floor(Math.random() * 100));
+ }, 1000);
+ });
+ }
+}
diff --git a/projects/angular-redux-injector-demo/src/app/store/counter-slice.ts b/projects/angular-redux-injector-demo/src/app/store/counter-slice.ts
new file mode 100644
index 0000000..ba67c31
--- /dev/null
+++ b/projects/angular-redux-injector-demo/src/app/store/counter-slice.ts
@@ -0,0 +1,38 @@
+import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
+import { inject } from '@angular/core';
+import { RandomNumberService } from '../services/random-number.service';
+import {
+ asyncRunInInjectionContext,
+ RunInInjectionContextProps,
+} from '../utils/async-run-in-injection-context';
+
+export const incrementByRandomNumber = createAsyncThunk(
+ 'counter/incrementByAmountFromService',
+ (arg: RunInInjectionContextProps<{}>, _thunkAPI) => {
+ return asyncRunInInjectionContext(arg.injector, async () => {
+ const service = inject(RandomNumberService);
+ const newCount = await service.getRandomNumber();
+ return newCount;
+ });
+ },
+);
+
+export const counterSlice = createSlice({
+ name: 'counter',
+ initialState: {
+ value: 0,
+ isLoading: false,
+ },
+ reducers: {},
+ extraReducers: (builder) => {
+ builder.addCase(incrementByRandomNumber.fulfilled, (state, action) => {
+ state.isLoading = false;
+ state.value += action.payload;
+ });
+ builder.addCase(incrementByRandomNumber.pending, (state) => {
+ state.isLoading = true;
+ });
+ },
+});
+
+export default counterSlice.reducer;
diff --git a/projects/angular-redux-demo/src/app/store/index.ts b/projects/angular-redux-injector-demo/src/app/store/index.ts
similarity index 100%
rename from projects/angular-redux-demo/src/app/store/index.ts
rename to projects/angular-redux-injector-demo/src/app/store/index.ts
diff --git a/projects/angular-redux-injector-demo/src/app/utils/async-run-in-injection-context.ts b/projects/angular-redux-injector-demo/src/app/utils/async-run-in-injection-context.ts
new file mode 100644
index 0000000..e188b4e
--- /dev/null
+++ b/projects/angular-redux-injector-demo/src/app/utils/async-run-in-injection-context.ts
@@ -0,0 +1,24 @@
+import { EnvironmentInjector, runInInjectionContext } from '@angular/core';
+
+export const asyncRunInInjectionContext = (
+ injector: EnvironmentInjector,
+ fn: () => Promise,
+) => {
+ return new Promise((resolve, reject) => {
+ runInInjectionContext(injector, () => {
+ fn()
+ .then((value) => {
+ resolve(value);
+ })
+ .catch((error) => {
+ reject(error);
+ });
+ });
+ });
+};
+
+export type RunInInjectionContextProps<
+ T extends object,
+> = T & {
+ injector: EnvironmentInjector;
+};
diff --git a/projects/angular-redux-injector-demo/src/index.html b/projects/angular-redux-injector-demo/src/index.html
new file mode 100644
index 0000000..b17f9d3
--- /dev/null
+++ b/projects/angular-redux-injector-demo/src/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+ AngularReduxInjectorDemo
+
+
+
+
+
+
+
+
diff --git a/projects/angular-redux-injector-demo/src/main.ts b/projects/angular-redux-injector-demo/src/main.ts
new file mode 100644
index 0000000..35b00f3
--- /dev/null
+++ b/projects/angular-redux-injector-demo/src/main.ts
@@ -0,0 +1,6 @@
+import { bootstrapApplication } from '@angular/platform-browser';
+import { appConfig } from './app/app.config';
+import { AppComponent } from './app/app.component';
+
+bootstrapApplication(AppComponent, appConfig)
+ .catch((err) => console.error(err));
diff --git a/projects/angular-redux-demo/src/styles.css b/projects/angular-redux-injector-demo/src/styles.css
similarity index 100%
rename from projects/angular-redux-demo/src/styles.css
rename to projects/angular-redux-injector-demo/src/styles.css
diff --git a/projects/angular-redux-injector-demo/tsconfig.app.json b/projects/angular-redux-injector-demo/tsconfig.app.json
new file mode 100644
index 0000000..e40712b
--- /dev/null
+++ b/projects/angular-redux-injector-demo/tsconfig.app.json
@@ -0,0 +1,15 @@
+/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
+/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../../out-tsc/app",
+ "types": []
+ },
+ "files": [
+ "src/main.ts"
+ ],
+ "include": [
+ "src/**/*.d.ts"
+ ]
+}
diff --git a/projects/angular-redux-simple-demo/public/favicon.ico b/projects/angular-redux-simple-demo/public/favicon.ico
new file mode 100644
index 0000000..57614f9
Binary files /dev/null and b/projects/angular-redux-simple-demo/public/favicon.ico differ
diff --git a/projects/angular-redux-demo/src/app/app.component.ts b/projects/angular-redux-simple-demo/src/app/app.component.ts
similarity index 100%
rename from projects/angular-redux-demo/src/app/app.component.ts
rename to projects/angular-redux-simple-demo/src/app/app.component.ts
diff --git a/projects/angular-redux-simple-demo/src/app/app.config.ts b/projects/angular-redux-simple-demo/src/app/app.config.ts
new file mode 100644
index 0000000..8f1092f
--- /dev/null
+++ b/projects/angular-redux-simple-demo/src/app/app.config.ts
@@ -0,0 +1,10 @@
+import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
+import { provideRedux } from '@reduxjs/angular-redux';
+import { store } from './store';
+
+export const appConfig: ApplicationConfig = {
+ providers: [
+ provideZoneChangeDetection({ eventCoalescing: true }),
+ provideRedux({ store }),
+ ],
+};
diff --git a/projects/angular-redux-demo/src/app/store/counter-slice.ts b/projects/angular-redux-simple-demo/src/app/store/counter-slice.ts
similarity index 100%
rename from projects/angular-redux-demo/src/app/store/counter-slice.ts
rename to projects/angular-redux-simple-demo/src/app/store/counter-slice.ts
diff --git a/projects/angular-redux-simple-demo/src/app/store/index.ts b/projects/angular-redux-simple-demo/src/app/store/index.ts
new file mode 100644
index 0000000..0e410ac
--- /dev/null
+++ b/projects/angular-redux-simple-demo/src/app/store/index.ts
@@ -0,0 +1,13 @@
+import { configureStore } from '@reduxjs/toolkit';
+import counterReducer from './counter-slice';
+
+export const store = configureStore({
+ reducer: {
+ counter: counterReducer,
+ },
+});
+
+// Infer the `RootState` and `AppDispatch` types from the store itself
+export type RootState = ReturnType;
+// Inferred type: {counter: CounterState}
+export type AppDispatch = typeof store.dispatch;
diff --git a/projects/angular-redux-demo/src/index.html b/projects/angular-redux-simple-demo/src/index.html
similarity index 100%
rename from projects/angular-redux-demo/src/index.html
rename to projects/angular-redux-simple-demo/src/index.html
diff --git a/projects/angular-redux-demo/src/main.ts b/projects/angular-redux-simple-demo/src/main.ts
similarity index 100%
rename from projects/angular-redux-demo/src/main.ts
rename to projects/angular-redux-simple-demo/src/main.ts
diff --git a/projects/angular-redux-simple-demo/src/styles.css b/projects/angular-redux-simple-demo/src/styles.css
new file mode 100644
index 0000000..90d4ee0
--- /dev/null
+++ b/projects/angular-redux-simple-demo/src/styles.css
@@ -0,0 +1 @@
+/* You can add global styles to this file, and also import other style files */
diff --git a/projects/angular-redux-demo/tsconfig.app.json b/projects/angular-redux-simple-demo/tsconfig.app.json
similarity index 100%
rename from projects/angular-redux-demo/tsconfig.app.json
rename to projects/angular-redux-simple-demo/tsconfig.app.json