Validace formulářů
Povinné prvky
Povinné prvky označíme metodou setRequired()
, jejíž argument je text chybové
hlášky, která se zobrazí, pokud uživatel prvek nevyplní. Pokud argument neuvedeme, použije se výchozí chybová
hláška.
Pravidla
Validační pravidla přidáváme prvkům metodou addRule()
. První parametr je pravidlo, druhý je text chybové hlášky a třetí je argument validačního pravidla.
Validační pravidla se ověřují pouze v případě, že uživatel prvek vyplnil.
Nette přichází s celou řadu předdefinovaných pravidel, jejichž názvy jsou konstanty třídy
Nette\Forms\Form
. U všech prvků můžeme použít tyto pravidla:
konstanta | popis | typ argumentu |
---|---|---|
Required |
povinný prvek, alias pro setRequired() |
– |
Filled |
povinný prvek, alias pro setRequired() |
– |
Blank |
prvek nesmí být vyplněn | – |
Equal |
hodnota se rovná parametru | mixed |
NotEqual |
hodnota se nerovná parametru | mixed |
IsIn |
hodnota se rovná některé položce v poli | array |
IsNotIn |
hodnota se nerovná žádné položce v poli | array |
Valid |
je prvek vyplněn správně? (pro podmínky) | – |
Textové vstupy
U prvků addText()
, addPassword()
, addTextArea()
, addEmail()
,
addInteger()
, addFloat()
lze použít i některá následující pravidla:
MinLength |
minimální délka textu | int |
MaxLength |
maximální délka textu | int |
Length |
délka v rozsahu nebo přesná délka | dvojice [int, int] nebo int |
Email |
platná e-mailová adresa | – |
URL |
absolutní URL | – |
Pattern |
vyhovuje regulárnímu výrazu | string |
PatternInsensitive |
jako Pattern , ale nezávislé na velikosti písmen |
string |
Integer |
celočíselná hodnota | – |
Numeric |
alias pro Integer |
– |
Float |
číslo | – |
Min |
minimální hodnota číselného prvku | int|float |
Max |
maximální hodnota číselného prvku | int|float |
Range |
hodnota v rozsahu | dvojice [int|float, int|float] |
Validační pravidla Integer
, Numeric
a Float
rovnou převádí hodnotu na integer resp.
float. A dále pravidlo URL
akceptuje i adresu bez schématu (např. nette.org
) a schéma doplní
(https://nette.org
). Výraz v Pattern
a PatternIcase
musí platit pro celou hodnotu, tj.
jako by byl obalen znaky ^
a $
.
Počet položek
U prvků addMultiUpload()
, addCheckboxList()
, addMultiSelect()
lze použít
i následující pravidla pro omezení počtu vybraných položek resp. uploadovaných souborů:
MinLength |
minimální počet | int |
MaxLength |
maximální počet | int |
Length |
počet v rozsahu nebo přesný počet | dvojice [int, int] nebo int |
Upload souborů
U prvků addUpload()
, addMultiUpload()
lze použít i následující pravidla:
MaxFileSize |
maximální velikost souboru v bajtech | int |
MimeType |
MIME type, povoleny zástupné znaky ('video/*' ) |
string|string[] |
Image |
obrázek JPEG, PNG, GIF, WebP, AVIF | – |
Pattern |
jméno souboru vyhovuje regulárnímu výrazu | string |
PatternInsensitive |
jako Pattern , ale nezávislé na velikosti písmen |
string |
MimeType
a Image
vyžadují PHP rozšíření fileinfo
. Že je soubor či obrázek
požadovaného typu detekují na základě jeho signatury a neověřují integritu celého souboru. Zda není obrázek
poškozený lze zjistit například pokusem o jeho načtení.
Chybové hlášky
Všechny předdefinované pravidla s výjimkou Pattern
a PatternInsensitive
mají výchozí chybovou
hlášku, takže ji lze vynechat. Nicméně uvedením a formulací všech hlášek na míru uděláte formulář uživatelsky
přívětivější.
Změnit výchozí hlášky můžete v konfiguraci, úpravou textů
v poli Nette\Forms\Validator::$messages
nebo použitím translatoru.
V textu chybových hlášek lze používat tyto zástupné řetězce:
%d |
nahradí postupně za argumenty pravidla |
%n$d |
nahradí za n-tý argument pravidla |
%label |
nahradí za popisku prvku (bez dvojtečky) |
%name |
nahradí za jméno prvku (např. name ) |
%value |
nahradí za uživatelem vloženou hodnotu |
Podmínky
Kromě pravidel lze přidávat také podmínky. Ty se zapisují podobně jako pravidla, jen místo addRule()
použijeme metodu addCondition()
a pochopitelně neuvádíme žádnou chybovou zprávu (podmínka se jen ptá):
Podmínku je možné vázat i na jiný prvek než aktuální pomocí addConditionOn()
. Jako první parametr
uvedeme referenci na prvek. V této ukázce bude e-mail povinný jen tehdy, zaškrtne-li se checkbox (jeho hodnota
bude true):
Z podmínek lze vytvářet komplexní struktury za pomoci elseCondition()
a endCondition()
:
V Nette lze velmi snadno reagovat na splnění či nesplnění podmínky i na straně JavaScriptu pomocí metody
toggle()
, viz dynamický JavaScript.
Reference na jiný prvek
Jako argument pravidla či podmínky lze předat i jiný prvek formuláře. Pravidlo potom použije hodnotu vloženou později
uživatelem v prohlížeči. Takto lze např. dynamicky validovat, že prvek password
obsahuje stejný řetězec
jako prvek password_confirm
:
Vlastní pravidla a podmínky
Občas se dostaneme do situace, kdy nám vestavěná validační pravidla v Nette nestačí a potřebujeme data od uživatele validovat po svém. V Nette je to velmi jednoduché!
Metodám addRule()
či addCondition()
lze jako první parametr předat libovolný callback. Ten
přijímá jako první parametr samotný prvek a vrací boolean hodnotu určující, zda validace proběhla v pořádku. Při
přidávání pravidla pomocí addRule()
je možné zadat i další argumenty, ty jsou pak předány jako druhý
parametr.
Vlastní sadu validátorů tak můžeme vytvořit jako třídu se statickými metodami:
Použití je pak velmi jednoduché:
Vlastní validační pravidla lze přidávat i do JavaScriptu. Podmínkou je, aby pravidlo byla statická metoda. Její název
pro JavaScriptový validátor vznikne spojením názvu třídy bez zpětných lomítek \
, podtržítka _
a názvu metody. Např. App\MyValidators::validateDivisibility
zapíšeme jako
AppMyValidators_validateDivisibility
a přidáme do objektu Nette.validators
:
Událost onValidate
Po odeslání formuláře se provádí validace, kdy se zkontrolují jednotlivá pravidla přidaná pomocí
addRule()
a následně se vyvolá událost
onValidate
. Její handler lze využít k doplňkové validaci, typicky ověření správné kombinace hodnot ve
více prvcích formuláře.
Pokud se odhalí chyba, předáme ji do formuláře metodou addError()
. Tu lze volat buď na konkrétním prvku,
nebo přímo na formuláři.
Chyby při zpracování
V mnoha případech se o chybě dozvíme až ve chvíli, kdy zpracováváme platný formulář, například zapisujeme novou
položku do databáze a narazíme na duplicitu klíčů. V takovém případě chybu opět předáme do formuláře metodou
addError()
. Tu lze volat buď na konkrétním prvku, nebo přímo na formuláři:
Pokud je to možné, doporučujeme připojit chybu přímo k prvku formuláře, protože se zobrazí vedle něj při použití výchozího rendereru.
Můžete addError()
volat opakovaně a tak předat formuláři nebo prvku více chybových zpráv. Získáte je
pomocí getErrors()
.
Pozor, $form->getErrors()
vrací sumář všech chybových zpráv, i těch, co byly předány přímo
jednotlivým prvkům, nejen přímo formuláři. Chybové zprávy předané pouze formuláři získáte přes
$form->getOwnErrors()
.
Úprava vstupu
Pomocí metody addFilter()
můžeme pozměnit uživatelem vloženou hodnotu. V této ukázce budeme tolerovat a
odstraňovat mezery v PSČ:
Filtr se začlení mezi validační pravidla a podmínky a tedy záleží na pořadí metod, tj. filtr a pravidlo se volají
v takovém pořadí, jako je pořadí metod addFilter()
a addRule()
.
JavaScriptová validace
Jazyk pro formulování podmínek a pravidel je velice silný. Všechny konstrukce přitom fungují jak na straně serveru, tak
i na straně JavaScriptu. Přenáší se v HTML atributech data-nette-rules
jako JSON. Samotnou validaci pak
provádí skript, který odchytí událost formuláře submit
, projde jednotlivé prvky a vykoná příslušnou
validaci.
Tím skriptem je netteForms.js
a je dostupný z více možných zdrojů:
Skript můžete vložit přímo do HTML stránky ze CDN:
Nebo zkopírovat lokálně do veřejné složky projektu (např. z
vendor/nette/forms/src/assets/netteForms.min.js
):
Nebo nainstalovat přes npm:
A následně načíst a spustit:
Alternativně jej můžete načíst přímo ze složky vendor
:
Dynamický JavaScript
Chcete zobrazit políčka pro zadání adresy pouze pokud uživatel zvolí zboží zaslat poštou? Žádný problém. Klíčem
je dvojice metod addCondition()
& toggle()
:
Tento kód říká, že když je podmínka splněná, tedy když je zaškrtnutý checkbox, bude viditelný HTML element
#address-container
. A obráceně. Prvky formuláře s adresou příjemce tak umístíme do kontejneru s tímto ID
a při kliknutí na checkbox se skryjí nebo zobrazí. To zajišťuje skript netteForms.js
.
Jako argument metody toggle()
je možné předat libovolný selektor. Z historických důvodů se alfanumerický
řetězec bez dalších speciálních znaků chápe jako ID prvku, tedy stejně, jako by mu předcházel znak #
.
Druhý nepovinný parametr umožňuje obrátit chování, tj. pokud bychom použili
toggle('#address-container', false)
, element by se naopak zobrazil pouze tehdy, pokud by checkbox
zaškrtnutý nebyl.
Výchozí implementace v JavaScriptu mění elementům property hidden
. Chování však můžeme snadno změnit,
například přidat animaci. Stačí v JavaScriptu přepsat metodu Nette.toggle
vlastním řešením:
Vypnutí validace
Někdy se může hodit validaci vypnout. Pokud stisknutí odesílacího tlačítka nemá provádět validaci (vhodné pro
tlačítka Cancel nebo Preview), vypneme ji metodou $submit->setValidationScope([])
. Pokud má
provádět validaci jen částečnou, můžeme určit které pole nebo formulářové kontejnery se mají validovat.
setValidationScope
neovlivní událost onValidate u formuláře, která
bude zavolána vždy. Událost onValidate
u kontejneru bude vyvolána pouze pokud je tento kontejner označen pro
částečnou validaci.