Skip to main content

Bạn cũng có thể thêm các handler thay đổi dữ liệu, chẳng hạn như POST. Trong hầu hết các trường hợp, bạn nên sử dụng form actions — bạn sẽ viết ít mã hơn và ứng dụng sẽ hoạt động mà không cần JavaScript, làm cho nó chắc chắn hơn.

Bên trong event handler keydown của phần tử <input> 'thêm todo', chúng ta hãy gửi một số dữ liệu đến server:

src/routes/+page.svelte
<input
	type="text"
	autocomplete="off"
	on:keydown={async (e) => {
		if (e.key !== 'Enter') return;

		const input = e.currentTarget;
		const description = input.value;

		const response = await fetch('/todo', {
			method: 'POST',
			body: JSON.stringify({ description }),
			headers: {
				'Content-Type': 'application/json'
			}
		});

		input.value = '';
	}}
/>

Ở đây, chúng ta đang gửi JSON đến API /todo — sử dụng một userid từ cookies của người dùng — và nhận id của todo mới được tạo ra trong phản hồi.

Tạo đường dẫn /todo bằng cách thêm một tệp src/routes/todo/+server.js với một POST handler gọi createTodo trong src/lib/server/database.js:

src/routes/todo/+server.js
import { json } from '@sveltejs/kit';
import * as database from '$lib/server/database.js';

export async function POST({ request, cookies }) {
	const { description } = await request.json();

	const userid = cookies.get('userid');
	const { id } = await database.createTodo({ userid, description });

	return json({ id }, { status: 201 });
}

Tương tự như với các hàm load và form actions, request là một đối tượng Request tiêu chuẩn; await request.json() trả về dữ liệu mà chúng ta đã gửi từ event handler (bộ xử lý sự kiện).

Chúng ta đang trả về một phản hồi với trạng thái 201 Createdid của todo mới được tạo trong cơ sở dữ liệu của chúng ta. Trong event handler, chúng ta có thể sử dụng nó để cập nhật trang:

src/routes/+page.svelte
<input
	type="text"
	autocomplete="off"
	on:keydown={async (e) => {
		if (e.key !== 'Enter') return;

		const input = e.currentTarget;
		const description = input.value;

		const response = await fetch('/todo', {
			method: 'POST',
			body: JSON.stringify({ description }),
			headers: {
				'Content-Type': 'application/json'
			}
		});

		const { id } = await response.json();

		data.todos = [...data.todos, {
			id,
			description
		}];

		input.value = '';
	}}
/>

Bạn chỉ nên cập nhật data hiển thị trên trang nếu biết chắc rằng khi thực hiện tải lại trang kết quả nhận được sẽ như vậy.

Tiếp theo: Other handlers

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<script>
	export let data;
</script>
 
<div class="centered">
	<h1>todos</h1>
 
	<label>
		thêm todo:
		<input
			type="text"
			autocomplete="off"
			on:keydown={async (e) => {
				if (e.key !== 'Enter') return;
 
				const input = e.currentTarget;
				const description = input.value;
				
				// TODO xử lý submit
 
				input.value = '';
			}}
		/>
	</label>
 
	<ul class="todos">
		{#each data.todos as todo (todo.id)}
			<li>
				<label>
					<input
						type="checkbox"
						checked={todo.done}
						on:change={async (e) => {
							const done = e.currentTarget.checked;
 
							// xử lý TODO change
						}}
					/>
					<span>{todo.description}</span>
					<button
						aria-label="Mark as complete"
						on:click={async (e) => {
							// xử lý TODO delete
						}}
					></button>
				</label>
			</li>
		{/each}
	</ul>
</div>
 
<style>
	.centered {
		max-width: 20em;
		margin: 0 auto;
	}
 
	label {
		display: flex;
		width: 100%;
	}
 
	input[type="text"] {
		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;
	}
</style>
	
initialising