Nyomtatványok érvényesítés
Kötelező vezérlők
A vezérlőelemeket a setRequired()
metódussal jelöljük meg kötelezőnek, amelynek argumentuma a hibaüzenet szövege, amely akkor jelenik meg, ha a felhasználó nem tölti ki. Ha nem adunk meg
argumentumot, akkor az alapértelmezett hibaüzenetet használjuk.
$form->addText('name', 'Name:')
->setRequired('Please fill your name.');
Szabályok
A addRule()
módszerrel adunk hozzá érvényesítési szabályokat a vezérlőkhöz. Az első paraméter a
szabály, a második a hibaüzenet, a harmadik pedig az érvényesítési szabály
argumentuma.
$form->addPassword('password', 'Password:')
->addRule($form::MinLength, 'Password must be at least %d characters', 8);
A hitelesítési szabályok csak akkor kerülnek ellenőrzésre, ha a felhasználó kitöltötte az elemet.
A Nette számos előre definiált szabályt tartalmaz, amelyek neve a Nette\Forms\Form
osztály konstanciái.
Ezeket a szabályokat minden elemre alkalmazhatjuk:
konstans | leírás | érvek |
---|---|---|
Required |
setRequired() álneve |
– – |
Filled |
a setRequired() álneve |
– |
Blank |
nem szabad kitölteni | – |
Equal |
érték egyenlő a paraméterrel | mixed |
NotEqual |
érték nem egyenlő a paraméterrel | mixed |
IsIn |
érték egyenlő a tömb valamelyik elemével | array |
IsNotIn |
érték nem egyenlő a tömb egyetlen elemével sem | array |
Valid |
a bemenet átmegy az érvényesítésen ( feltételek esetén) | – |
Szöveges bemenetek
A addText()
, addPassword()
, addTextArea()
, addEmail()
,
addInteger()
, addFloat()
elemekre a következő szabályok közül néhányat is lehet alkalmazni:
MinLength |
minimális karakterlánc-hossz | int |
MaxLength |
maximális karakterlánc-hossz | int |
Length |
hossz a tartományban vagy pontos hossz | pár [int, int] vagy int |
Email |
érvényes e-mail cím | – |
URL |
érvényes URL | – |
Pattern |
megfelel a szabályos mintának | string |
PatternInsensitive |
mint a Pattern , de a nagy- és kisbetűket figyelmen kívül hagyja |
string |
Integer |
egész szám | – |
Numeric |
Integer álneve |
– |
Float |
egész vagy lebegőpontos szám | – |
Min |
az egész szám értékének minimuma | int|float |
Max |
az egész szám értékének maximuma | int|float |
Range |
érték a tartományban | pár [int|float, int|float] |
A Integer
, Numeric
és Float
szabályok automatikusan egész számra (illetve
lebegőszámra) konvertálják az értéket. Továbbá a URL
szabály elfogad egy séma nélküli címet is (pl.
nette.org
), és kiegészíti a sémát (https://nette.org
). A Pattern
és a
PatternInsensitive
kifejezéseknek a teljes értékre érvényesnek kell lenniük, azaz mintha a ^
and
$
karakterekbe lenne csomagolva.
Tételek száma
A addMultiUpload()
, addCheckboxList()
, addMultiSelect()
elemek esetében a következő
szabályokkal is korlátozhatja a kiválasztott elemek vagy feltöltött fájlok számát:
MinLength |
minimális szám | int |
MaxLength |
maximális szám | int |
Length |
szám tartományon belül vagy pontos szám | párok [int, int] vagy int |
Fájl feltöltés
A addUpload()
, addMultiUpload()
vezérlőkre a következő szabályok is alkalmazhatók:
MaxFileSize |
maximális fájlméret bájtban | int |
MimeType |
MIME-típus, elfogadja a helyettesítő karaktereket ('video/*' ) |
string|string[] |
Image |
a feltöltött fájl JPEG, PNG, GIF, WebP | – |
Pattern |
a fájl neve megfelel a reguláris kifejezésnek | string |
PatternInsensitive |
mint a Pattern , de a nagy- és kisbetűket nem érzékeli |
string |
A MimeType
és a Image
a fileinfo
PHP kiterjesztést igényli. Az, hogy egy fájl vagy
kép a kívánt típusba tartozik-e, az aláírás alapján állapítható meg. A teljes fájl sértetlenségét nem ellenőrzi a
rendszer. Azt, hogy egy kép nem sérült-e, például úgy lehet megállapítani, ha megpróbáljuk betölteni.
Hibaüzenetek
A Pattern
és a PatternInsensitive
kivételével minden előre definiált szabály rendelkezik
alapértelmezett hibaüzenettel, így ezek elhagyhatók. Az összes testreszabott üzenet átadásával és megfogalmazásával
azonban felhasználóbarátabbá teszi az űrlapot.
Az alapértelmezett üzeneteket a forms:configuration-ban, a
Nette\Forms\Validator::$messages
tömbben lévő szövegek módosításával vagy a translator használatával módosíthatja.
A hibaüzenetek szövegében a következő helyettesítő karakterek használhatók:
%d |
fokozatosan helyettesíti a szabályokat az argumentumok után. |
%n$d |
az n-edik szabály argumentumával helyettesíti. |
%label |
a mező címkéjével helyettesíti (kettőspont nélkül) |
%name |
a mező nevével helyettesíti (pl. name ). |
%value |
a felhasználó által megadott értékkel helyettesíti. |
$form->addText('name', 'Name:')
->setRequired('Please fill in %label');
$form->addInteger('id', 'ID:')
->addRule($form::Range, 'at least %d and no more than %d', [5, 10]);
$form->addInteger('id', 'ID:')
->addRule($form::Range, 'no more than %2$d and at least %1$d', [5, 10]);
Feltételek
Az érvényesítési szabályok mellett feltételek is beállíthatók. Ezek beállítása hasonlóan történik, mint a
szabályoké, azonban a addCondition()
helyett a addRule()
címet használjuk, és természetesen
hibaüzenet nélkül hagyjuk (a feltétel csak kérdez):
$form->addPassword('password', 'Jelszó:')
// ha a jelszó nem hosszabb 8 karakternél ...
->addCondition($form::MaxLength, 8)
// ... akkor egy számot kell tartalmaznia.
->addRule($form::Pattern, 'Számot kell tartalmaznia', '.*[0-9].*');
A feltétel a addConditionOn()
segítségével az aktuális elemtől eltérő elemhez is kapcsolható. Az első
paraméter a mezőre való hivatkozás. A következő esetben az e-mail csak akkor lesz kötelező, ha a jelölőnégyzet be van
jelölve (azaz az értéke true
):
$form->addCheckbox('newsletters', 'send me newsletters');
$form->addEmail('email', 'Email:')
// ha a jelölőnégyzet be van jelölve ...
->addConditionOn($form['newsletters'], $form::Equal, true)
// ... megköveteli az email
->setRequired('Adja meg az e-mail címét');
A feltételek a elseCondition()
és a endCondition()
metódusokkal összetett struktúrákba
csoportosíthatók.
$form->addText(/* ... */)
->addCondition(/* ... */) // ha az első feltétel teljesül.
->addConditionOn(/* ... */) // és a második feltétel egy másik elemre is.
->addRule(/* ... */) // megköveteli ezt a szabályt
->elseCondition() // ha a második feltétel nem teljesül
->addRule(/* ... */) // szükség van ezekre a szabályokra.
->addRule(/* ... */)
->endCondition() // visszatérünk az első feltételhez
->addRule(/* ... */);
A Nette-ben nagyon egyszerűen reagálhatunk egy feltétel teljesülésére vagy nem teljesülésére a JavaScript oldalán a
toggle()
metódus segítségével, lásd Dynamic JavaScript.
Hivatkozás egy másik elemre
Egy szabály vagy feltétel argumentumaként egy másik űrlapelemet is átadhat. A szabály ekkor a felhasználó által a
böngészőben később megadott értéket fogja használni. Ez például arra használható, hogy dinamikusan ellenőrizze, hogy
a password
elem ugyanazt a karakterláncot tartalmazza-e, mint a password_confirm
elem:
$form->addPassword('password', 'Password');
$form->addPassword('password_confirm', 'Confirm Password')
->addRule($form::Equal, 'The passwords do not match', $form['password']);
Egyéni szabályok és feltételek
Néha olyan helyzetbe kerülünk, amikor a Nette beépített érvényesítési szabályai nem elegendőek, és a felhasználó adatait saját módon kell érvényesítenünk. A Nette-ben ez nagyon egyszerű!
A addRule()
vagy a addCondition()
metódusok első paramétereként bármilyen visszahívást
átadhatunk. A callback első paraméterként magát az elemet fogadja el, és egy bóluszi értéket ad vissza, amely jelzi,
hogy az érvényesítés sikeres volt-e. Szabály hozzáadásakor a addRule()
segítségével további argumentumok
adhatók át, amelyek második paraméterként kerülnek átadásra.
Az egyéni érvényesítőkészlet tehát statikus metódusokkal rendelkező osztályként hozható létre:
class MyValidators
{
// teszteli, hogy az érték osztható-e az argumentummal.
public static function validateDivisibility(BaseControl $input, $arg): bool
{
return $input->getValue() % $arg === 0;
}
public static function validateEmailDomain(BaseControl $input, $domain)
{
// további validátorok
}
}
A használat nagyon egyszerű:
$form->addInteger('num')
->addRule(
[MyValidators::class, 'validateDivisibility'],
'The value must be a multiple of %d',
8,
);
Egyéni érvényesítési szabályokat is hozzá lehet adni a JavaScripthez. Az egyetlen követelmény, hogy a szabály
statikus metódus legyen. Nevét a JavaScript-érvényesítő számára az osztály neve (backslashes nélkül) \
,
the underscore _
, és a metódus neve egymás mellé fűzésével hozzuk létre. Például írjuk a
App\MyValidators::validateDivisibility
-t AppMyValidators_validateDivisibility
néven, és adjuk hozzá
a Nette.validators
objektumhoz:
Nette.validators['AppMyValidators_validateDivisibility'] = (elem, args, val) => {
return val % args === 0;
};
Esemény onValidate
Az űrlap elküldése után az érvényesítés a addRule()
által hozzáadott egyedi szabályok
ellenőrzésével, majd a onValidate
esemény
meghívásával történik. Kezelője további érvényesítésre használható, jellemzően több űrlapelem értékének helyes
kombinációjának ellenőrzésére.
Ha hibát észlel, azt a addError()
metódus segítségével továbbítja az űrlapnak. Ezt vagy egy adott elemen,
vagy közvetlenül az űrlapon lehet meghívni.
protected function createComponentSignInForm(): Form
{
$form = new Form;
// ...
$form->onValidate[] = [$this, 'validateSignInForm'];
return $form;
}
public function validateSignInForm(Form $form, \stdClass $data): void
{
if ($data->foo > 1 && $data->bar > 5) {
$form->addError('Ez a kombináció nem lehetséges.');
}
}
Hibák feldolgozása
Sok esetben egy érvényes űrlap feldolgozása közben fedezünk fel hibát, például amikor új bejegyzést írunk az
adatbázisba, és egy duplikált kulcsot találunk. Ebben az esetben a addError()
metódus segítségével adjuk
vissza a hibát az űrlapnak. Ezt vagy egy adott elemen, vagy közvetlenül az űrlapon hívhatjuk meg:
try {
$data = $form->getValues();
$this->user->login($data->username, $data->password);
$this->redirect('Home:');
} catch (Nette\Security\AuthenticationException $e) {
if ($e->getCode() === Nette\Security\Authenticator::InvalidCredential) {
$form->addError('Invalid password.');
}
}
Ha lehetséges, javasoljuk, hogy a hibát közvetlenül az űrlap elemhez adjuk hozzá, mivel az alapértelmezett renderelő használata esetén a hiba mellette fog megjelenni.
$form['date']->addError('Sorry, this date is already taken.');
A addError()
többször is meghívható, hogy több hibaüzenetet adjon át egy űrlapnak vagy elemnek. Ezeket a
getErrors()
segítségével kapja meg.
Vegye figyelembe, hogy a $form->getErrors()
az összes hibaüzenet összefoglalóját adja vissza, még a
közvetlenül az egyes elemeknek átadottakat is, nem csak közvetlenül az űrlapnak. A csak az űrlapnak átadott
hibaüzeneteket a $form->getOwnErrors()
segítségével kapjuk meg.
A beviteli értékek módosítása
A addFilter()
módszerrel módosíthatjuk a felhasználó által megadott értéket. Ebben a példában
megtűrjük és eltávolítjuk a szóközöket az irányítószámban:
$form->addText('zip', 'Irányítószám:')
->addFilter(function ($value) {
return str_replace(' ', '', $value); // eltávolítjuk a szóközöket az irányítószámból.
})
->addRule($form::Pattern, 'Az irányítószám nem ötjegyű', '\d{5}');
A szűrő az érvényesítési szabályok és feltételek között szerepel, ezért függ a módszerek sorrendjétől, azaz a
szűrő és a szabály meghívása ugyanabban a sorrendben történik, mint a addFilter()
és a
addRule()
módszerek sorrendje.
JavaScript érvényesítés
Az érvényesítési szabályok és feltételek nyelve nagy teljesítményű. Annak ellenére, hogy minden konstrukció
szerver- és kliensoldalon egyaránt működik, JavaScriptben. A szabályok átadása HTML-attribútumokban történik
data-nette-rules
JSON-ként. Magát az érvényesítést egy másik szkript kezeli, amely az űrlap összes
submit
eseményét megakasztja, iterálja az összes bemenetet és lefuttatja a megfelelő érvényesítéseket.
Ez a szkript a netteForms.js
, amely több lehetséges forrásból is elérhető:
A szkriptet közvetlenül a CDN-ből származó HTML-oldalba ágyazhatja be:
<script src="https://unpkg.com/nette-forms@3"></script>
Vagy másolja be helyileg a projekt nyilvános mappájába (pl. a
vendor/nette/forms/src/assets/netteForms.min.js
):
<script src="/path/to/netteForms.min.js"></script>
Vagy telepítse az npm segítségével:
npm install nette-forms
Aztán töltsd be és futtasd:
import netteForms from 'nette-forms';
netteForms.initOnLoad();
Alternatívaként közvetlenül a vendor
mappából is betöltheti:
import netteForms from '../path/to/vendor/nette/forms/src/assets/netteForms.js';
netteForms.initOnLoad();
Dinamikus JavaScript
Csak akkor szeretné megjeleníteni a cím mezőt, ha a felhasználó úgy dönt, hogy postai úton küldi el az árut? Nem
probléma. A kulcs a addCondition()
& toggle()
metóduspár:
$form->addCheckbox('send_it')
->addCondition($form::Equal, true)
->toggle('#address-container');
Ez a kód azt mondja, hogy ha a feltétel teljesül, vagyis ha a jelölőnégyzet be van jelölve, akkor a
#address-container
HTML-elem láthatóvá válik. És fordítva. Tehát a címzett címét tartalmazó űrlapelemeket
egy ilyen azonosítóval rendelkező konténerbe helyezzük, és amikor a jelölőnégyzetre kattintunk, elrejtjük vagy
megjelenítjük őket. Ezt a netteForms.js
szkript kezeli.
A toggle()
metódusnak argumentumként bármilyen szelektor átadható. Történelmi okokból a más speciális
karaktereket nem tartalmazó alfanumerikus karakterláncot elemazonosítóként kezeljük, ugyanúgy, mintha a #
character. The second optional parameter allows us to reverse the behavior, i.e. if we used
toggle('#address-container', false)
lenne előtte, az elem csak akkor jelenne meg, ha a jelölőnégyzet nincs
bejelölve.
Az alapértelmezett JavaScript implementáció megváltoztatja az elemek hidden
tulajdonságát. A viselkedést
azonban könnyen megváltoztathatjuk, például egy animáció hozzáadásával. Csak írjuk felül a Nette.toggle
metódust JavaScriptben egy egyéni megoldással:
Nette.toggle = (selector, visible, srcElement, event) => {
document.querySelectorAll(selector).forEach((el) => {
// hide or show 'el' according to the value of 'visible'
});
};
Az érvényesítés letiltása
Bizonyos esetekben le kell tiltani az érvényesítést. Ha egy beküldőgombnak nem kellene érvényesítést futtatnia a
beküldés után (például Mondás vagy Közlemény gomb), akkor az érvényesítést a
$submit->setValidationScope([])
meghívásával tilthatja le. Az űrlapot részlegesen is érvényesítheti az
érvényesítendő elemek megadásával.
$form->addText('name')
->setRequired();
$details = $form->addContainer('details');
$details->addInteger('age')
->setRequired('age');
$details->addInteger('age2')
->setRequired('age2');
$form->addSubmit('send1'); // Az egész űrlap hitelesítése
$form->addSubmit('send2')
->setValidationScope([]); // Nem érvényesít semmit.
$form->addSubmit('send3')
->setValidationScope([$form['name']]); // Csak a 'name' mezőt érvényesíti.
$form->addSubmit('send4')
->setValidationScope([$form['details']['age']]); // Csak az 'age' mezőt érvényesíti.
$form->addSubmit('send5')
->setValidationScope([$form['details']]); // Validálja a 'details' konténert.
Az onValidate esemény az űrlapon mindig meghívásra kerül, és nem befolyásolja a
setValidationScope
. onValidate
esemény a konténeren csak akkor hívódik meg, ha ez a konténer
részleges érvényesítésre van megadva.