Potrjevanje obrazcev
Zahtevani kontrolni elementi
Kontrole so označene kot zahtevane z metodo setRequired()
, katere argument je besedilo sporočila o napaki, ki se prikaže, če ga uporabnik ne izpolni. Če argument ni podan, se
uporabi privzeto sporočilo o napaki.
$form->addText('name', 'Name:')
->setRequired('Please fill your name.');
Pravila
Pravila potrjevanja dodajamo kontrolnim elementom z metodo addRule()
. Prvi parameter je pravilo, drugi je sporočilo o napaki, tretji pa argument pravila potrjevanja.
$form->addPassword('password', 'Password:')
->addRule($form::MinLength, 'Password must be at least %d characters', 8);
Pravila potrjevanja se preverijo le, če je uporabnik izpolnil element.
Nette ima na voljo številna vnaprej določena pravila, katerih imena so konstante razreda Nette\Forms\Form
. Ta
pravila lahko uporabimo za vse elemente:
konstanta | opis | argumenti |
---|---|---|
Required |
vzdevek setRequired() |
– |
Filled |
vzdevek setRequired() |
– |
Blank |
ne sme biti izpolnjen | – |
Equal |
vrednost je enaka parametru | mixed |
NotEqual |
vrednost ni enaka parametru | mixed |
IsIn |
vrednost je enaka nekemu elementu v polju | array |
IsNotIn |
vrednost ni enaka nobenemu elementu v polju | array |
Valid |
vhodni podatki so uspešno preverjeni (za pogoje) | – |
Besedilni vnosi
Za elemente addText()
, addPassword()
, addTextArea()
, addEmail()
,
addInteger()
, addFloat()
se lahko uporabijo tudi nekatera od naslednjih pravil:
MinLength |
minimalna dolžina niza | int |
MaxLength |
največja dolžina niza | int |
Length |
dolžina v območju ali natančna dolžina | par [int, int] ali int |
Email |
veljavni e-poštni naslov | – |
URL |
veljavni URL | – |
Pattern |
ustreza regularnemu vzorcu | string |
PatternInsensitive |
kot Pattern , vendar ne upošteva velikih in malih črk |
string |
Integer |
celo število | – |
Numeric |
vzdevek Integer |
– |
Float |
celo število ali število s plavajočo vejico | – |
Min |
najmanjša vrednost celega števila | int|float |
Max |
največja vrednost celega števila | int|float |
Range |
vrednost v območju | par [int|float, int|float] |
Pravila Integer
, Numeric
in Float
samodejno pretvorijo vrednost v celo število
(oziroma plavajoče število). Poleg tega pravilo URL
sprejme tudi naslov brez sheme (npr. nette.org
) in
dopolni shemo (https://nette.org
). Izraza v Pattern
in PatternInsensitive
morata biti
veljavna za celotno vrednost, tj. kot da bi bila zavita v znake ^
and $
.
Število elementov
Za elemente addMultiUpload()
, addCheckboxList()
, addMultiSelect()
lahko za omejitev
števila izbranih elementov ali naloženih datotek uporabite tudi naslednja pravila:
MinLength |
najmanjše število | int |
MaxLength |
največje število | int |
Length |
število v razponu ali natančno število | pari [int, int] ali int |
Prenos datotek
Za kontrole addUpload()
, addMultiUpload()
se lahko uporabljajo tudi naslednja pravila:
MaxFileSize |
največja velikost datoteke v bajtih | int |
MimeType |
vrsta MIME, sprejema nadomestne znake ('video/*' ) |
string|string[] |
Image |
naložena datoteka je JPEG, PNG, GIF, WebP | – |
Pattern |
ime datoteke ustreza regularnemu izrazu | string |
PatternInsensitive |
kot Pattern , vendar se pri tem ne upošteva velikih in malih črk |
string |
Za MimeType
in Image
je potrebna razširitev PHP fileinfo
. Ali je datoteka ali slika
zahtevane vrste, se ugotovi na podlagi njenega podpisa. Celovitost celotne datoteke se ne preverja. Ali slika ni poškodovana,
lahko ugotovite na primer tako, da jo poskusite naložiti.
Sporočila o napakah
Vsa vnaprej določena pravila, razen Pattern
in PatternInsensitive
, imajo privzeto sporočilo
o napaki, zato jih lahko izpustite. Vendar pa boste s posredovanjem in oblikovanjem vseh prilagojenih sporočil naredili obrazec
prijaznejši do uporabnika.
Privzeta sporočila lahko spremenite v obrazcu configuration, tako da
spremenite besedila v polju Nette\Forms\Validator::$messages
ali uporabite prevajalnik.
V besedilu sporočil o napakah lahko uporabite naslednje nadomestne znake:
%d |
postopoma nadomesti pravila za argumenti |
%n$d |
nadomesti z n-tim argumentom pravila |
%label |
nadomesti z oznako polja (brez dvopičja) |
%name |
nadomesti z imenom polja (npr. name ) |
%value |
nadomesti z vrednostjo, ki jo vnese uporabnik |
$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]);
Pogoji
Poleg pravil potrjevanja lahko določite tudi pogoje. Nastavljamo jih podobno kot pravila, le da namesto
addCondition()
uporabimo addRule()
in seveda pustimo brez sporočila o napaki (pogoj samo vpraša):
$form->addPassword('password', 'Password:')
// če geslo ni daljše od 8 znakov ...
->addCondition($form::MaxLength, 8)
// ... potem mora vsebovati številko
->addRule($form::Pattern, 'Must contain number', '.*[0-9].*');
Pogoj lahko povežemo z drugim elementom od trenutnega z uporabo addConditionOn()
. Prvi parameter je referenca
na polje. V naslednjem primeru bo elektronsko sporočilo zahtevano le, če je potrditveno polje označeno (tj. njegova vrednost
je true
):
$form->addCheckbox('newsletters', 'send me newsletters');
$form->addEmail('email', 'Email:')
// če je potrditveno polje označeno ...
->addConditionOn($form['newsletters'], $form::Equal, true)
// ... zahteva e-pošto
->setRequired('Fill your email address');
Pogoje lahko združite v kompleksne strukture z metodama elseCondition()
in endCondition()
.
$form->addText(/* ... */)
->addCondition(/* ... */) // če je izpolnjen prvi pogoj.
->addConditionOn(/* ... */) // in drugi pogoj tudi za drug element
->addRule(/* ... */) // zahteva to pravilo
->elseCondition() // če drugi pogoj ni izpolnjen
->addRule(/* ... */) // zahteva ta pravila
->addRule(/* ... */)
->endCondition() // se vrnemo k prvemu pogoju
->addRule(/* ... */);
V Nette je zelo enostavno reagirati na izpolnitev ali neizpolnitev pogoja na strani JavaScript z uporabo metode
toggle()
, glejte Dinamični JavaScript.
Sklicevanje na drug element
Kot argument za pravilo ali pogoj lahko posredujete tudi drug element obrazca. Pravilo bo nato uporabilo vrednost, ki jo bo
uporabnik kasneje vnesel v brskalnik. To lahko na primer uporabite za dinamično preverjanje, ali element password
vsebuje isti niz kot element password_confirm
:
$form->addPassword('password', 'Password');
$form->addPassword('password_confirm', 'Confirm Password')
->addRule($form::Equal, 'The passwords do not match', $form['password']);
Pravila in pogoji po meri
Včasih se znajdemo v situaciji, ko vgrajena pravila potrjevanja v Nette niso dovolj in moramo podatke od uporabnika potrditi na svoj način. V Nette je to zelo enostavno!
Metodam addRule()
ali addCondition()
lahko kot prvi parameter posredujete katerikoli povratni klic.
Povratni klic sprejme sam element kot prvi parameter in vrne logično vrednost, ki označuje, ali je bilo preverjanje uspešno.
Pri dodajanju pravila z uporabo metode addRule()
lahko posredujete dodatne argumente, ki se nato posredujejo kot
drugi parameter.
Lastni nabor validatorjev je tako mogoče ustvariti kot razred s statičnimi metodami:
class MyValidators
{
// preveri, ali je vrednost deljiva z argumentom
public static function validateDivisibility(BaseControl $input, $arg): bool
{
return $input->getValue() % $arg === 0;
}
public static function validateEmailDomain(BaseControl $input, $domain)
{
// dodatni validatorji
}
}
Uporaba je nato zelo preprosta:
$form->addInteger('num')
->addRule(
[MyValidators::class, 'validateDivisibility'],
'The value must be a multiple of %d',
8,
);
Pravila potrjevanja po meri lahko dodate tudi v JavaScript. Edina zahteva je, da mora biti pravilo statična metoda. Njegovo
ime za validator JavaScript se ustvari z združitvijo imena razreda brez povratnih lomk \
, the underscore
_
, in imena metode. Na primer, App\MyValidators::validateDivisibility
zapišite kot
AppMyValidators_validateDivisibility
in ga dodajte predmetu Nette.validators
:
Nette.validators['AppMyValidators_validateDivisibility'] = (elem, args, val) => {
return val % args === 0;
};
Dogodek onValidate
Ko je obrazec poslan, se preverjanje veljavnosti izvede tako, da se preverijo posamezna pravila, dodana s strani
addRule()
, nato pa se pokliče dogodek
onValidate
. Njegovega izvajalca je mogoče uporabiti za dodatno potrjevanje, običajno za preverjanje pravilne
kombinacije vrednosti v več elementih obrazca.
Če je odkrita napaka, se posreduje obrazcu z metodo addError()
. Ta se lahko kliče na določen element ali
neposredno na obrazec.
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('This combination is not possible.');
}
}
Napake pri obdelavi
V številnih primerih odkrijemo napako med obdelavo veljavnega obrazca, npr. ko zapišemo nov vnos v zbirko podatkov in
naletimo na podvojen ključ. V tem primeru napako posredujemo nazaj v obrazec s pomočjo metode addError()
. To
lahko kličemo na določen element ali neposredno na obrazec:
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.');
}
}
Če je mogoče, priporočamo, da napako dodate neposredno na element obrazca, saj se bo ob uporabi privzetega prikazovalnika prikazala poleg njega.
$form['date']->addError('Sorry, this date is already taken.');
Za posredovanje več sporočil o napakah obrazcu ali elementu lahko večkrat pokličete addError()
. Pridobite jih
s getErrors()
.
Upoštevajte, da $form->getErrors()
vrne povzetek vseh sporočil o napakah, tudi tistih, ki so posredovana
neposredno posameznim elementom, ne le neposredno obrazcu. Sporočila o napakah, ki so posredovana samo obrazcu, se pridobijo
prek $form->getOwnErrors()
.
Spreminjanje vhodnih vrednosti
Z metodo addFilter()
lahko spremenimo vrednost, ki jo je vnesel uporabnik. V tem primeru bomo dopustili in
odstranili presledke v poštni številki:
$form->addText('zip', 'Postcode:')
->addFilter(function ($value) {
return str_replace(' ', '', $value); // odstranite presledke iz poštne številke.
})
->addRule($form::Pattern, 'The postal code is not five digits', '\d{5}');
Filter je vključen med pravila in pogoje potrjevanja in je zato odvisen od vrstnega reda metod, tj. filter in pravilo se
kličeta v enakem vrstnem redu, kot je vrstni red metod addFilter()
in addRule()
.
Potrjevanje v javascriptu
Jezik pravil in pogojev potrjevanja je zelo zmogljiv. Čeprav vse konstrukcije delujejo tako na strani strežnika kot na strani
odjemalca, v jeziku JavaScript. Pravila se prenašajo v atributih HTML data-nette-rules
kot JSON. Za samo
potrjevanje skrbi druga skripta, ki zasvoji vse dogodke obrazca submit
, iterira čez vse vhode in izvede ustrezne
validacije.
Ta skripta je netteForms.js
, ki je na voljo iz več možnih virov:
Skripto lahko vstavite neposredno v stran HTML iz CDN:
<script src="https://unpkg.com/nette-forms@3"></script>
Lahko pa jo kopirate lokalno v javno mapo projekta (npr. s spletne strani
vendor/nette/forms/src/assets/netteForms.min.js
):
<script src="/path/to/netteForms.min.js"></script>
ali namestite prek npm:
npm install nette-forms
Nato naložite in zaženite:
import netteForms from 'nette-forms';
netteForms.initOnLoad();
Lahko ga naložite tudi neposredno iz mape vendor
:
import netteForms from '../path/to/vendor/nette/forms/src/assets/netteForms.js';
netteForms.initOnLoad();
Dinamični JavaScript
Ali želite prikazati polja z naslovi le, če se uporabnik odloči za pošiljanje blaga po pošti? Ni problema. Ključ je par
metod addCondition()
in toggle()
:
$form->addCheckbox('send_it')
->addCondition($form::Equal, true)
->toggle('#address-container');
Ta koda pravi, da bo ob izpolnitvi pogoja, tj. ko je potrditveno polje označeno, viden element HTML
#address-container
. In obratno. Elemente obrazca z naslovom prejemnika torej postavimo v vsebnik s tem ID, in ko
je potrditveno polje kliknjeno, se skrijejo ali prikažejo. Za to poskrbi skripta netteForms.js
.
Metodi toggle()
lahko kot argument posredujemo katerikoli selektor. Iz zgodovinskih razlogov se alfanumerični niz
brez drugih posebnih znakov obravnava kot ID elementa, enako, kot če bi pred njim bil #
character. The second
optional parameter allows us to reverse the behavior, i.e. if we used toggle('#address-container', false)
, element bi
se prikazal le, če bi bilo potrditveno polje odkljukano.
Privzeta implementacija JavaScript spreminja lastnost hidden
za elemente. Vendar lahko obnašanje preprosto
spremenimo, na primer z dodajanjem animacije. Preprosto nadomeščajte metodo Nette.toggle
v jeziku JavaScript
s prilagojeno rešitvijo:
Nette.toggle = (selector, visible, srcElement, event) => {
document.querySelectorAll(selector).forEach((el) => {
// hide or show 'el' according to the value of 'visible'
});
};
Onemogočanje potrjevanja
V nekaterih primerih morate preverjanje onemogočiti. Če gumb za oddajo ne sme po oddaji zagnati preverjanja (na primer gumb
Preklic ali Preview), lahko preverjanje onemogočite tako, da pokličete
$submit->setValidationScope([])
. Obrazec lahko delno potrdite tudi tako, da določite elemente, ki jih je treba
potrditi.
$form->addText('name')
->setRequired();
$details = $form->addContainer('details');
$details->addInteger('age')
->setRequired('age');
$details->addInteger('age2')
->setRequired('age2');
$form->addSubmit('send1'); // Potrdi celoten obrazec
$form->addSubmit('send2')
->setValidationScope([]); // Ne potrdi ničesar
$form->addSubmit('send3')
->setValidationScope([$form['name']]); // Potrdi samo polje 'ime'
$form->addSubmit('send4')
->setValidationScope([$form['details']['age']]); // Potrdi samo polje "starost".
$form->addSubmit('send5')
->setValidationScope([$form['details']]); // Potrdi vsebnik "podrobnosti".
Dogodek onValidate na obrazcu se vedno sproži in nanj ne vpliva
setValidationScope
. Dogodek onValidate
na vsebniku se sproži le, če je ta vsebnik določen za delno
preverjanje.