INTEGRITY Dokumentace

Vytvořte HTML formulář

V tomto tutoriálu vytvoříte jednoduchý <form> pomocí čistého HTML a CSS a nasaďte ho na Cloudflare Pages. Přitom se seznámíte s některými atributy HTML formulářů a s tím, jak odeslaná data zpracovat ve Workeru.

Tento tutoriál hojně využívá Cloudflare Pages a jeho integrace s Workers. Přečtěte si Úvodní návod průvodce a seznamte se s platformou.

Přehled

Formuláře jsou na webu běžným bodem interakce mezi uživatelem a webovým dokumentem. Umožňují uživateli zadat data a obvykle je odeslat na server. Formulář se skládá alespoň z jednoho vstupního pole, kterým může být textové pole, rozbalovací seznam, zaškrtávací políčko a podobně.

Každý vstup by měl mít název, a to pomocí name atribut, aby hodnota vstupu měla při přijetí na serveru identifikovatelný název. S příchodem HTML5 navíc mohou prvky formuláře deklarovat další atributy pro zapnutí automatické validace formuláře. Dostupné validace se liší podle typu vstupu, například textový vstup přijímající e-maily (přes type=email) může zajistit, že hodnota vypadá jako platná e-mailová adresa, číselné pole (přes type=number) přijme pouze celá čísla nebo desetinné hodnoty (pokud jsou povoleny) a obecná textová pole mohou definovat vlastní pattern k povolení. Všechny vstupy nicméně mohou určit, zda je hodnota required.

Níže je příklad formuláře HTML5 s několika vstupy a definovanými validačními pravidly:

<form method="POST" action="/api/submit">
	<input type="text" name="fullname" pattern="[A-Za-z]+" required />
	<input type="email" name="email" required />
	<input type="number" name="age" min="18" required />

	<button type="submit">Submit</button>
</form>

Pokud má formulář HTML5 definovaná pravidla validace, prohlížeč je při pokusu o odeslání formuláře automaticky zkontroluje. Pokud dojde k chybě, odeslání se zablokuje a prohlížeč zobrazí uživateli chybové hlášení k opravě. Atribut <form> pouze POST data do /submit endpoint when there are no outstanding validation errors. This entire process is native to HTML5 and only requires the appropriate form and input attributes to exist, no JavaScript is required.

Prvky formuláře mohou mít také <label> element, který k nim náleží, což vám umožňuje jasně popsat každé vstupní pole. To je užitečné zejména z hlediska vizuální přehlednosti, ale zároveň to vede k přístupnějšímu uživatelskému prostředí, protože HTML markup je lépe definovaný. Asistivní technologie z toho přímo těží, obrazovkové čtečky tak mohou oznámit, který <input> má fokus. A když se <label> klikne, aktivuje se namísto něj přiřazený vstupní prvek formuláře, čímž se zvětší plocha pro kliknutí.

Chcete-li to povolit, musíte vytvořit <label> element pro každé vstupní pole a každému z nich přiřadit <input> element a jedinečný id hodnotu atributu. <label> musí mít také for atribut, který odráží jedinečný id hodnotu. Úpravou předchozího úryvku byste měli získat následující:

<form method="POST" action="/api/submit">
	<label for="i-fullname">Full Name</label>
	<input
		id="i-fullname"
		type="text"
		name="fullname"
		pattern="[A-Za-z]+"
		required
	/>

	<label for="i-email">Email Address</label>
	<input id="i-email" type="email" name="email" required />

	<label for="i-age">Your Age</label>
	<input id="i-age" type="number" name="age" min="18" required />

	<button type="submit">Submit</button>
</form>

Když tento <form> odešle s platnými daty, jeho obsah se odešle na server. Způsob a cíl odeslání dat můžete přizpůsobit deklarací atributů přímo na formuláři. Pokud tyto údaje neuvedete, <form> odešle data metodou GET na aktuální URL adresu, což většinou není požadované chování. Abyste to opravili, musíte minimálně definovat action atribut s cílovou adresou URL, ale uvedení method se také často doporučuje, i když jen znovu deklarujete výchozí GET hodnota.

HTML formuláře ve výchozím nastavení odesílají svůj obsah ve formátu application/x-www-form-urlencoded typu MIME. Tato hodnota se projeví v Content-Type HTTP hlavičku, kterou musí přijímající server přečíst, aby určil, jak zpracovat obsah dat. Typ MIME můžete přizpůsobit pomocí enctype atribut. Chcete-li například přijímat soubory (přes type=file), musíte změnit enctype do multipart/form-data hodnotu:

<form method="POST" action="/api/submit" enctype="multipart/form-data">
	<label for="i-fullname">Full Name</label>
	<input
		id="i-fullname"
		type="text"
		name="fullname"
		pattern="[A-Za-z]+"
		required
	/>

	<label for="i-email">Email Address</label>
	<input id="i-email" type="email" name="email" required />

	<label for="i-age">Your Age</label>
	<input id="i-age" type="number" name="age" min="18" required />

	<label for="i-avatar">Profile Picture</label>
	<input id="i-avatar" type="file" name="avatar" required />

	<button type="submit">Submit</button>
</form>

Protože enctype změní, prohlížeč změní i způsob, jakým odesílá data na server. Content-Type HTTP hlavička bude odrážet nový přístup a tělo HTTP požadavku bude odpovídat novému typu MIME. Přijímající server musí tento nový formát podporovat a přizpůsobit mu způsob zpracování požadavku.

Živý příklad

Zbytek tohoto tutoriálu se zaměří na vytvoření formuláře HTML na Pages včetně Workeru pro příjem a zpracování odeslaných dat formuláře.

Nastavení

Nejprve vytvořte nový repozitář GitHub. Poté na svém počítači vytvořte nový lokální adresář, inicializujte git a připojte umístění na GitHubu jako vzdálený cíl:

# create new directory
mkdir new-project
# enter new directory
cd new-project
# initialize git
git init
# attach remote
git remote add origin [email protected]:<username>/<repo>.git
# change default branch name
git branch -M main

Nyní můžete začít pracovat v new-project adresář, který jste vytvořili.

Výstup

Formulář pro tento příklad je poměrně jednoduchý. Obsahuje řadu různých typů vstupů včetně zaškrtávacích políček pro výběr více hodnot. Formulář také neobsahuje žádné validace, abyste viděli, jak se prázdné nebo chybějící hodnoty interpretují na serveru.

You will only be using plain HTML for this example project. You may use your preferred JavaScript framework, but raw languages have been chosen for simplicity and familiarity, all frameworks are abstracting and/or producing a similar result.

Vytvořte public/index.html v adresáři projektu. Veškerá frontendová aktiva se budou nacházet v tomto public adresář a tento index.html soubor bude sloužit jako domovská stránka webu.

Zkopírujte a vložte následující obsah do public/index.html soubor:

<html lang="en">
	<head>
		<meta charset="utf8" />
		<title>Form Demo</title>
		<meta name="viewport" content="width=device-width,initial-scale=1" />
	</head>
	<body>
		<form method="POST" action="/api/submit">
			<div class="input">
				<label for="name">Full Name</label>
				<input id="name" name="name" type="text" />
			</div>

			<div class="input">
				<label for="email">Email Address</label>
				<input id="email" name="email" type="email" />
			</div>

			<div class="input">
				<label for="referers">How did you hear about us?</label>
				<select id="referers" name="referers">
					<option hidden disabled selected value></option>
					<option value="Facebook">Facebook</option>
					<option value="Twitter">Twitter</option>
					<option value="Google">Google</option>
					<option value="Bing">Bing</option>
					<option value="Friends">Friends</option>
				</select>
			</div>

			<div class="checklist">
				<label>What are your favorite movies?</label>
				<ul>
					<li>
						<input id="m1" type="checkbox" name="movies" value="Space Jam" />
						<label for="m1">Space Jam</label>
					</li>
					<li>
						<input
							id="m2"
							type="checkbox"
							name="movies"
							value="Little Rascals"
						/>
						<label for="m2">Little Rascals</label>
					</li>
					<li>
						<input id="m3" type="checkbox" name="movies" value="Frozen" />
						<label for="m3">Frozen</label>
					</li>
					<li>
						<input id="m4" type="checkbox" name="movies" value="Home Alone" />
						<label for="m4">Home Alone</label>
					</li>
				</ul>
			</div>

			<button type="submit">Submit</button>
		</form>
	</body>
</html>

Tento HTML dokument bude obsahovat formulář s několika poli, které uživatel vyplní. Formulář neobsahuje žádná validační pravidla, všechna pole jsou tedy nepovinná a uživatel může odeslat i prázdný formulář. V tomto příkladu jde o zamýšlené chování.

Worker

Formulář HTML je hotový a připravený k nasazení. Když uživatel formulář odešle, všechna data budou odeslána ve formátu POST požadavek na /api/submit URL. Je to dáno tím, že formulář method a action atributy. V současnosti však neexistuje žádný request handler na /api/submit adresu. Nyní ji vytvoříte.

Cloudflare Pages nabízí Funkce funkci, která umožňuje definovat a nasazovat Workers pro dynamické chování.

Functions jsou propojeny s functions adresář a pohodlně vytvářet obslužné rutiny URL požadavků ve vztahu k functions struktura souboru. Například functions/about.js soubor se namapuje na /about URL a functions/hello/[name].js zpracuje /hello/:name vzor URL, kde :name představuje libovolný odpovídající segment URL. Více informací najdete v Směrování Functions dokumentaci, kde najdete další informace.

Chcete-li definovat handler pro /api/submit, musíte vytvořit functions/api/submit.js soubor. To znamená, že váš functions a public adresáře by měly být na stejné úrovni, celková struktura projektu by měla vypadat přibližně takto:

├── functions
│   └── api
│       └── submit.js
└── public
    └── index.html

<form> odešle POST požadavky, což znamená, že functions/api/submit.js soubor musí exportovat onRequestPost handler:

/**
 * POST /api/submit
 */
export async function onRequestPost(context) {
	// TODO: Handle the form submission
}

context je objekt obsahující několik hodnot, které mohou být užitečné. Pro tento příklad budete potřebovat pouze Request objekt, ke kterému máte přístup prostřednictvím context.request klíč.

Jak již bylo zmíněno, <form> je ve výchozím nastavení application/x-www-form-urlencoded typu MIME při odesílání. A pro pokročilejší scénáře enctype="multipart/form-data" atribut. Naštěstí lze oba typy MIME zpracovat a považovat je za FormData. To znamená, že u Workers (což zahrnuje i Pages Functions) můžete použít nativní Request.formData parser.

Pro ilustraci obslužná rutina formuláře v ukázkové aplikaci odpoví všemi přijatými hodnotami. Požadavek Response musí handler vždy vrátit i

/**
 * POST /api/submit
 */
export async function onRequestPost(context) {
	try {
		let input = await context.request.formData();
		let pretty = JSON.stringify([...input], null, 2);
		return new Response(pretty, {
			headers: {
				"Content-Type": "application/json;charset=utf-8",
			},
		});
	} catch (err) {
		return new Response("Error parsing JSON content", { status: 400 });
	}
}

Jakmile je tento handler na místě, je příklad plně funkční. Po přijetí odeslaného formuláře Worker odpoví seznamem JSON obsahujícím FormData dvojice klíč-hodnota.

Pokud však chcete odpovědět objektem JSON namísto dvojic klíč-hodnota (polem polí), musíte to udělat ručně. JavaScript nedávno přidal Object.fromEntries nástroj. To v některých případech funguje dobře, ovšem příklad <form> obsahuje movies zaškrtávací seznam, který umožňuje více hodnot. Pokud používáte Object.fromEntries, vygenerovaný objekt by si ponechal jen jeden z movies hodnoty a zbytek zahodí. Abyste tomu předešli, musíte si napsat vlastní FormData na Object nástroj místo toho:

/**
 * POST /api/submit
 */
export async function onRequestPost(context) {
	try {
		let input = await context.request.formData();

		// Convert FormData to JSON
		// NOTE: Allows multiple values per key
		let output = {};
		for (let [key, value] of input) {
			let tmp = output[key];
			if (tmp === undefined) {
				output[key] = value;
			} else {
				output[key] = [].concat(tmp, value);
			}
		}

		let pretty = JSON.stringify(output, null, 2);
		return new Response(pretty, {
			headers: {
				"Content-Type": "application/json;charset=utf-8",
			},
		});
	} catch (err) {
		return new Response("Error parsing JSON content", { status: 400 });
	}
}

Poslední úryvek kódu (výše) umožňuje Workeru zachovat všechny hodnoty a vrátit odpověď JSON s přesným zobrazením <form> odeslání.

Nasazení

Nyní jste připraveni nasadit svůj projekt.

Pokud jste tak ještě neučinili, uložte si postup v git a poté odešlete commit (nebo commity) do repozitáře GitHub:

# Add all files
git add -A
# Commit w/ message
git commit -m "working example"
# Push commit(s) to remote
git push -u origin main

Vaše práce se nyní nachází v repozitáři GitHub, což znamená, že k ní má přístup i Pages.

Pokud je toto váš první projekt Cloudflare Pages, přečtěte si Úvodní návod s kompletním postupem. Po výběru příslušného repozitáře GitHub musíte projekt nakonfigurovat s následujícím nastavením sestavení:

Po kliknutí na Save and Deploy spustí se první nasazení vašeho projektu Pages. Po úspěšném dokončení se zobrazí jedinečná *.pages.dev subdoména a odkaz na živou ukázku.

V tomto tutoriálu jste vytvořili a nasadili web i jeho backendovou logiku pomocí Cloudflare Pages s integrací Workers. Vytvořili jste statický HTML dokument s formulářem, který komunikuje s handlerem Workeru zajišťujícím zpracování odeslaných požadavků.

Pokud si chcete prohlédnout celý zdrojový kód této aplikace, najdete ho na GitHub.