From 0c1ff86ac8941105fcab0eeb927e777868991155 Mon Sep 17 00:00:00 2001 From: Sheik Althaf Date: Thu, 8 Aug 2024 07:02:20 +0530 Subject: [PATCH 01/10] docs: update example app to standalone Updated the example app to standalone, removed all the modules from app. --- projects/example-app/src/app/app.config.ts | 78 ++++++++++++++++++ projects/example-app/src/app/app.module.ts | 81 ------------------- .../{app-routing.module.ts => app.routing.ts} | 22 ++--- .../src/app/auth/auth-routing.module.ts | 13 --- .../example-app/src/app/auth/auth.module.ts | 37 --------- .../example-app/src/app/auth/auth.routes.ts | 10 +++ .../components/login-form.component.spec.ts | 6 +- .../auth/components/login-form.component.ts | 6 +- ...gout-confirmation-dialog.component.spec.ts | 4 +- .../logout-confirmation-dialog.component.ts | 3 + .../containers/login-page.component.spec.ts | 9 +-- .../auth/containers/login-page.component.ts | 4 + projects/example-app/src/app/auth/index.ts | 1 - .../src/app/books/books-routing.module.ts | 34 -------- .../example-app/src/app/books/books.module.ts | 69 ---------------- .../example-app/src/app/books/books.routes.ts | 54 +++++++++++++ .../components/book-authors.component.ts | 4 + .../books/components/book-detail.component.ts | 5 ++ .../components/book-preview-list.component.ts | 4 + .../components/book-preview.component.ts | 13 +++ .../books/components/book-search.component.ts | 4 + .../collection-page.component.spec.ts | 22 +---- .../containers/collection-page.component.ts | 5 ++ .../find-book-page.component.spec.ts | 30 +------ .../containers/find-book-page.component.ts | 4 + .../selected-book-page.component.spec.ts | 19 +---- .../selected-book-page.component.ts | 4 + .../view-book-page.component.spec.ts | 16 +--- .../containers/view-book-page.component.ts | 3 + .../app/core/components/layout.component.ts | 3 + .../app/core/components/nav-item.component.ts | 5 ++ .../app/core/components/sidenav.component.ts | 3 + .../app/core/components/toolbar.component.ts | 3 + .../src/app/core/containers/app.component.ts | 19 +++++ .../containers/not-found-page.component.ts | 4 + .../example-app/src/app/core/core.module.ts | 31 ------- projects/example-app/src/app/core/index.ts | 1 - .../src/app/material/material.module.ts | 38 +++------ .../src/app/shared/pipes/add-commas.pipe.ts | 5 +- .../src/app/shared/pipes/ellipsis.pipe.ts | 5 +- projects/example-app/src/main.ts | 9 +-- 41 files changed, 286 insertions(+), 404 deletions(-) create mode 100644 projects/example-app/src/app/app.config.ts delete mode 100644 projects/example-app/src/app/app.module.ts rename projects/example-app/src/app/{app-routing.module.ts => app.routing.ts} (50%) delete mode 100644 projects/example-app/src/app/auth/auth-routing.module.ts delete mode 100644 projects/example-app/src/app/auth/auth.module.ts create mode 100644 projects/example-app/src/app/auth/auth.routes.ts delete mode 100644 projects/example-app/src/app/auth/index.ts delete mode 100644 projects/example-app/src/app/books/books-routing.module.ts delete mode 100644 projects/example-app/src/app/books/books.module.ts create mode 100644 projects/example-app/src/app/books/books.routes.ts delete mode 100644 projects/example-app/src/app/core/core.module.ts delete mode 100644 projects/example-app/src/app/core/index.ts diff --git a/projects/example-app/src/app/app.config.ts b/projects/example-app/src/app/app.config.ts new file mode 100644 index 0000000000..ea8ea569c0 --- /dev/null +++ b/projects/example-app/src/app/app.config.ts @@ -0,0 +1,78 @@ +import { ApplicationConfig } from '@angular/core'; +import { provideHttpClient } from '@angular/common/http'; +import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; + +import { provideState, provideStore } from '@ngrx/store'; +import { provideEffects } from '@ngrx/effects'; +import { provideRouterStore } from '@ngrx/router-store'; +import { provideStoreDevtools } from '@ngrx/store-devtools'; + +import { rootReducers, metaReducers } from '@example-app/reducers'; + +import { APP_ROUTES } from '@example-app/app.routing'; +import { UserEffects, RouterEffects } from '@example-app/core/effects'; +import { provideRouter, withHashLocation } from '@angular/router'; +import * as fromAuth from '@example-app/auth/reducers'; +import { AuthEffects } from './auth/effects'; + +export const appConfig: ApplicationConfig = { + providers: [ + provideAnimationsAsync(), + provideHttpClient(), + provideRouter(APP_ROUTES, withHashLocation()), + + /** + * provideStore() is imported once in the root providers, accepting a reducer + * function or object map of reducer functions. If passed an object of + * reducers, combineReducers will be run creating your application + * meta-reducer. This returns all providers for an @ngrx/store + * based application. + */ + provideStore(rootReducers, { + metaReducers, + runtimeChecks: { + // strictStateImmutability and strictActionImmutability are enabled by default + strictStateSerializability: true, + strictActionSerializability: true, + strictActionWithinNgZone: true, + strictActionTypeUniqueness: true, + }, + }), + + /** + * @ngrx/router-store keeps router state up-to-date in the store. + */ + provideRouterStore(), + + /** + * Store devtools instrument the store retaining past versions of state + * and recalculating new states. This enables powerful time-travel + * debugging. + * + * To use the debugger, install the Redux Devtools extension for either + * Chrome or Firefox + * + * See: https://github.com/zalmoxisus/redux-devtools-extension + */ + provideStoreDevtools({ + name: 'NgRx Book Store App', + // In a production build you would want to disable the Store Devtools + // logOnly: !isDevMode(), + }), + + /** + * The provideEffects() function is used to register effect classes + * so they are initialized when the application starts. + */ + provideEffects(UserEffects, RouterEffects, AuthEffects), + + /** + * The Auth state is provided here to ensure that the login details + * are available as soon as the application starts. + */ + provideState({ + name: fromAuth.authFeatureKey, + reducer: fromAuth.reducers, + }), + ], +}; diff --git a/projects/example-app/src/app/app.module.ts b/projects/example-app/src/app/app.module.ts deleted file mode 100644 index 1f66f73f6a..0000000000 --- a/projects/example-app/src/app/app.module.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { HttpClientModule } from '@angular/common/http'; -import { BrowserModule } from '@angular/platform-browser'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; - -import { StoreModule } from '@ngrx/store'; -import { EffectsModule } from '@ngrx/effects'; -import { StoreRouterConnectingModule } from '@ngrx/router-store'; -import { StoreDevtoolsModule } from '@ngrx/store-devtools'; - -import { AuthModule } from '@example-app/auth'; - -import { rootReducers, metaReducers } from '@example-app/reducers'; - -import { CoreModule } from '@example-app/core'; -import { AppRoutingModule } from '@example-app/app-routing.module'; -import { UserEffects, RouterEffects } from '@example-app/core/effects'; -import { AppComponent } from '@example-app/core/containers'; - -@NgModule({ - imports: [ - CommonModule, - BrowserModule, - BrowserAnimationsModule, - HttpClientModule, - AuthModule, - AppRoutingModule, - - /** - * StoreModule.forRoot is imported once in the root module, accepting a reducer - * function or object map of reducer functions. If passed an object of - * reducers, combineReducers will be run creating your application - * meta-reducer. This returns all providers for an @ngrx/store - * based application. - */ - StoreModule.forRoot(rootReducers, { - metaReducers, - runtimeChecks: { - // strictStateImmutability and strictActionImmutability are enabled by default - strictStateSerializability: true, - strictActionSerializability: true, - strictActionWithinNgZone: true, - strictActionTypeUniqueness: true, - }, - }), - - /** - * @ngrx/router-store keeps router state up-to-date in the store. - */ - StoreRouterConnectingModule.forRoot(), - - /** - * Store devtools instrument the store retaining past versions of state - * and recalculating new states. This enables powerful time-travel - * debugging. - * - * To use the debugger, install the Redux Devtools extension for either - * Chrome or Firefox - * - * See: https://github.com/zalmoxisus/redux-devtools-extension - */ - StoreDevtoolsModule.instrument({ - name: 'NgRx Book Store App', - // In a production build you would want to disable the Store Devtools - // logOnly: !isDevMode(), - }), - - /** - * EffectsModule.forRoot() is imported once in the root module and - * sets up the effects class to be initialized immediately when the - * application starts. - * - * See: https://ngrx.io/guide/effects#registering-root-effects - */ - EffectsModule.forRoot(UserEffects, RouterEffects), - CoreModule, - ], - bootstrap: [AppComponent], -}) -export class AppModule {} diff --git a/projects/example-app/src/app/app-routing.module.ts b/projects/example-app/src/app/app.routing.ts similarity index 50% rename from projects/example-app/src/app/app-routing.module.ts rename to projects/example-app/src/app/app.routing.ts index cba7ce2327..d4606d572a 100644 --- a/projects/example-app/src/app/app-routing.module.ts +++ b/projects/example-app/src/app/app.routing.ts @@ -1,15 +1,19 @@ -import { NgModule } from '@angular/core'; -import { Routes, RouterModule } from '@angular/router'; +import { Routes } from '@angular/router'; import { authGuard } from '@example-app/auth/services'; import { NotFoundPageComponent } from '@example-app/core/containers'; -export const routes: Routes = [ +export const APP_ROUTES: Routes = [ + { + path: 'login', + loadChildren: () => + import('@example-app/auth/auth.routes').then((m) => m.AUTH_ROUTES), + }, { path: '', redirectTo: '/books', pathMatch: 'full' }, { path: 'books', loadChildren: () => - import('@example-app/books/books.module').then((m) => m.BooksModule), + import('@example-app/books/books.routes').then((m) => m.BOOKS_ROUTES), canActivate: [authGuard], }, { @@ -18,13 +22,3 @@ export const routes: Routes = [ data: { title: 'Not found' }, }, ]; - -@NgModule({ - imports: [ - RouterModule.forRoot(routes, { - useHash: true, - }), - ], - exports: [RouterModule], -}) -export class AppRoutingModule {} diff --git a/projects/example-app/src/app/auth/auth-routing.module.ts b/projects/example-app/src/app/auth/auth-routing.module.ts deleted file mode 100644 index 62ceda18b6..0000000000 --- a/projects/example-app/src/app/auth/auth-routing.module.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { NgModule } from '@angular/core'; -import { Routes, RouterModule } from '@angular/router'; -import { LoginPageComponent } from '@example-app/auth/containers'; - -const routes: Routes = [ - { path: 'login', component: LoginPageComponent, data: { title: 'Login' } }, -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule], -}) -export class AuthRoutingModule {} diff --git a/projects/example-app/src/app/auth/auth.module.ts b/projects/example-app/src/app/auth/auth.module.ts deleted file mode 100644 index 39527caa8a..0000000000 --- a/projects/example-app/src/app/auth/auth.module.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { ReactiveFormsModule } from '@angular/forms'; -import { StoreModule } from '@ngrx/store'; -import { EffectsModule } from '@ngrx/effects'; -import { LoginPageComponent } from '@example-app/auth/containers'; -import { - LoginFormComponent, - LogoutConfirmationDialogComponent, -} from '@example-app/auth/components'; - -import { AuthEffects } from '@example-app/auth/effects'; -import * as fromAuth from '@example-app/auth/reducers'; -import { MaterialModule } from '@example-app/material'; -import { AuthRoutingModule } from './auth-routing.module'; - -export const COMPONENTS = [ - LoginPageComponent, - LoginFormComponent, - LogoutConfirmationDialogComponent, -]; - -@NgModule({ - imports: [ - CommonModule, - ReactiveFormsModule, - MaterialModule, - AuthRoutingModule, - StoreModule.forFeature({ - name: fromAuth.authFeatureKey, - reducer: fromAuth.reducers, - }), - EffectsModule.forFeature(AuthEffects), - ], - declarations: COMPONENTS, -}) -export class AuthModule {} diff --git a/projects/example-app/src/app/auth/auth.routes.ts b/projects/example-app/src/app/auth/auth.routes.ts new file mode 100644 index 0000000000..7197a2c553 --- /dev/null +++ b/projects/example-app/src/app/auth/auth.routes.ts @@ -0,0 +1,10 @@ +import { Routes } from '@angular/router'; +import { LoginPageComponent } from '@example-app/auth/containers'; + +export const AUTH_ROUTES: Routes = [ + { + path: '', + component: LoginPageComponent, + data: { title: 'Login' }, + }, +]; diff --git a/projects/example-app/src/app/auth/components/login-form.component.spec.ts b/projects/example-app/src/app/auth/components/login-form.component.spec.ts index 52aba4fbe0..0cb1e3456a 100644 --- a/projects/example-app/src/app/auth/components/login-form.component.spec.ts +++ b/projects/example-app/src/app/auth/components/login-form.component.spec.ts @@ -1,7 +1,7 @@ import { TestBed, ComponentFixture } from '@angular/core/testing'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { LoginFormComponent } from '@example-app/auth/components'; -import { ReactiveFormsModule } from '@angular/forms'; +import { provideNoopAnimations } from '@angular/platform-browser/animations'; describe('Login Page', () => { let fixture: ComponentFixture; @@ -9,8 +9,8 @@ describe('Login Page', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [ReactiveFormsModule], - declarations: [LoginFormComponent], + imports: [LoginFormComponent], + providers: [provideNoopAnimations()], schemas: [NO_ERRORS_SCHEMA], }); diff --git a/projects/example-app/src/app/auth/components/login-form.component.ts b/projects/example-app/src/app/auth/components/login-form.component.ts index 2357726616..269d298e86 100644 --- a/projects/example-app/src/app/auth/components/login-form.component.ts +++ b/projects/example-app/src/app/auth/components/login-form.component.ts @@ -1,9 +1,13 @@ +import { NgIf } from '@angular/common'; import { Component, Input, Output, EventEmitter } from '@angular/core'; -import { FormGroup, FormControl } from '@angular/forms'; +import { FormGroup, FormControl, ReactiveFormsModule } from '@angular/forms'; import { Credentials } from '@example-app/auth/models'; +import { MaterialModule } from '@example-app/material'; @Component({ + standalone: true, selector: 'bc-login-form', + imports: [MaterialModule, ReactiveFormsModule, NgIf], template: ` Login diff --git a/projects/example-app/src/app/auth/components/logout-confirmation-dialog.component.spec.ts b/projects/example-app/src/app/auth/components/logout-confirmation-dialog.component.spec.ts index 78066eadee..0f3fe7d746 100644 --- a/projects/example-app/src/app/auth/components/logout-confirmation-dialog.component.spec.ts +++ b/projects/example-app/src/app/auth/components/logout-confirmation-dialog.component.spec.ts @@ -1,14 +1,12 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { LogoutConfirmationDialogComponent } from '@example-app/auth/components'; -import { MaterialModule } from '@example-app/material'; describe('Logout Confirmation Dialog', () => { let fixture: ComponentFixture; beforeEach(() => { TestBed.configureTestingModule({ - imports: [MaterialModule], - declarations: [LogoutConfirmationDialogComponent], + imports: [LogoutConfirmationDialogComponent], }); fixture = TestBed.createComponent(LogoutConfirmationDialogComponent); diff --git a/projects/example-app/src/app/auth/components/logout-confirmation-dialog.component.ts b/projects/example-app/src/app/auth/components/logout-confirmation-dialog.component.ts index 1ee60f1102..eeff134db7 100644 --- a/projects/example-app/src/app/auth/components/logout-confirmation-dialog.component.ts +++ b/projects/example-app/src/app/auth/components/logout-confirmation-dialog.component.ts @@ -1,10 +1,13 @@ import { Component } from '@angular/core'; +import { MaterialModule } from '@example-app/material'; /** * The dialog will close with true if user clicks the ok button, * otherwise it will close with undefined. */ @Component({ + standalone: true, + imports: [MaterialModule], template: `

Logout

Are you sure you want to logout? diff --git a/projects/example-app/src/app/auth/containers/login-page.component.spec.ts b/projects/example-app/src/app/auth/containers/login-page.component.spec.ts index b9433c4573..7f367b213f 100644 --- a/projects/example-app/src/app/auth/containers/login-page.component.spec.ts +++ b/projects/example-app/src/app/auth/containers/login-page.component.spec.ts @@ -1,12 +1,9 @@ import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { ReactiveFormsModule } from '@angular/forms'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { provideNoopAnimations } from '@angular/platform-browser/animations'; import { LoginPageComponent } from '@example-app/auth/containers'; -import { LoginFormComponent } from '@example-app/auth/components'; import * as fromAuth from '@example-app/auth/reducers'; import { LoginPageActions } from '@example-app/auth/actions/login-page.actions'; import { provideMockStore, MockStore } from '@ngrx/store/testing'; -import { MaterialModule } from '@example-app/material'; describe('Login Page', () => { let fixture: ComponentFixture; @@ -15,9 +12,9 @@ describe('Login Page', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [NoopAnimationsModule, MaterialModule, ReactiveFormsModule], - declarations: [LoginPageComponent, LoginFormComponent], + imports: [LoginPageComponent], providers: [ + provideNoopAnimations(), provideMockStore({ selectors: [ { selector: fromAuth.selectLoginPagePending, value: false }, diff --git a/projects/example-app/src/app/auth/containers/login-page.component.ts b/projects/example-app/src/app/auth/containers/login-page.component.ts index d5dec368ee..e85d256c94 100644 --- a/projects/example-app/src/app/auth/containers/login-page.component.ts +++ b/projects/example-app/src/app/auth/containers/login-page.component.ts @@ -3,9 +3,13 @@ import { Store } from '@ngrx/store'; import { Credentials } from '@example-app/auth/models'; import * as fromAuth from '@example-app/auth/reducers'; import { LoginPageActions } from '@example-app/auth/actions/login-page.actions'; +import { LoginFormComponent } from '../components'; +import { AsyncPipe } from '@angular/common'; @Component({ + standalone: true, selector: 'bc-login-page', + imports: [LoginFormComponent, AsyncPipe], template: ` Written By: diff --git a/projects/example-app/src/app/books/components/book-detail.component.ts b/projects/example-app/src/app/books/components/book-detail.component.ts index ae1c59958f..3453300464 100644 --- a/projects/example-app/src/app/books/components/book-detail.component.ts +++ b/projects/example-app/src/app/books/components/book-detail.component.ts @@ -1,9 +1,14 @@ +import { NgIf } from '@angular/common'; import { Component, EventEmitter, Input, Output } from '@angular/core'; import { Book } from '@example-app/books/models'; +import { MaterialModule } from '@example-app/material'; +import { BookAuthorsComponent } from './book-authors.component'; @Component({ + standalone: true, selector: 'bc-book-detail', + imports: [MaterialModule, NgIf, BookAuthorsComponent], template: ` diff --git a/projects/example-app/src/app/books/components/book-preview-list.component.ts b/projects/example-app/src/app/books/components/book-preview-list.component.ts index b93c3e83e7..7ef391e47e 100644 --- a/projects/example-app/src/app/books/components/book-preview-list.component.ts +++ b/projects/example-app/src/app/books/components/book-preview-list.component.ts @@ -1,9 +1,13 @@ import { Component, Input } from '@angular/core'; import { Book } from '@example-app/books/models'; +import { BookPreviewComponent } from './book-preview.component'; +import { NgFor } from '@angular/common'; @Component({ + standalone: true, selector: 'bc-book-preview-list', + imports: [BookPreviewComponent, NgFor], template: ` `, diff --git a/projects/example-app/src/app/books/components/book-preview.component.ts b/projects/example-app/src/app/books/components/book-preview.component.ts index 41a5f4c14d..eb56168424 100644 --- a/projects/example-app/src/app/books/components/book-preview.component.ts +++ b/projects/example-app/src/app/books/components/book-preview.component.ts @@ -1,9 +1,22 @@ import { Component, Input } from '@angular/core'; +import { RouterLink } from '@angular/router'; import { Book } from '@example-app/books/models'; +import { MaterialModule } from '@example-app/material'; +import { EllipsisPipe } from '@example-app/shared/pipes/ellipsis.pipe'; +import { BookAuthorsComponent } from './book-authors.component'; +import { NgIf } from '@angular/common'; @Component({ + standalone: true, selector: 'bc-book-preview', + imports: [ + MaterialModule, + RouterLink, + EllipsisPipe, + BookAuthorsComponent, + NgIf, + ], template: ` diff --git a/projects/example-app/src/app/books/components/book-search.component.ts b/projects/example-app/src/app/books/components/book-search.component.ts index 1ae6822056..28c4f161d7 100644 --- a/projects/example-app/src/app/books/components/book-search.component.ts +++ b/projects/example-app/src/app/books/components/book-search.component.ts @@ -1,7 +1,11 @@ +import { NgIf } from '@angular/common'; import { Component, Output, Input, EventEmitter } from '@angular/core'; +import { MaterialModule } from '@example-app/material'; @Component({ + standalone: true, selector: 'bc-book-search', + imports: [MaterialModule, NgIf], template: ` Find a Book diff --git a/projects/example-app/src/app/books/containers/collection-page.component.spec.ts b/projects/example-app/src/app/books/containers/collection-page.component.spec.ts index 5addaa4aef..257cf36940 100644 --- a/projects/example-app/src/app/books/containers/collection-page.component.spec.ts +++ b/projects/example-app/src/app/books/containers/collection-page.component.spec.ts @@ -1,20 +1,11 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { RouterTestingModule } from '@angular/router/testing'; +import { provideNoopAnimations } from '@angular/platform-browser/animations'; import { MockStore, provideMockStore } from '@ngrx/store/testing'; import { CollectionPageActions } from '@example-app/books/actions/collection-page.actions'; -import { - BookAuthorsComponent, - BookPreviewComponent, - BookPreviewListComponent, -} from '@example-app/books/components'; import { CollectionPageComponent } from '@example-app/books/containers'; import * as fromBooks from '@example-app/books/reducers'; -import { AddCommasPipe } from '@example-app/shared/pipes/add-commas.pipe'; -import { EllipsisPipe } from '@example-app/shared/pipes/ellipsis.pipe'; -import { MaterialModule } from '@example-app/material'; describe('Collection Page', () => { let fixture: ComponentFixture; @@ -22,16 +13,9 @@ describe('Collection Page', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [NoopAnimationsModule, MaterialModule, RouterTestingModule], - declarations: [ - CollectionPageComponent, - BookPreviewListComponent, - BookPreviewComponent, - BookAuthorsComponent, - AddCommasPipe, - EllipsisPipe, - ], + imports: [CollectionPageComponent], providers: [ + provideNoopAnimations(), provideMockStore({ selectors: [{ selector: fromBooks.selectBookCollection, value: [] }], }), diff --git a/projects/example-app/src/app/books/containers/collection-page.component.ts b/projects/example-app/src/app/books/containers/collection-page.component.ts index 48acf84839..c0e6308cfd 100644 --- a/projects/example-app/src/app/books/containers/collection-page.component.ts +++ b/projects/example-app/src/app/books/containers/collection-page.component.ts @@ -6,10 +6,15 @@ import { Observable } from 'rxjs'; import { CollectionPageActions } from '@example-app/books/actions/collection-page.actions'; import { Book } from '@example-app/books/models'; import * as fromBooks from '@example-app/books/reducers'; +import { MaterialModule } from '@example-app/material'; +import { BookPreviewListComponent } from '../components'; +import { AsyncPipe } from '@angular/common'; @Component({ + standalone: true, selector: 'bc-collection-page', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [MaterialModule, BookPreviewListComponent, AsyncPipe], template: ` My Collection diff --git a/projects/example-app/src/app/books/containers/find-book-page.component.spec.ts b/projects/example-app/src/app/books/containers/find-book-page.component.spec.ts index 719d1a31ae..0811c8ba76 100644 --- a/projects/example-app/src/app/books/containers/find-book-page.component.spec.ts +++ b/projects/example-app/src/app/books/containers/find-book-page.component.spec.ts @@ -1,22 +1,11 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { ReactiveFormsModule } from '@angular/forms'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { RouterTestingModule } from '@angular/router/testing'; +import { provideNoopAnimations } from '@angular/platform-browser/animations'; import { MockStore, provideMockStore } from '@ngrx/store/testing'; import { FindBookPageActions } from '@example-app/books/actions/find-book-page.actions'; -import { - BookAuthorsComponent, - BookPreviewComponent, - BookPreviewListComponent, - BookSearchComponent, -} from '@example-app/books/components'; import { FindBookPageComponent } from '@example-app/books/containers'; import * as fromBooks from '@example-app/books/reducers'; -import { AddCommasPipe } from '@example-app/shared/pipes/add-commas.pipe'; -import { EllipsisPipe } from '@example-app/shared/pipes/ellipsis.pipe'; -import { MaterialModule } from '@example-app/material'; describe('Find Book Page', () => { let fixture: ComponentFixture; @@ -25,22 +14,9 @@ describe('Find Book Page', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule, - RouterTestingModule, - MaterialModule, - ReactiveFormsModule, - ], - declarations: [ - FindBookPageComponent, - BookSearchComponent, - BookPreviewComponent, - BookPreviewListComponent, - BookAuthorsComponent, - AddCommasPipe, - EllipsisPipe, - ], + imports: [FindBookPageComponent], providers: [ + provideNoopAnimations(), provideMockStore({ selectors: [ { selector: fromBooks.selectSearchQuery, value: '' }, diff --git a/projects/example-app/src/app/books/containers/find-book-page.component.ts b/projects/example-app/src/app/books/containers/find-book-page.component.ts index 254727e58f..86ba1f132b 100644 --- a/projects/example-app/src/app/books/containers/find-book-page.component.ts +++ b/projects/example-app/src/app/books/containers/find-book-page.component.ts @@ -7,10 +7,14 @@ import { take } from 'rxjs/operators'; import { FindBookPageActions } from '@example-app/books/actions/find-book-page.actions'; import { Book } from '@example-app/books/models'; import * as fromBooks from '@example-app/books/reducers'; +import { BookPreviewListComponent, BookSearchComponent } from '../components'; +import { AsyncPipe } from '@angular/common'; @Component({ + standalone: true, selector: 'bc-find-book-page', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [BookSearchComponent, AsyncPipe, BookPreviewListComponent], template: ` { let fixture: ComponentFixture; @@ -20,14 +15,8 @@ describe('Selected Book Page', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [NoopAnimationsModule, MaterialModule], - declarations: [ - SelectedBookPageComponent, - BookDetailComponent, - BookAuthorsComponent, - AddCommasPipe, - ], - providers: [provideMockStore()], + imports: [SelectedBookPageComponent], + providers: [provideNoopAnimations(), provideMockStore()], }); fixture = TestBed.createComponent(SelectedBookPageComponent); diff --git a/projects/example-app/src/app/books/containers/selected-book-page.component.ts b/projects/example-app/src/app/books/containers/selected-book-page.component.ts index 292666869b..e16ba31976 100644 --- a/projects/example-app/src/app/books/containers/selected-book-page.component.ts +++ b/projects/example-app/src/app/books/containers/selected-book-page.component.ts @@ -6,10 +6,14 @@ import { Observable } from 'rxjs'; import { SelectedBookPageActions } from '@example-app/books/actions/selected-book-page.actions'; import { Book } from '@example-app/books/models'; import * as fromBooks from '@example-app/books/reducers'; +import { BookDetailComponent } from '../components'; +import { AsyncPipe } from '@angular/common'; @Component({ + standalone: true, selector: 'bc-selected-book-page', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [BookDetailComponent, AsyncPipe], template: ` { let fixture: ComponentFixture; @@ -21,7 +14,7 @@ describe('View Book Page', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [MaterialModule], + imports: [ViewBookPageComponent], providers: [ { provide: ActivatedRoute, @@ -29,13 +22,6 @@ describe('View Book Page', () => { }, provideMockStore(), ], - declarations: [ - ViewBookPageComponent, - SelectedBookPageComponent, - BookDetailComponent, - BookAuthorsComponent, - AddCommasPipe, - ], }); fixture = TestBed.createComponent(ViewBookPageComponent); diff --git a/projects/example-app/src/app/books/containers/view-book-page.component.ts b/projects/example-app/src/app/books/containers/view-book-page.component.ts index f4bf63b54c..a6295f1860 100644 --- a/projects/example-app/src/app/books/containers/view-book-page.component.ts +++ b/projects/example-app/src/app/books/containers/view-book-page.component.ts @@ -5,6 +5,7 @@ import { Subscription } from 'rxjs'; import { map } from 'rxjs/operators'; import { ViewBookPageActions } from '@example-app/books/actions/view-book-page.actions'; +import { SelectedBookPageComponent } from './selected-book-page.component'; /** * Note: Container components are also reusable. Whether or not @@ -17,8 +18,10 @@ import { ViewBookPageActions } from '@example-app/books/actions/view-book-page.a * SelectedBookPageComponent */ @Component({ + standalone: true, selector: 'bc-view-book-page', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [SelectedBookPageComponent], template: ` `, }) export class ViewBookPageComponent implements OnDestroy { diff --git a/projects/example-app/src/app/core/components/layout.component.ts b/projects/example-app/src/app/core/components/layout.component.ts index 0975f50bd0..8510b0f925 100644 --- a/projects/example-app/src/app/core/components/layout.component.ts +++ b/projects/example-app/src/app/core/components/layout.component.ts @@ -1,7 +1,10 @@ import { Component } from '@angular/core'; +import { MaterialModule } from '@example-app/material'; @Component({ + standalone: true, selector: 'bc-layout', + imports: [MaterialModule], template: ` diff --git a/projects/example-app/src/app/core/components/nav-item.component.ts b/projects/example-app/src/app/core/components/nav-item.component.ts index 535d744b94..28e8753929 100644 --- a/projects/example-app/src/app/core/components/nav-item.component.ts +++ b/projects/example-app/src/app/core/components/nav-item.component.ts @@ -1,7 +1,12 @@ +import { NgIf } from '@angular/common'; import { Component, Input, Output, EventEmitter } from '@angular/core'; +import { RouterLink } from '@angular/router'; +import { MaterialModule } from '@example-app/material'; @Component({ + standalone: true, selector: 'bc-nav-item', + imports: [MaterialModule, RouterLink, NgIf], template: ` {{ icon }} diff --git a/projects/example-app/src/app/core/components/sidenav.component.ts b/projects/example-app/src/app/core/components/sidenav.component.ts index a9f4c1c103..702433fff2 100644 --- a/projects/example-app/src/app/core/components/sidenav.component.ts +++ b/projects/example-app/src/app/core/components/sidenav.component.ts @@ -1,7 +1,10 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { MaterialModule } from '@example-app/material'; @Component({ + standalone: true, selector: 'bc-sidenav', + imports: [MaterialModule], template: ` @@ -57,47 +149,133 @@ exports[`Login Page should disable the form if pending 1`] = ` form={[Function FormGroup]} submitted={[Function EventEmitter_]} > - - + + Login - +

- - + +

+
+
+ +
+
+
+
+
+
+
+
+

- - + +

+
+
+ +
+
+
+
+
+
+
+
+

@@ -112,35 +290,111 @@ exports[`Login Page should display an error message if provided 1`] = ` form={[Function FormGroup]} submitted={[Function EventEmitter_]} > - - + + Login - +

- - + +

+
+
+
+ +
+
+
+
+
+
+
+
+

- - + +

+
+
+
+ +
+
+
+
+
+
+
+
+

diff --git a/projects/example-app/src/app/auth/containers/__snapshots__/login-page.component.spec.ts.snap b/projects/example-app/src/app/auth/containers/__snapshots__/login-page.component.spec.ts.snap index dcfc5b501c..b90481a4b3 100644 --- a/projects/example-app/src/app/auth/containers/__snapshots__/login-page.component.spec.ts.snap +++ b/projects/example-app/src/app/auth/containers/__snapshots__/login-page.component.spec.ts.snap @@ -2,9 +2,9 @@ exports[`Login Page should compile 1`] = ` { it('should return the default state', () => { const action = {} as any; - const result = reducer(undefined, action); + const result = statusFeature.reducer(undefined, action); /** * Snapshot tests are a quick way to validate @@ -28,7 +28,7 @@ describe('AuthReducer', () => { const user = { name: 'test' } as User; const createAction = AuthApiActions.loginSuccess({ user }); - const result = reducer(fromAuth.initialState, createAction); + const result = statusFeature.reducer(fromAuth.initialState, createAction); expect(result).toMatchSnapshot(); }); @@ -41,7 +41,7 @@ describe('AuthReducer', () => { } as fromAuth.State; const createAction = AuthActions.logout(); - const result = reducer(initialState, createAction); + const result = statusFeature.reducer(initialState, createAction); expect(result).toMatchSnapshot(); }); diff --git a/projects/example-app/src/app/auth/reducers/login-page.reducer.spec.ts b/projects/example-app/src/app/auth/reducers/login-page.reducer.spec.ts index 781008a3f1..7f856a77d8 100644 --- a/projects/example-app/src/app/auth/reducers/login-page.reducer.spec.ts +++ b/projects/example-app/src/app/auth/reducers/login-page.reducer.spec.ts @@ -1,17 +1,17 @@ -import { reducer } from '@example-app/auth/reducers/login-page.reducer'; import * as fromLoginPage from '@example-app/auth/reducers/login-page.reducer'; import { LoginPageActions } from '@example-app/auth/actions/login-page.actions'; import { AuthApiActions } from '@example-app/auth/actions/auth-api.actions'; import { Credentials, User } from '@example-app/auth/models'; +import { loginPageFeature } from '@example-app/auth/reducers/login-page.reducer'; describe('LoginPageReducer', () => { describe('undefined action', () => { it('should return the default state', () => { const action = {} as any; - const result = reducer(undefined, action); + const result = loginPageFeature.reducer(undefined, action); expect(result).toMatchSnapshot(); }); @@ -22,7 +22,10 @@ describe('LoginPageReducer', () => { const user = { username: 'test' } as Credentials; const createAction = LoginPageActions.login({ credentials: user }); - const result = reducer(fromLoginPage.initialState, createAction); + const result = loginPageFeature.reducer( + fromLoginPage.initialState, + createAction + ); expect(result).toMatchSnapshot(); }); @@ -33,7 +36,10 @@ describe('LoginPageReducer', () => { const user = { name: 'test' } as User; const createAction = AuthApiActions.loginSuccess({ user }); - const result = reducer(fromLoginPage.initialState, createAction); + const result = loginPageFeature.reducer( + fromLoginPage.initialState, + createAction + ); expect(result).toMatchSnapshot(); }); @@ -44,7 +50,10 @@ describe('LoginPageReducer', () => { const error = 'login failed'; const createAction = AuthApiActions.loginFailure({ error }); - const result = reducer(fromLoginPage.initialState, createAction); + const result = loginPageFeature.reducer( + fromLoginPage.initialState, + createAction + ); expect(result).toMatchSnapshot(); }); diff --git a/projects/example-app/src/app/auth/services/auth-guard.service.spec.ts b/projects/example-app/src/app/auth/services/auth-guard.service.spec.ts index e97451e90b..508e6c2639 100644 --- a/projects/example-app/src/app/auth/services/auth-guard.service.spec.ts +++ b/projects/example-app/src/app/auth/services/auth-guard.service.spec.ts @@ -1,15 +1,14 @@ import { TestBed } from '@angular/core/testing'; -import { MemoizedSelector } from '@ngrx/store'; import { cold } from 'jasmine-marbles'; import { authGuard } from '@example-app/auth/services'; -import * as fromAuth from '@example-app/auth/reducers'; import { provideMockStore, MockStore } from '@ngrx/store/testing'; import { Observable } from 'rxjs'; +import { selectLoggedIn } from '@example-app/auth/reducers'; describe('Auth Guard', () => { let guard: Observable; let store: MockStore; - let loggedIn: MemoizedSelector; + let loggedIn: typeof selectLoggedIn; beforeEach(() => { TestBed.configureTestingModule({ @@ -18,7 +17,7 @@ describe('Auth Guard', () => { store = TestBed.inject(MockStore); guard = TestBed.runInInjectionContext(authGuard); - loggedIn = store.overrideSelector(fromAuth.selectLoggedIn, false); + loggedIn = store.overrideSelector(selectLoggedIn, false); }); it('should return false if the user state is not logged in', () => { diff --git a/projects/example-app/src/app/books/containers/__snapshots__/collection-page.component.spec.ts.snap b/projects/example-app/src/app/books/containers/__snapshots__/collection-page.component.spec.ts.snap index dd31673d71..c675f5ac0b 100644 --- a/projects/example-app/src/app/books/containers/__snapshots__/collection-page.component.spec.ts.snap +++ b/projects/example-app/src/app/books/containers/__snapshots__/collection-page.component.spec.ts.snap @@ -2,8 +2,8 @@ exports[`Collection Page should compile 1`] = ` From 9cfc91e2a25615c41f83995b3661272455ba6adb Mon Sep 17 00:00:00 2001 From: Rainer Hahnekamp Date: Mon, 16 Sep 2024 00:46:49 +0200 Subject: [PATCH 05/10] docs: move to new control flow syntax --- .../auth/components/login-form.component.ts | 7 ++-- .../books/components/book-detail.component.ts | 32 ++++++++----------- .../components/book-preview-list.component.ts | 7 ++-- .../components/book-preview.component.ts | 26 ++++++--------- .../books/components/book-search.component.ts | 7 ++-- .../app/core/components/nav-item.component.ts | 7 ++-- .../src/app/core/containers/app.component.ts | 21 +++++------- 7 files changed, 48 insertions(+), 59 deletions(-) diff --git a/projects/example-app/src/app/auth/components/login-form.component.ts b/projects/example-app/src/app/auth/components/login-form.component.ts index 269d298e86..320eafcae4 100644 --- a/projects/example-app/src/app/auth/components/login-form.component.ts +++ b/projects/example-app/src/app/auth/components/login-form.component.ts @@ -1,4 +1,3 @@ -import { NgIf } from '@angular/common'; import { Component, Input, Output, EventEmitter } from '@angular/core'; import { FormGroup, FormControl, ReactiveFormsModule } from '@angular/forms'; import { Credentials } from '@example-app/auth/models'; @@ -7,7 +6,7 @@ import { MaterialModule } from '@example-app/material'; @Component({ standalone: true, selector: 'bc-login-form', - imports: [MaterialModule, ReactiveFormsModule, NgIf], + imports: [MaterialModule, ReactiveFormsModule], template: ` Login @@ -35,9 +34,11 @@ import { MaterialModule } from '@example-app/material';

- + }