Week 11 · Day 05 — 實作:任務 CRUD

學習目標

  • 建立任務 API 服務(get / create / update / delete)
  • 用 NgRx 管理任務狀態
  • 任務列表與編輯頁面

重點

TodoService(CRUD)

@Injectable({ providedIn: 'root' })
export class TodoService {
  private api = 'https://api.example.com/tasks';

  constructor(private http: HttpClient) {}

  getTasks(): Observable<Todo[]>      { return this.http.get<Todo[]>(this.api); }
  createTask(todo: Todo): Observable<Todo> {
    return this.http.post<Todo>(this.api, todo);
  }
  updateTask(todo: Todo): Observable<Todo> {
    return this.http.put<Todo>(`${this.api}/${todo.id}`, todo);
  }
  deleteTask(id: string): Observable<void> {
    return this.http.delete<void>(`${this.api}/${id}`);
  }
}

任務 NgRx state

interface TodoState { todos: Todo[]; loading: boolean; error: string | null }
- effects:loadTasks / createTask / updateTask / deleteTask 呼叫 API - 成功後 dispatch *Success 更新 state - selectors:selectTodos, selectLoading

任務列表頁

todos$ = this.store.select(selectTodos);
loading$ = this.store.select(selectLoading);

ngOnInit(): void { this.store.dispatch(loadTasks()); }
<mat-card *ngFor="let t of todos$ | async; trackBy: trackById">
  <mat-checkbox [checked]="t.status === 'done'"
                (change)="toggle(t)"></mat-checkbox>
  <span>{{ t.title }}</span>
  <button mat-icon-button (click)="edit(t)">...</button>
  <button mat-icon-button (click)="remove(t)">...</button>
</mat-card>

任務編輯頁 - Reactive 表單(title 必填、description、category、tags) - 送出時 dispatch create 或 update

實作

  1. 建立 TodoService(CRUD)
  2. 建立 todo store(services + effects + 更新)
  3. 任務列表頁(顯示、刪除、完成切換)
  4. 任務新增/編輯頁(form + submit)

作業

  • 完成任務 CRUD 服務與 store
  • 列表頁可顯示、完成、刪除任務
  • 編輯頁用表單建立/更新任務