diff --git a/src/app/super-behaviour-subject.ts b/src/app/super-behaviour-subject.ts new file mode 100644 index 0000000..f2f30d8 --- /dev/null +++ b/src/app/super-behaviour-subject.ts @@ -0,0 +1,13 @@ +import {BehaviorSubject} from 'rxjs'; + +export type SuperBehaviourSubjectNext = T | ((previousValue: T) => T); + +export class SuperBehaviourSubject extends BehaviorSubject { + next(value: SuperBehaviourSubjectNext): void { + if (typeof value === 'function') { + // @ts-ignore + return super.next(value(this._value)); // _value of BehaviorSubject must became not so private + } + super.next(value); + } +} diff --git a/src/app/todo.facade.ts b/src/app/todo.facade.ts index 098cbae..1b0dbc5 100644 --- a/src/app/todo.facade.ts +++ b/src/app/todo.facade.ts @@ -31,35 +31,31 @@ export class TodoFacade { createTodo(description: string) { const todo = { description: description, done: false }; - const todos = this.todoState.getTodos(); - this.todoState.setTodos( - [...todos, todo] - ); + this.todoState.setTodos((todos) => [...todos, todo]); } deleteTodo(todo: Todo) { - const todos = this.todoState.getTodos(); - this.todoState.setTodos( - [...todos.filter(x => x !== todo)] - ); + this.todoState.setTodos((todos) => [...todos.filter(x => x !== todo)]); } toggleTodo(todo: Todo) { - const todos = this.todoState.getTodos(); - todo = todos.find(x => x.description === todo.description); - todo.done = !todo.done; - this.todoState.setTodos( - [...todos] + this.todoState.setTodos((todos) => todos.map(todoItem => { + if (todoItem.description === todo.description) { + todoItem.done = !todoItem.done; + } + return todoItem; + }) ); } toggleAllTodos() { - const todos = this.todoState.getTodos(); - const allDone = todos.every(todo => todo.done); - todos.forEach(todo => todo.done = !allDone); - this.todoState.setTodos( - [...todos] - ); + this.todoState.setTodos((todos) => { + const isAllDone = todos.every(todo => todo.done); + return todos.map(todo => { + todo.done = !isAllDone; + return todo; + }); + }); } deleteAllTodos() { @@ -68,5 +64,5 @@ export class TodoFacade { filterTodos(value: string) { this.todoState.setFilter(value); - }; + } } diff --git a/src/app/todo.state.ts b/src/app/todo.state.ts index 522b32f..a7997f4 100644 --- a/src/app/todo.state.ts +++ b/src/app/todo.state.ts @@ -1,5 +1,6 @@ import {BehaviorSubject, Observable} from "rxjs"; import {Injectable} from "@angular/core"; +import {SuperBehaviourSubject, SuperBehaviourSubjectNext} from './super-behaviour-subject'; export interface Todo { description: string; @@ -21,7 +22,7 @@ const sampleTodos: Todo[] = [ @Injectable({"providedIn": "root"}) export class TodoState { - private readonly todos$ = new BehaviorSubject(sampleTodos); + private readonly todos$ = new SuperBehaviourSubject(sampleTodos); private readonly filter$ = new BehaviorSubject(''); private readonly updating$ = new BehaviorSubject(false); @@ -37,11 +38,7 @@ export class TodoState { return this.updating$.asObservable(); } - getTodos(): Todo[] { - return this.todos$.getValue(); - } - - setTodos(todos: Todo[]): void { + setTodos(todos: SuperBehaviourSubjectNext): void { this.todos$.next(todos); }