Week 11 · Day 07 — 實作:搜尋與篩選(第十一週收尾)
學習目標
- 實作任務搜尋
- 依狀態 / 分類 / 標籤篩選
- 完成整個 MVP 專案並複習
重點
篩選狀態變數
export type Filter = 'all' | 'todo' | 'in-progress' | 'done';
filterBy: Filter = 'all';
searchTerm = '';
selectedCategory = '';
用 selector 做純函式篩選(推薦)
import { createSelector } from '@ngrx/store';
export const selectVisibleTodos = createSelector(
selectTodos,
selectFilter, // { status?, category?, search }
(todos, filter) => {
return todos.filter(t => {
const matchStatus =
!filter.status || filter.status === 'all' || t.status === filter.status;
const matchSearch =
!filter.search ||
t.title.toLowerCase().includes(filter.search.toLowerCase());
return matchStatus && matchSearch;
});
}
);
任務列表套用
<mat-form-field>
<input matInput placeholder="搜尋..." (input)="onSearch($event)">
</mat-form-field>
<mat-button-toggle-group [(ngModel)]="filterBy">
<mat-button-toggle value="all">全部</mat-button-toggle>
<mat-button-toggle value="todo">待辦</mat-button-toggle>
<mat-button-toggle value="done">已完成</mat-button-toggle>
</mat-button-toggle-group>
<ul>
<li *ngFor="let t of (visible$ | async)!; trackBy: trackById">{{ t.title }}</li>
</ul>
處理搜尋
onSearch(e: any): void {
const term = (e.target as HTMLInputElement).value;
this.store.dispatch(setSearch({ term })); // 更新 filter state
}
建議
- 搜尋用 debounceTime 減低即時打字的負擔
- 篩選邏輯放 selector(純函式)方便測試
實作
- 建立
setFilter/setSearchaction 更新 filter state - 寫
selectVisibleTodos同時處理狀態與關鍵字 - 列表套用篩選,測試「全部/待辦/已完成」交換
- 收尾:確認整個 MVP 流程順暢
作業
- 用 selector 實作狀態與關鍵字篩選
- 列表可交換篩選並搜尋
- 完整走一遍 MVP(登入 → 建任務 → 篩選 → 完成)
總結
你已完成「任務管理系統」MVP!整合了 Angular、Material、NgRx、REST API。下一週處理上線——部署與維護。