diff --git a/projects/example-app/src/app/app.module.ts b/projects/example-app/src/app/app.config.ts similarity index 50% rename from projects/example-app/src/app/app.module.ts rename to projects/example-app/src/app/app.config.ts index 1f66f73f6a..2251b42d0d 100644 --- a/projects/example-app/src/app/app.module.ts +++ b/projects/example-app/src/app/app.config.ts @@ -1,40 +1,34 @@ -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 { ApplicationConfig } from '@angular/core'; +import { provideHttpClient } from '@angular/common/http'; +import { provideAnimations } 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 { 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 { CoreModule } from '@example-app/core'; -import { AppRoutingModule } from '@example-app/app-routing.module'; +import { APP_ROUTES } from '@example-app/app.routing'; import { UserEffects, RouterEffects } from '@example-app/core/effects'; -import { AppComponent } from '@example-app/core/containers'; +import { provideRouter, withHashLocation } from '@angular/router'; +import * as fromAuth from '@example-app/auth/reducers'; +import { AuthEffects } from './auth/effects'; -@NgModule({ - imports: [ - CommonModule, - BrowserModule, - BrowserAnimationsModule, - HttpClientModule, - AuthModule, - AppRoutingModule, +export const appConfig: ApplicationConfig = { + providers: [ + provideAnimations(), + provideHttpClient(), + provideRouter(APP_ROUTES, withHashLocation()), /** - * StoreModule.forRoot is imported once in the root module, accepting a reducer + * 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. */ - StoreModule.forRoot(rootReducers, { + provideStore(rootReducers, { metaReducers, runtimeChecks: { // strictStateImmutability and strictActionImmutability are enabled by default @@ -48,7 +42,7 @@ import { AppComponent } from '@example-app/core/containers'; /** * @ngrx/router-store keeps router state up-to-date in the store. */ - StoreRouterConnectingModule.forRoot(), + provideRouterStore(), /** * Store devtools instrument the store retaining past versions of state @@ -60,22 +54,27 @@ import { AppComponent } from '@example-app/core/containers'; * * See: https://github.com/zalmoxisus/redux-devtools-extension */ - StoreDevtoolsModule.instrument({ + provideStoreDevtools({ 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. + * The provideEffects() function is used to register effect classes + * so they are initialized when the application starts. * * See: https://ngrx.io/guide/effects#registering-root-effects */ - EffectsModule.forRoot(UserEffects, RouterEffects), - CoreModule, + provideEffects(UserEffects, RouterEffects, AuthEffects), + + /** + * The Auth state is provided here to ensure that the login details + * is available as soon as the application starts. + */ + provideState({ + name: fromAuth.authFeatureKey, + reducer: fromAuth.reducers, + }), ], - 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..398d7de535 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.routing').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.routing').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.routing.ts b/projects/example-app/src/app/auth/auth.routing.ts new file mode 100644 index 0000000000..7197a2c553 --- /dev/null +++ b/projects/example-app/src/app/auth/auth.routing.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.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.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.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.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.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: ` `, }) 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: `