Compare commits
No commits in common. "610ed791f0cf5ed2856cf84738ba10504d2dee09" and "8e026944aaffd7ef6441e4c4b8cfe8cf56b80e63" have entirely different histories.
610ed791f0
...
8e026944aa
12 changed files with 97 additions and 90 deletions
29
package-lock.json
generated
29
package-lock.json
generated
|
@ -15,6 +15,8 @@
|
||||||
"@angular/platform-browser": "^20.0.0",
|
"@angular/platform-browser": "^20.0.0",
|
||||||
"@angular/router": "^20.0.0",
|
"@angular/router": "^20.0.0",
|
||||||
"@ngrx/signals": "^19.2.1",
|
"@ngrx/signals": "^19.2.1",
|
||||||
|
"@ngrx/store": "^19.2.1",
|
||||||
|
"@ngrx/store-devtools": "^19.2.1",
|
||||||
"rxjs": "~7.8.0",
|
"rxjs": "~7.8.0",
|
||||||
"tslib": "^2.3.0"
|
"tslib": "^2.3.0"
|
||||||
},
|
},
|
||||||
|
@ -2244,6 +2246,33 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@ngrx/store": {
|
||||||
|
"version": "19.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@ngrx/store/-/store-19.2.1.tgz",
|
||||||
|
"integrity": "sha512-c5vQId7YoAhM0y4HASrz9mtLju+28vJspd6OBlhPbBlSae8GN8m9S/oav+8LaSY19yh95cZ5B/nMcLNNWgL/jA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@angular/core": "^19.0.0",
|
||||||
|
"rxjs": "^6.5.3 || ^7.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@ngrx/store-devtools": {
|
||||||
|
"version": "19.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@ngrx/store-devtools/-/store-devtools-19.2.1.tgz",
|
||||||
|
"integrity": "sha512-gj1YO+4yl6D0l9vzLWdw07TQSu5UPKgsSLsNJfDLXraaLCUcB8voAp4J7zohN8qR5ixDuHeMoiSSVuklQ75u2w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@angular/core": "^19.0.0",
|
||||||
|
"@ngrx/store": "19.2.1",
|
||||||
|
"rxjs": "^6.5.3 || ^7.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@npmcli/agent": {
|
"node_modules/@npmcli/agent": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-3.0.0.tgz",
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
"@angular/platform-browser": "^20.0.0",
|
"@angular/platform-browser": "^20.0.0",
|
||||||
"@angular/router": "^20.0.0",
|
"@angular/router": "^20.0.0",
|
||||||
"@ngrx/signals": "^19.2.1",
|
"@ngrx/signals": "^19.2.1",
|
||||||
|
"@ngrx/store": "^19.2.1",
|
||||||
|
"@ngrx/store-devtools": "^19.2.1",
|
||||||
"rxjs": "~7.8.0",
|
"rxjs": "~7.8.0",
|
||||||
"tslib": "^2.3.0"
|
"tslib": "^2.3.0"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,29 @@
|
||||||
import { ApplicationConfig, provideBrowserGlobalErrorListeners, provideZonelessChangeDetection } from '@angular/core';
|
import {
|
||||||
|
ApplicationConfig,
|
||||||
|
importProvidersFrom,
|
||||||
|
isDevMode,
|
||||||
|
provideBrowserGlobalErrorListeners,
|
||||||
|
provideZonelessChangeDetection,
|
||||||
|
} from '@angular/core';
|
||||||
|
import { StoreModule } from '@ngrx/store';
|
||||||
|
import { provideStoreDevtools } from '@ngrx/store-devtools';
|
||||||
|
import { appStateReducer } from './state/state.reducer';
|
||||||
|
|
||||||
export const appConfig: ApplicationConfig = {
|
export const appConfig: ApplicationConfig = {
|
||||||
providers: [provideBrowserGlobalErrorListeners(), provideZonelessChangeDetection()],
|
providers: [
|
||||||
|
provideBrowserGlobalErrorListeners(),
|
||||||
|
provideZonelessChangeDetection(),
|
||||||
|
importProvidersFrom(
|
||||||
|
StoreModule.forRoot({
|
||||||
|
app: appStateReducer,
|
||||||
|
})
|
||||||
|
),
|
||||||
|
provideStoreDevtools({
|
||||||
|
maxAge: 25,
|
||||||
|
logOnly: !isDevMode(),
|
||||||
|
autoPause: true,
|
||||||
|
trace: false,
|
||||||
|
traceLimit: 75,
|
||||||
|
}),
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<main>
|
<main>
|
||||||
@switch (currentView()) {
|
@switch (currentView$ | async) {
|
||||||
@default {
|
@default {
|
||||||
<app-starting-point></app-starting-point>
|
<app-starting-point></app-starting-point>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
import { patchState, signalStore, withMethods, withState } from '@ngrx/signals';
|
|
||||||
|
|
||||||
export type AppState = {
|
|
||||||
currentView: CurrentView;
|
|
||||||
};
|
|
||||||
|
|
||||||
export enum CurrentView {
|
|
||||||
StartingPoint = 'startingPoint',
|
|
||||||
}
|
|
||||||
|
|
||||||
const initialState: AppState = {
|
|
||||||
currentView: CurrentView.StartingPoint,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const AppStateStore = signalStore(
|
|
||||||
{ providedIn: 'root' },
|
|
||||||
withState(initialState),
|
|
||||||
withMethods(store => ({
|
|
||||||
updateCurrentView: (currentView: CurrentView) =>
|
|
||||||
patchState(store, () => ({
|
|
||||||
...store,
|
|
||||||
currentView,
|
|
||||||
})),
|
|
||||||
}))
|
|
||||||
);
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
import { AsyncPipe } from '@angular/common';
|
||||||
import { ChangeDetectionStrategy, Component, inject, OnInit } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, inject, OnInit } from '@angular/core';
|
||||||
import { AppStateStore } from './app.state';
|
import { select, Store } from '@ngrx/store';
|
||||||
|
import { selectCurrentView } from './state/state.selectors';
|
||||||
import { StartingPoint } from './views/starting-point/starting-point';
|
import { StartingPoint } from './views/starting-point/starting-point';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -7,11 +9,12 @@ import { StartingPoint } from './views/starting-point/starting-point';
|
||||||
templateUrl: './app.html',
|
templateUrl: './app.html',
|
||||||
styleUrl: './app.scss',
|
styleUrl: './app.scss',
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
imports: [StartingPoint],
|
imports: [AsyncPipe, StartingPoint],
|
||||||
})
|
})
|
||||||
export class App implements OnInit {
|
export class App implements OnInit {
|
||||||
private readonly state = inject(AppStateStore);
|
private readonly store$ = inject(Store);
|
||||||
readonly currentView = this.state.currentView;
|
|
||||||
|
readonly currentView$ = this.store$.pipe(select(selectCurrentView));
|
||||||
|
|
||||||
ngOnInit(): void {}
|
ngOnInit(): void {}
|
||||||
}
|
}
|
||||||
|
|
15
src/app/state/state.reducer.ts
Normal file
15
src/app/state/state.reducer.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { createReducer } from '@ngrx/store';
|
||||||
|
|
||||||
|
export interface AppState {
|
||||||
|
currentView: CurrentView;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum CurrentView {
|
||||||
|
StartingPoint = 'startingPoint',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const initialState: AppState = {
|
||||||
|
currentView: CurrentView.StartingPoint,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const appStateReducer = createReducer(initialState);
|
6
src/app/state/state.selectors.ts
Normal file
6
src/app/state/state.selectors.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import { createFeatureSelector, createSelector } from '@ngrx/store';
|
||||||
|
import { AppState } from './state.reducer';
|
||||||
|
|
||||||
|
export const selectAppState = createFeatureSelector<AppState>('app');
|
||||||
|
|
||||||
|
export const selectCurrentView = createSelector(selectAppState, (state: AppState) => state.currentView);
|
|
@ -1,24 +1,7 @@
|
||||||
|
<h1>
|
||||||
|
Hello {{ name() }}
|
||||||
|
</h1>
|
||||||
<form [formGroup]="form">
|
<form [formGroup]="form">
|
||||||
<div class="name">
|
<label for="name">Your Name: </label>
|
||||||
<label for="name">Your Name: </label>
|
<input id="name" type="text" formControlName="name">
|
||||||
<input id="name" type="text" formControlName="name">
|
|
||||||
</div>
|
|
||||||
<div class="gender">
|
|
||||||
<label for="gender">Your Gender:</label>
|
|
||||||
<select id="gender" formControlName="gender">
|
|
||||||
<option value="">--Please select a gender--</option>
|
|
||||||
@for (option of genders(); track $index) {
|
|
||||||
<option value="{{ option.value }}">{{ option.desc }}</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="after-high-school">
|
|
||||||
<label for="after-high-school">What You're Doing After Graduation:</label>
|
|
||||||
<select id="after-high-school" formControlName="afterHighSchool">
|
|
||||||
<option value="">--Please select an option--</option>
|
|
||||||
@for (option of afterHighSchoolOptions(); track $index) {
|
|
||||||
<option value="{{ option.value }}">{{ option.desc }}</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { effect } from '@angular/core';
|
import { patchState, signalStore, withMethods, withState } from '@ngrx/signals';
|
||||||
import { getState, patchState, signalStore, withHooks, withMethods, withState } from '@ngrx/signals';
|
|
||||||
|
|
||||||
export type StartingPointState = {
|
export type StartingPointState = {
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -34,13 +33,5 @@ export const StartingPointStateStore = signalStore(
|
||||||
gender: gender ?? Gender.Undefined,
|
gender: gender ?? Gender.Undefined,
|
||||||
afterHighSchool: afterHighSchool ?? AfterHighSchool.Undefined,
|
afterHighSchool: afterHighSchool ?? AfterHighSchool.Undefined,
|
||||||
})),
|
})),
|
||||||
})),
|
}))
|
||||||
withHooks({
|
|
||||||
onInit: store => {
|
|
||||||
effect(() => {
|
|
||||||
const state = getState(store);
|
|
||||||
console.log(state);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
})
|
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ChangeDetectionStrategy, Component, effect, inject, OnInit, signal } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, computed, inject, OnInit, Signal } from '@angular/core';
|
||||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
|
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||||
import { StartingPointState, StartingPointStateStore } from './starting-point.state';
|
import { StartingPointState, StartingPointStateStore } from './starting-point.state';
|
||||||
|
@ -40,28 +40,6 @@ export class StartingPoint implements OnInit {
|
||||||
afterHighSchool: [AfterHighSchool.Undefined, Validators.required],
|
afterHighSchool: [AfterHighSchool.Undefined, Validators.required],
|
||||||
});
|
});
|
||||||
|
|
||||||
readonly genders = signal<Array<{ desc: string; value: Gender }>>([
|
|
||||||
{
|
|
||||||
desc: 'Female',
|
|
||||||
value: Gender.Female,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: 'Male',
|
|
||||||
value: Gender.Male,
|
|
||||||
},
|
|
||||||
]).asReadonly();
|
|
||||||
|
|
||||||
readonly afterHighSchoolOptions = signal<Array<{ desc: string; value: AfterHighSchool }>>([
|
|
||||||
{
|
|
||||||
desc: 'Go to College',
|
|
||||||
value: AfterHighSchool.College,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: 'Enter the Workforce',
|
|
||||||
value: AfterHighSchool.Workforce,
|
|
||||||
},
|
|
||||||
]).asReadonly();
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.form.valueChanges
|
this.form.valueChanges
|
||||||
.pipe(takeUntilDestroyed())
|
.pipe(takeUntilDestroyed())
|
||||||
|
@ -71,6 +49,4 @@ export class StartingPoint implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {}
|
ngOnInit(): void {}
|
||||||
|
|
||||||
onSubmit() {}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
"references": [
|
"references": [
|
||||||
{
|
{
|
||||||
"path": "./tsconfig.app.json"
|
"path": "./tsconfig.app.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.spec.json"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue