Jak zbudować formularz na stronie: znacznik form z atrybutami action i method, pola input i ich typy, etykiety, listy wyboru, walidacja HTML5 oraz różnica między metodą GET i POST. Lekcja 3.7 kursu INF.03.
Formularz to zestaw pól, w które użytkownik wpisuje dane, oraz przycisk, który wysyła te dane na serwer. Bez formularza strona tylko pokazuje treść: logowanie, wyszukiwarka, komentarz i zamówienie zaczynają się właśnie od niego. W części pisemnej wracają pytania z rysunkiem („który kod dał ten zestaw kontrolek", „co pokaże przeglądarka po wysłaniu", „GET czy POST", „co robi required i pattern"). W zadaniu praktycznym arkusz każe zwykle zrobić formularz wysyłany metodą POST do tej samej strony, z polami numerycznymi, przyciskiem wysyłającym i przyciskiem kasującym.
Znacznik form: dokąd i jaką metodą
<form> (FORMULARZ) to pojemnik obejmujący wszystkie pola należące do jednej wysyłki. Kontrolka postawiona poza nim wyświetli się normalnie, ale nie wyśle niczego. O zachowaniu formularza decydują dwa atrybuty.
›
action (adres celu) wskazuje plik, który odbierze dane. Pusta wartość action="" albo pominięty atrybut kieruje dane pod adres bieżącej strony, i dokładnie o to prosi arkusz CKE zdaniem „formularz przesyłający dane do tego samego pliku".
›
method (metoda) wybiera sposób przesłania: get albo post. Pominięty method znaczy get.
Każde pole ma osobny atrybut name (nazwa). To klucz, pod którym serwer odbiera wpisaną wartość: pole name="imie" wysłane metodą POST czeka po stronie PHP pod $_POST['imie'], a wysłane metodą GET pod $_GET['imie']. Pole bez name nie jest w ogóle wysyłane, więc brak tego atrybutu to najcichszy błąd w całym formularzu. Odbieraniem i przetwarzaniem danych zajmuje się dział o PHP.
<form action="zamow.php" method="post">
<label for="imie">Imię</label>
<input type="text" id="imie" name="imie">
<input type="submit" value="Zamów">
</form>
Metoda GET dopisuje dane do adresu: po znaku zapytania idą pary nazwa i wartość, oddzielone znakiem &. Adres zamow.php?imie=Anna&ilosc=2 niesie całą treść formularza, więc widać ją w pasku przeglądarki, można ją zapisać w zakładce i wysłać komuś odnośnikiem, a długość adresu jest ograniczona. Metoda POST pakuje te same dane w treść żądania HTTP, której pasek adresu nie pokazuje i której rozmiar praktycznie nie ma limitu.
Formularz zamówienia i dwie drogi na serwer: GET dopisuje dane do adresu zamow.php?imie=Anna&ilosc=2, POST wysyła je w treści żądania
Gdzie jadą dane
w adresie, po znaku zapytania
w treści żądania
Widać je w pasku adresu
tak
nie
Zakładka, historia, odnośnik
tak
nie
Limit długości
tak, adres ma ograniczoną długość
praktycznie brak
Do czego
wyszukiwanie, filtry, odnośniki do wyników
hasła, zamówienia, zmiany w bazie
Ukrycie danych w treści żądania to nie jest szyfrowanie. Wysłane zwykłym protokołem HTTP dane POST da się podejrzeć w sieci tak samo jak GET, a poufność daje dopiero HTTPS, więc pytanie o najbezpieczniejszy sposób wysłania danych poufnych ma odpowiedź: metoda POST przez HTTPS. Oba protokoły opisuje lekcja Jak działa strona WWW. Trzeci atrybut <form> pojawia się tylko przy wysyłaniu plików: enctype="multipart/form-data" (wieloczęściowe dane formularza) każe podzielić żądanie na części i wstawić w jedną z nich zawartość pliku. Bez tego atrybutu pole wyboru pliku prześle samą nazwę, bez treści. Wysyłka pliku wymaga też metody POST.
Pole input i jego typy
<input> (pole wejściowe) to jeden znacznik, z którego atrybut type robi kilkanaście różnych kontrolek. Znacznik nie ma części zamykającej i w HTML5 pisze się go bez ukośnika.
Typ
Do czego służy
Przykład
text
krótki tekst, typ domyślny
<input type="text" name="imie">
password
hasło, wpisywane znaki są maskowane
<input type="password" name="haslo">
email
adres poczty, sprawdzany przez przeglądarkę
<input type="email" name="mail">
number
tylko liczby, z min, max i step
<input type="number" name="ilosc" min="1" max="10">
range
suwak w podanym zakresie
<input type="range" name="ocena" min="1" max="5">
date
data wybierana z kalendarza
<input type="date" name="dostawa">
time
godzina
<input type="time" name="odbior">
color
próbnik koloru
<input type="color" name="kolor">
checkbox
pole wyboru, kilka zaznaczeń naraz
<input type="checkbox" name="regulamin" checked>
radio
jedna opcja z kilku, wspólny name
<input type="radio" name="platnosc" value="karta">
file
wybór pliku do wysłania
<input type="file" name="zdjecie">
hidden
wartość niewidoczna, wysyłana razem z resztą
<input type="hidden" name="id" value="7">
submit
przycisk wysyłający formularz
<input type="submit" value="Zamów">
reset
przycisk kasujący wpisane dane
<input type="reset" value="Wyczyść">
button
przycisk bez własnego działania, dla skryptu
<input type="button" value="Licz">
Przyciski opcji (radio) tworzą grupę przez WSPÓLNĄ wartość name: tylko wtedy zaznaczenie jednego odznacza pozostałe. Pola wyboru (checkbox) zaznacza się niezależnie od siebie, więc każde może mieć własną nazwę. Atrybut checked zaznacza kontrolkę od razu po wczytaniu strony, a value mówi, co poleci na serwer, bo napis stojący obok kontrolki jest tylko etykietą.
name
klucz, pod którym serwer odbiera wartość pola
value
wartość początkowa, wysyłana razem z formularzem
placeholder
szara podpowiedź w pustym polu, znika po rozpoczęciu pisania
maxlength
największa liczba znaków, jaką da się wpisać
size
szerokość pola na ekranie, liczona w znakach
readonly
wartość widoczna i wysyłana, ale nie do zmiany
disabled
kontrolka wyszarzona i pomijana przy wysyłce
autofocus
kursor stoi w tym polu zaraz po wczytaniu strony
Pułapka: maxlength ogranicza liczbę wpisanych znaków, size tylko szerokość pola na ekranie. Pole z maxlength="20" size="30" przyjmie 20 znaków, a nie 30.
Etykiety, listy i grupy pól
<label> (etykieta) to podpis związany z konkretną kontrolką. Wiąże się przez parę atrybutów: for etykiety ma tę samą wartość co id pola. Zysk jest podwójny. Kliknięcie w napis ustawia kursor w polu, a przy checkbox i radio zaznacza kontrolkę, co przy małym kwadraciku na telefonie ma spore znaczenie. Czytnik ekranu odczytuje wtedy podpis razem z polem, więc osoba niewidoma wie, co wpisuje. Wariant drugi to zagnieżdżenie: gdy kontrolka stoi w środku znacznika <label>, atrybuty for i id nie są potrzebne.
<textarea> (obszar tekstu) to pole na dłuższy tekst, wysokie na rows wierszy i szerokie na cols znaków. Tekst początkowy wpisuje się MIĘDZY znaczniki, nie w atrybut value. <select> (lista wyboru) tworzy listę rozwijaną, a każdą pozycję opisuje <option> (opcja). Na serwer leci value opcji, a nie jej widoczny napis, natomiast selected wskazuje pozycję zaznaczoną na starcie. Atrybut size pokazuje kilka pozycji naraz zamiast listy rozwijanej, a multiple pozwala zaznaczyć kilka pozycji jednocześnie. <optgroup> z atrybutem label dzieli długą listę na nazwane części.
<label for="uwagi">Uwagi do zamówienia</label>
<textarea id="uwagi" name="uwagi" rows="4" cols="30"></textarea>
<label for="dostawa">Dostawa</label>
<select id="dostawa" name="dostawa">
<optgroup label="Kurier">
<option value="dpd">DPD</option>
<option value="inpost" selected>InPost</option>
</optgroup>
<option value="odbior">Odbiór osobisty</option>
</select>
<datalist> daje zwykłemu polu tekstowemu listę podpowiedzi, ale nie zabrania wpisać czegoś spoza niej, i to odróżnia go od listy <select>. <fieldset> (zestaw pól) grupuje powiązane ze sobą kontrolki i rysuje wokół nich ramkę, a <legend> podpisuje tę grupę.
<button> (przycisk) robi to samo co input typu przycisk, tylko treść bierze spomiędzy znaczników, więc mieści obraz albo pogrubione słowo. Jego atrybut type przyjmuje submit (wysyła, wartość domyślna), reset (kasuje) oraz button (przycisk bez własnego działania, czekający na skrypt JavaScript). <output> pokazuje wynik wyliczony skryptem, na przykład kwotę zamówienia policzoną z ilości i ceny.
Walidacja HTML5
Walidacja formularza to sprawdzenie, czy wprowadzone dane spełniają określone reguły. HTML5 potrafi to zrobić bez żadnego skryptu: przy próbie wysłania przeglądarka zatrzymuje formularz, ustawia kursor w błędnym polu i wyświetla przy nim dymek z komunikatem.
required
pole nie może zostać puste
type="email"
wartość wygląda jak adres poczty, czyli zawiera znak @
type="number" z min i max
tylko liczba i tylko z podanego zakresu
step
co ile wolno zmieniać wartość, na przykład step="0.5"
minlength, maxlength
najmniejsza i największa liczba znaków
pattern="[0-9]{2}-[0-9]{3}"
wartość pasuje do wyrażenia regularnego
title="Format 00-000"
tekst dopisany do komunikatu o błędzie
novalidate w <form>
wyłącza całe sprawdzanie przy wysyłce
Wyrażenie regularne [0-9]{2}-[0-9]{3} czyta się kawałek po kawałku: [0-9] to jedna cyfra, {2} to dokładnie dwa takie znaki, potem zwykły dywiz, potem trzy cyfry. Wzorzec musi pasować do CAŁEJ wartości, więc 12-345 przechodzi, a 12-3456 już nie.
<label for="kod">Kod pocztowy</label>
<input type="text" id="kod" name="kod" required
pattern="[0-9]{2}-[0-9]{3}" title="Format 00-000">
Sprawdzanie w przeglądarce jest wygodą dla użytkownika, a nie zabezpieczeniem: dane da się wysłać z pominięciem strony, więc te same reguły muszą powtórzyć się w skrypcie po stronie serwera. Osobna sprawa to sprawdzanie w trakcie pisania, znak po znaku, z komunikatem obok pola: tego atrybuty HTML5 nie robią, pisze się to w języku JavaScript.
Formularz zamówienia w sklepie
<form action="" method="post">
<fieldset>
<legend>Zamówienie</legend>
<label for="imie">Imię i nazwisko</label>
<input type="text" id="imie" name="imie" required maxlength="40">
<label for="produkt">Produkt</label>
<select id="produkt" name="produkt">
<option value="klawiatura">Klawiatura</option>
<option value="mysz" selected>Mysz</option>
<option value="monitor24">Monitor 24</option>
</select>
<label for="ilosc">Ilość</label>
<input type="number" id="ilosc" name="ilosc" min="1" max="10" value="1">
<input type="submit" value="Zamów">
<input type="reset" value="Wyczyść">
</fieldset>
</form>
W przeglądarce widać ramkę z napisem „Zamówienie" wpisanym w jej górną krawędź, a w środku podpisane pole tekstowe, listę rozwijaną z trzema produktami (od razu wybrana jest Mysz), pole liczbowe ze strzałkami i wartością 1 oraz dwa przyciski. Naciśnięcie przycisku „Zamów" z pustym imieniem nie wysyła niczego: przeglądarka pokazuje dymek przy pierwszym błędnym polu. Po poprawnym wypełnieniu strona wczytuje się ponownie pod tym samym adresem, bo action jest puste, a pasek adresu nie zmienia się, bo metodą jest POST. Przycisk „Wyczyść" przywraca wartości początkowe, czyli puste imię, Mysz i 1.
Pułapka: reset przywraca wartości POCZĄTKOWE zapisane w kodzie, a nie puste pola. Pole z value="1" po wyczyszczeniu znowu pokazuje 1.
Na egzaminie
Pytania pisemne o formularze mają kilka stałych kształtów. Rysunek z zestawem kontrolek i cztery bloki kodu do wyboru: policz kontrolki i sprawdź, które są polami tekstowymi, która listą, a które przyciskami. Fragment kodu z jednym polem i pytanie, co o nim wiadomo: type="password" ukrywa wpisywane znaki, type="number" przyjmuje wyłącznie wartości liczbowe, readonly pokazuje wartość bez możliwości zmiany. Pytanie o grupowanie: powiązane ze sobą elementy formularza grupuje <fieldset>, a nie <optgroup>, który obejmuje wyłącznie opcje listy. Pytanie o walidację: pole z required i wzorcem wymagającym znaku @ znaczy „nie może być puste i wymaga tekstu ze znakiem @". Pytanie z adresem po wysłaniu: skoro w pasku widać ?imie=Anna, metodą była GET, a dane czekają w tablicy $_GET.
Kilka odpowiedzi myli się regularnie. placeholder to podpowiedź w polu, znikająca po rozpoczęciu pisania, a value to wartość domyślna, która w polu zostaje i zostanie wysłana. Kilka zaznaczeń naraz daje checkbox, jedno z kilku daje radio ze wspólnym name, a wielokrotny wybór z listy rozwijanej włącza atrybut multiple w znaczniku <select>. Walidacja to sprawdzenie, czy wprowadzone dane spełniają określone reguły, a nie sprawdzenie, kto je wprowadził ani czy plik odbierający istnieje.
W zadaniu praktycznym polecenie brzmi zwykle: formularz wysyłany metodą POST do tego samego pliku, z polami numerycznymi, przyciskiem wysyłającym i przyciskiem kasującym. Tłumaczy się je punkt po punkcie. „Metoda POST do tego samego pliku" to method="post" i action="", „pole numeryczne" to type="number", „przycisk wysyłający" to type="submit", „przycisk kasujący" to type="reset". Nazwy pól muszą zgadzać się co do znaku z tym, czego szuka skrypt PHP dołączony do arkusza: name="ilosc" po stronie strony i $_POST['ilosc'] po stronie skryptu. Każde pole dostaje etykietę, bo oceniana jest zawartość witryny, a sam napis obok kontrolki podpisem nie jest. Egzaminator klika po gotowej stronie, więc formularz musi się wyświetlić i zareagować na oba przyciski.
Ściąga
<form action="" method="post">
formularz wysyłany metodą POST do tej samej strony
method="get"
dane w adresie, widoczne, można je zapisać w zakładce
<input type="text" name="imie">
pole tekstowe, name to klucz odbioru na serwerze
<input type="number" min="1" max="10">
pole numeryczne z zakresem wartości
<input type="password">
pole hasła, maskuje wpisywane znaki
<input type="submit" value="Zamów">
przycisk wysyłający formularz
<input type="reset" value="Wyczyść">
przycisk przywracający wartości początkowe
<label for="imie">
etykieta pola o id="imie", klikalna
<select> z <option value="mysz">
lista rozwijana, selected to opcja domyślna
<fieldset> z <legend>
grupuje powiązane kontrolki i podpisuje grupę
required
pole nie może zostać puste
pattern="[0-9]{2}-[0-9]{3}"
wartość musi pasować do wzorca, tu kod pocztowy
Pobierz ściągę PDF