Chào các bạn, ở bài viết trước chúng ta đã tiến hành mockup database, khởi tạo server và tiến hành test một số API trên phần mềm postman. Trong bài viết này, chúng ta cùng nhau thực hành làm một ứng dụng todolist cơ bản để thực hành kết nối với API

Trước khi đọc bài viết này các bạn có thể tham khảo lại các bài viết trước để tìm hiểu và thực hành

Về phần giao diện của ứng dụng, các bạn có thể tham khảo link sau: https://github.com/buihien0109/todolist-api/tree/main/public

Trong thư mục chứa project " todolist", chúng ta tạo ra thư mục public, bên trong thư mục này chứa giao diện tĩnh của ứng dụng todolist

Đây là cấu trúc thư mục todolist sau khi bổ sung thư mục public

.
├── database.json
├── node_modules
├── package-lock.json
├── package.json
├── public
│   ├── css
│   ├── img
│   ├── index.html
│   └── js
└── server.js

Tiến hành chạy lại server

$ npm start

Truy cập trình duyệt http://localhost:3000/ và đây là kết quả của chúng ta

giao diện ban đầu

Hiện tại thì trong giao diện ban đầu của ứng dụng todolist, mình có fix cứng code của 2 todo với status là hoàn thành và chưa hoàn thành

Chức năng của ứng dụng

Các chức năng có trong ứng dụng todolist

  1. Lấy danh sách công việc hiện có
  2. Thêm công việc
  3. Sửa công việc
  4. Xóa công việc
  5. Lọc công việc theo trạng thái (tất cả, các công việc đã hoàn thành, các công việc chưa hoàn thành)
  6. Thay đổi trạng thái của công việc (hoàn thành, chưa hoàn thành)

Trong khuôn khổ của bài viết này, mình sẽ hướng dẫn các bạn thực hiện các chức năng

  1. Lấy danh sách công việc hiện có
  2. Thêm công việc
  3. Xóa công việc

Tiến hành thôi nào 😁😁

Lấy danh sách công việc hiện có

Để thực hiện gọi API lấy dữ liệu, mình có sử dụng axios. Ngoài ra các bạn có thể sử dụng fetch API của Javascript để thực hiện

// API lấy danh sách todo
function getTodosAPI() {
    return axios.get("/todos"); // => luôn trả về promise
}

Function getTodosAPI có tác dụng gọi API để lấy danh sach todo, axios.get luôn trả về kết quả cho chúng ta là promise

// Khai báo biến
let todos = [];

// Lấy danh sách todo
async function getTodos() {
    try {
        const res = await getTodosAPI();
        todos = res.data;

        // Render ra ngoài giao diện
        renderUI(todos);
    } catch (error) {
        console.log(error);
    }
}

Function getTodos là một async function, tác dụng gọi getTodosAPI để lấy data, sau khi có data trả về, chúng ta sẽ gán data cho biến todos

Tiếp theo chúng ta thực hiện gọi function renderUI để hiển thị danh sách todo vừa lấy được ra ngoài giao diện

function renderUI được định nghĩa như sau

const todo_list = document.querySelector(".todo-list");

// Render UI - Hiển thị danh sách todo ra ngoài giao diện
function renderUI(arr) {
    todo_list.innerHTML = "";

    // Kiểm tra mảng rỗng
    if (arr.length == 0) {
        todo_list.innerHTML = "Không có công việc nào trong danh sách";
        return;
    }

    // Trường hợp có công việc
    for (let i = 0; i < arr.length; i++) {
        const t = arr[i];
        todo_list.innerHTML += `
            <div class="todo-item ${t.status ? "active-todo" : ""}">
                <div class="todo-item-title">
                    <input type="checkbox" ${t.status ? "checked" : ""}/>
                    <p>${t.title}</p>
                </div>
                <div class="option">
                    <button class="btn btn-update">
                        <img src="./img/pencil.svg" alt="icon" />
                    </button>
                    <button class="btn btn-delete" onclick=deleteTodo(${t.id})>
                        <img src="./img/remove.svg" alt="icon" />
                    </button>
                </div>
            </div>
        `;
    }
}

Kế tiếp, lắng nghe sự kiện onload và gọi function getTodos()

window.onload = () => {
    getTodos();
};

Đây là kết quả sau khi chúng ta thực hiện bước này

kết quả sau khi chúng ta thực hiện

Thêm công việc

// Random ngẫu nhiên Id
function createId() {
    return Math.floor(Math.random() * 100000);
}

// API thêm công việc
function createTodoAPI(title) {
    return axios.post("/todos", {
        id: createId(),
        title: title,
        status: false,
    });
}

Để thêm công việc chúng ta có HTTP method là POST, với tham số đầu vào là title của công việc. Trong phần body của request chúng ta cần gửi lên server bao gồm : id, title, status (mặc định thì status khi tạo sẽ là false)

Id của công việc chúng ta định nghĩa function createId để tạo ngẫu nhiên Id có giá trị trong khoảng từ 0 -> 100000 để tránh sự trùng lặp

// Hàm xử lý việc thêm
async function createTodo(title) {
    try {
        const res = await createTodoAPI(title);
        todos.push(res.data)

        // Render ra ngoài giao diện
        renderUI(todos);
    } catch (error) {
        console.log(error);
    }
}

Tương tự như phần lấy danh sách công việc, chúng ta thực hiện định nghĩa async function createTodo để thực hiện chức năng thêm công việc

Trong function này chúng ta thực hiện gọi createTodoAPI() để thực hiện gọi API thêm công việc. Sau khi API thực hiện xong và trả về kết quả là công việc sau khi tạo. Lúc này chúng ta sẽ thêm công việc đó vào trong mảng todos ban đầu. Đồng thời gọi function renderUI để hiển thị công việc mới sau khi tạo ra ngoài giao diện

const todo_input = document.getElementById("todo-input");
const btn_add = document.getElementById("btn-add");

// Thêm công việc
btn_add.addEventListener("click", function () {
    let todoTitle = todo_input.value; // Lấy ra nội dung trong ô input
    if(todoTitle == "") {
        alert("Tiêu đề không được để trống")
        return
    }

    createTodo(todoTitle)
    todo_input.value = ""
});

Để thêm công việc trên giao diên, đầu tiên chúng ta cần điền tiêu đề vào trong ô input => sau đó bấm " Thêm" để gọi API thêm công việc

Trường hợp tiêu đề của công việc mà để trống, chúng ta cần cảnh báo cho người dùng, để họ tiến hành nhập lại

Sau khi công việc đã thêm thành công, lúc này chúng ta cần clear nội dung trong ô input để người dùng có thể tiến hành nhập công việc khác

Kết quả

Kết quả

Xóa công việc

// API xóa công việc
function deleteTodoAPI(id) {
    return axios({
        method : "delete",
        url : `/todos/${id}`
    })
}

Để xóa công việc, chúng ta định nghĩa function deleteTodoAPI sử dụng HTTP method là " delete" đồng thời cần biết id của của việc mà chúng ta muốn xóa

// Hàm xử lý việc xóa
async function deleteTodo(id) {
    try {
        await deleteTodoAPI(id) // Gọi API xóa

        // Xóa todo trong mảng todos ban đầu
        todos.forEach((todo, index) => {
            if(todo.id == id) {
                todos.splice(index, 1)
            }
        })

        renderUI(todos)

    } catch (error) {
        console.log(error);
    }
}

Function deleteTodo có tác dụng gọi function deleteTodoAPI để gọi API xóa công việc trên server

Sau khi API thực hiện thành công, chúng ta cần xóa todo có id tương ứng trong mảng todos ban đầu, đồng thời sau đó gọi function renderUI để hiển thị lại giao diện sau khi xóa công việc

Kết quả

Kết quả

Các bạn có thể tham khảo source code của bài viết này tại đây : https://github.com/buihien0109/todolist-api

Các bài tiếp tiếp theo trong series này:

  1. Ứng dụng todolist + Kết nối API : Lập trình chức năng (Phần 3)
  2. Ứng dụng todolist + Kết nối API : Deploy ứng dụng lên Heroku (Phần 4)

Các bạn có thể tham khảo thêm khóa học này nhé:

  • Javascript căn bản - Tổng hợp 12 game huyền thoại - tại đây.
  • Lập trình Game Javascript (trực tuyến có tương tác) - tại đây.