diff --git a/projects/todo-mvc/src/app/todo.component.ts b/projects/todo-mvc/src/app/todo.component.ts
index 563d5b1..2bc4406 100644
--- a/projects/todo-mvc/src/app/todo.component.ts
+++ b/projects/todo-mvc/src/app/todo.component.ts
@@ -11,49 +11,85 @@ import {
} from '@angular/core';
import { RxStrategyProvider } from '@rx-angular/cdk/render-strategies';
import { rxState } from '@rx-angular/state';
-import { rxActions } from '@rx-angular/state/actions';
+import { eventValue, rxActions } from '@rx-angular/state/actions';
import { rxEffects } from '@rx-angular/state/effects';
import { select } from '@rx-angular/state/selections';
+import { merge, switchMap, take } from 'rxjs';
import { Todo } from './todo.service';
+interface Actions {
+ remove: Todo;
+ toggleDone: boolean;
+ updateText: string;
+ edit: void;
+}
+
+interface Transforms {
+ toggleDone: (e: Event) => boolean;
+ updateText: (e: Event | string) => string;
+}
+
+const eventChecked = (e: Event): boolean => {
+ return (e.target as HTMLInputElement).checked;
+};
+
@Component({
standalone: true,
selector: 'app-todo',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
@if (isEditing) {
+
+ } @else {
+
}
`,
})
export class TodoComponent {
private readonly cd = inject(ChangeDetectorRef);
private readonly strategyProvider = inject(RxStrategyProvider);
+
+ readonly actions = rxActions(({ transforms }) =>
+ transforms({
+ toggleDone: eventChecked,
+ updateText: eventValue,
+ })
+ );
+
private readonly state = rxState<{ isEditing: boolean; todo: Todo }>(
- ({ set }) => set({ isEditing: false })
+ ({ set, connect }) => {
+ set({ isEditing: false });
+ connect('todo', this.actions.toggleDone$, ({ todo }, done: boolean) => ({
+ ...todo,
+ done,
+ }));
+ connect(this.actions.updateText$, ({ todo }, text: string) => ({
+ isEditing: false,
+ todo: {
+ ...todo,
+ text,
+ },
+ }));
+ connect('isEditing', this.actions.edit$, () => true);
+ }
);
- private readonly actions = rxActions<{ remove: Todo; update: Todo }>();
@ViewChild('input') input?: ElementRef;
- @ViewChild('toggle') toggle?: ElementRef;
@HostBinding('class.todo') readonly hostClass = true;
@HostBinding('class.completed') get completed(): boolean {
@@ -77,7 +113,10 @@ export class TodoComponent {
}
@Output() remove = this.actions.remove$;
- @Output() update = this.actions.update$;
+ @Output() update = merge(
+ this.actions.toggleDone$,
+ this.actions.updateText$
+ ).pipe(switchMap(() => this.state.select('todo').pipe(take(1))));
constructor() {
rxEffects(({ register }) => {
@@ -97,35 +136,4 @@ export class TodoComponent {
register(focusInputWhenEditing$);
});
}
-
- toggleDone(): void {
- this.state.set(({ todo }) => ({
- todo: {
- ...todo,
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- done: this.toggle!.nativeElement.checked,
- },
- }));
- this.actions.update(this.todo);
- }
-
- edit(): void {
- this.state.set({ isEditing: true });
- }
-
- destroy(): void {
- this.actions.remove(this.todo);
- }
-
- updateText(): void {
- this.state.set(({ todo }) => ({
- isEditing: false,
- todo: {
- ...todo,
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- text: this.input!.nativeElement.value,
- },
- }));
- this.actions.update(this.todo);
- }
}