Đăng nhập

BÀI 16: TÌM KIẾM VÀ LỌC TODO (FILTER + SEARCH)

Tìm kiếm và lọc Todo nâng cao là bài học rất quan trọng để nâng tầm Todo App, giúp người dùng dễ dàng lọc và tìm công việc mình quan tâm.

Mục tiêu:

  • Thêm bộ lọc theo trạng thái: Tất cả – Đã làm – Chưa làm
  • Thêm thanh Tìm kiếm theo từ khóa
  • Dùng computed property để xử lý danh sách lọc

Bước 1: Cập nhật TodoList.vue

<template>
  <div>
    <div class="filter">
      <button :class="{active: filter === 'all'}" @click="filter = 'all'">Tất cả</button>
      <button :class="{active: filter === 'done'}" @click="filter = 'done'">✅ Đã làm</button>
      <button :class="{active: filter === 'undone'}" @click="filter = 'undone'">📋 Chưa làm</button>
      <input v-model="keyword" placeholder="🔍 Tìm kiếm..." />
    </div>

    <p v-if="store.loading">⏳ Đang tải...</p>
    <p v-if="store.error" class="error">❌ {{ store.error }}</p>

    <TodoItem
      v-for="todo in filteredTodos"
      :key="todo.id"
      :todo="todo"
      @toggle="store.toggleTodo"
      @delete="store.deleteTodo"
    />
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'
import { useTodoStore } from '@/store/todoStore'
import TodoItem from './TodoItem.vue'

const store = useTodoStore()
onMounted(() => store.fetchTodos())

const filter = ref('all')
const keyword = ref('')

const filteredTodos = computed(() => {
  return store.todos.filter(todo => {
    const matchStatus =
      filter.value === 'all' ||
      (filter.value === 'done' && todo.completed) ||
      (filter.value === 'undone' && !todo.completed)

    const matchKeyword = todo.title.toLowerCase().includes(keyword.value.toLowerCase())

    return matchStatus && matchKeyword
  })
})
</script>

<style scoped>
.filter {
  margin-bottom: 16px;
}
.filter button {
  margin-right: 8px;
  padding: 5px 10px;
}
.filter button.active {
  background-color: #2b8a3e;
  color: white;
}
.filter input {
  margin-left: 10px;
  padding: 6px;
  width: 200px;
}
</style>

Giải thích:

Thành phầnVai trò
filterBiến trạng thái lọc: all, done, undone
keywordChuỗi tìm kiếm nhập vào
filteredTodosDanh sách sau khi lọc theo cả 2 tiêu chí
computed()Theo dõi filter, keyword, store.todos và tự cập nhật danh sách

Tổng kết:

Bạn đã làm được:

  • Bộ lọc thông minh cho danh sách
  • Tìm kiếm theo từ khóa
  • Dùng computed() để tạo logic lọc dễ bảo trì và phản ứng tự động

Bài tập mở rộng:

  1. Hiển thị số lượng:
    • Tổng: 5 việc
    • Đã làm: 3 – Chưa làm: 2
  2. Thêm filter chọn nhiều tiêu chí nâng cao:
    • Ví dụ: “Tìm việc chứa chữ ‘vue’ và chưa hoàn thành”
  3. Tích hợp bộ lọc nâng cao với localStorage để ghi nhớ lựa chọn

Thảo luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

Đăng ký nhận tin mới

Nhận bài học, tài nguyên và cơ hội việc làm qua email hàng tuần.

Chúng tôi cam kết không spam. Bạn có thể hủy bất cứ lúc nào.