From 936b7f502b92fbe9ce694aac1a5e3389c7dc2bc0 Mon Sep 17 00:00:00 2001 From: Brandon Roberts Date: Thu, 25 Apr 2019 22:28:13 -0500 Subject: [PATCH 1/2] 06-effects crud complete --- src/app/books/actions/books-api.actions.ts | 30 +++++++++++++-- src/app/books/books-api.effects.ts | 43 +++++++++++++++++++++- src/app/shared/state/books.reducer.ts | 11 ++++-- 3 files changed, 75 insertions(+), 9 deletions(-) diff --git a/src/app/books/actions/books-api.actions.ts b/src/app/books/actions/books-api.actions.ts index 2c48a20..9cf6486 100644 --- a/src/app/books/actions/books-api.actions.ts +++ b/src/app/books/actions/books-api.actions.ts @@ -2,7 +2,10 @@ import { Book } from "src/app/shared/models/book.model"; import { Action } from "@ngrx/store"; export enum BooksApiActionTypes { - BooksLoaded = '[Books API] Books Loaded Success', + BooksLoaded = "[Books API] Books Loaded Success", + BookCreated = "[Books API] Book Created", + BookUpdated = "[Books API] Book Updated", + BookDeleted = "[Books API] Book Deleted" } export class BooksLoaded implements Action { @@ -11,5 +14,26 @@ export class BooksLoaded implements Action { constructor(public books: Book[]) {} } -export type BooksApiActions = - | BooksLoaded; +export class BookCreated implements Action { + readonly type = BooksApiActionTypes.BookCreated; + + constructor(public book: Book) {} +} + +export class BookUpdated implements Action { + readonly type = BooksApiActionTypes.BookUpdated; + + constructor(public book: Book) {} +} + +export class BookDeleted implements Action { + readonly type = BooksApiActionTypes.BookDeleted; + + constructor(public book: Book) {} +} + +export type BooksApiActions = + | BooksLoaded + | BookCreated + | BookUpdated + | BookDeleted; diff --git a/src/app/books/books-api.effects.ts b/src/app/books/books-api.effects.ts index 0107a38..e0e70bc 100644 --- a/src/app/books/books-api.effects.ts +++ b/src/app/books/books-api.effects.ts @@ -2,7 +2,13 @@ import { Injectable } from "@angular/core"; import { Effect, Actions, ofType } from "@ngrx/effects"; import { BooksPageActions, BooksApiActions } from "./actions"; import { BooksService } from "../shared/services/book.service"; -import { mergeMap, map, catchError } from "rxjs/operators"; +import { + mergeMap, + map, + catchError, + exhaustMap, + concatMap +} from "rxjs/operators"; import { EMPTY } from "rxjs"; @Injectable() @@ -10,7 +16,7 @@ export class BooksApiEffects { @Effect() loadBooks$ = this.actions$.pipe( ofType(BooksPageActions.BooksActionTypes.Enter), - mergeMap(() => + exhaustMap(() => this.booksService.all().pipe( map(books => new BooksApiActions.BooksLoaded(books)), catchError(() => EMPTY) @@ -18,6 +24,39 @@ export class BooksApiEffects { ) ); + @Effect() + createBook$ = this.actions$.pipe( + ofType(BooksPageActions.BooksActionTypes.CreateBook), + mergeMap(action => + this.booksService.create(action.book).pipe( + map(book => new BooksApiActions.BookCreated(book)), + catchError(() => EMPTY) + ) + ) + ); + + @Effect() + updateBook$ = this.actions$.pipe( + ofType(BooksPageActions.BooksActionTypes.UpdateBook), + concatMap(action => + this.booksService.update(action.book.id, action.book).pipe( + map(book => new BooksApiActions.BookUpdated(book)), + catchError(() => EMPTY) + ) + ) + ); + + @Effect() + deleteBook$ = this.actions$.pipe( + ofType(BooksPageActions.BooksActionTypes.DeleteBook), + mergeMap(action => + this.booksService.delete(action.book.id).pipe( + map(() => new BooksApiActions.BookDeleted(action.book)), + catchError(() => EMPTY) + ) + ) + ); + constructor( private booksService: BooksService, private actions$: Actions< diff --git a/src/app/shared/state/books.reducer.ts b/src/app/shared/state/books.reducer.ts index f24b393..5bfede0 100644 --- a/src/app/shared/state/books.reducer.ts +++ b/src/app/shared/state/books.reducer.ts @@ -54,16 +54,19 @@ export function reducer( activeBookId: null }; - case BooksPageActions.BooksActionTypes.CreateBook: - return adapter.addOne(action.book, state); + case BooksApiActions.BooksApiActionTypes.BookCreated: + return adapter.addOne(action.book, { + ...state, + activeBookId: action.book.id + }); - case BooksPageActions.BooksActionTypes.UpdateBook: + case BooksApiActions.BooksApiActionTypes.BookUpdated: return adapter.updateOne( { id: action.book.id, changes: action.book }, { ...state, activeBookId: action.book.id } ); - case BooksPageActions.BooksActionTypes.DeleteBook: + case BooksApiActions.BooksApiActionTypes.BookDeleted: return adapter.removeOne(action.book.id, { ...state, activeBookId: null From ee1174a7885716a4763c31541b6f1058f8ce5317 Mon Sep 17 00:00:00 2001 From: Mike Ryan Date: Tue, 30 Apr 2019 11:31:40 -0600 Subject: [PATCH 2/2] Update books-api.effects.ts Switching to `concatMap` for creating a book --- src/app/books/books-api.effects.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/books/books-api.effects.ts b/src/app/books/books-api.effects.ts index e0e70bc..a3456db 100644 --- a/src/app/books/books-api.effects.ts +++ b/src/app/books/books-api.effects.ts @@ -27,7 +27,7 @@ export class BooksApiEffects { @Effect() createBook$ = this.actions$.pipe( ofType(BooksPageActions.BooksActionTypes.CreateBook), - mergeMap(action => + concatMap(action => this.booksService.create(action.book).pipe( map(book => new BooksApiActions.BookCreated(book)), catchError(() => EMPTY)