Trong chương về tải dữ liệu, chúng ta đã thấy cách lấy dữ liệu từ server tới trình duyệt. Đôi khi, bạn cần gửi dữ liệu theo hướng ngược lại, và đó là lúc <form> — cách mà nền tảng web gửi dữ liệu — xuất hiện.
Hãy cùng xây dựng một ứng dụng todo. Chúng ta đã có một cơ sở dữ liệu trên bộ nhớ được thiết lập trong src/lib/server/database.js, và hàm load trong src/routes/+page.server.js sử dụng API cookies để mỗi người dùng có một danh sách todo riêng, nhưng ta cần thêm một <form> để tạo todo mới:
<h1>todos</h1>
<form method="POST">
<label>
Thêm todo:
<input
name="description"
autocomplete="off"
/>
</label>
</form>
<ul class="todos">Nếu chúng ta gõ gì đó vào và nhấn Enter, trình duyệt sẽ tạo một yêu cầu POST (nhờ thuộc tính method="POST") đến trang hiện tại. Nhưng sẽ có lỗi vì ta chưa tạo một action (hành động) ở phía server để xử lý yêu cầu POST. Hãy làm điều đó ngay bây giờ:
import * as db from '$lib/server/database.js';
export function load({ cookies }) {
// ...
}
export const actions = {
default: async ({ cookies, request }) => {
const data = await request.formData();
db.createTodo(cookies.get('userid'), data.get('description'));
}
};request là một đối tượng Request tiêu chuẩn; await request.formData() trả về một FormData.
Khi chúng ta nhấn Enter, cơ sở dữ liệu được cập nhật và trang tải lại với dữ liệu mới.
Lưu ý: chúng ta không cần viết bất kỳ mã fetch nào hoặc những câu lệnh tương tự — cập nhật dữ liệu tự động xảy ra. Và vì chúng ta đang sử dụng phần tử
<script>
export let data;
</script>
<div class="centered">
<h1>todos</h1>
<ul class="todos">
{#each data.todos as todo (todo.id)}<li>
{todo.description}</li>
{/each}</ul>
</div>
<style>
.centered {max-width: 20em;
margin: 0 auto;
}
label {width: 100%;
}
input {flex: 1;
}
span {flex: 1;
}
button {border: none;
background: url(./remove.svg) no-repeat 50% 50%;
background-size: 1rem 1rem;
cursor: pointer;
height: 100%;
aspect-ratio: 1;
opacity: 0.5;
transition: opacity 0.2s;
}
button:hover {opacity: 1;
}
.saving {opacity: 0.5;
}
</style>