Formuláře v Nette 2.1
Formuláře byly vždy klíčovou součástí frameworku. Od první verze umožňují vývojářům snadno definovat vstupní prvky, vykreslit je a zpracovávat data vložená uživatelem. Nette 2.1 přináší několik nových funkcí a řeší řadu problémů a omezení z předchozích verzí.
Tento článek se zabývá nejdůležitějšími vylepšeními formulářů:
- nový nízkoúrovňový přístup k datům formuláře,
- vylepšené vykreslování pomocí atributů
n:
- nové funkce ve validaci formuláře
Low-level formuláře
Nyní lze používat i prvky, které zapíšeme pouze v šabloně a
nepřidáme je do formuláře některou z metod
$form->addXyz()
. Když například vypisujeme záznamy
z databáze a dopředu nevíme, kolik jich bude a jaké budou mít ID, a chceme
u každého řádku zobrazit checkbox nebo radio button, stačí jej nakódovat
v šabloně:
{foreach $items as $item}
<p><input type=checkbox name="sel[]" value={$item->id}> {$item->name}</p>
{/foreach}
A po odeslání hodnotu zjistíme:
$values = $form->getHttpData($form::DATA_TEXT, 'sel[]');
kde první parametr je typ elementu (DATA_FILE
pro
type=file
, DATA_LINE
pro jednořádkové vstupy jako
text
, password
, email
apod. a
DATA_TEXT
pro všechny ostatní) a druhý parametr
sel[]
odpovídá HTML atributu name
.
Podstatné je, že getHttpData()
vrací sanitizovanou
hodnotu, v tomto případě to bude vždy pole validních
UTF-8 řetězců, ať už se pokusíte serveru podstrčit cokoliv. Jde
o obdobu přímé práce s $_POST
nebo $_GET
avšak
s tím podstatným rozdílem, že vždy vrací čistá data, tak, jak jste
zvyklí u standardních prvků Nette formulářů.
CheckboxList
Nový prvek pro výběr z více možností je CheckboxList. Stejně jako v případě selectboxů nebo radiolistů kontroluje, zda odeslané hodnoty jsou z těch, které nabízíme:
$form = new Form;
$form->addCheckboxList('colors', 'Favorite colors:', array(
'r' => 'red',
'g' => 'green',
'b' => 'blue',
));
Multiple file upload
Najednou lze uploadovat i více souborů, všimněte si
true
:
$form = new Form;
$form->addUpload('avatar', 'Picture:', true);
Zároveň formuláře mají integrovanou kontrolu, zda nebyl překročen povolený limit velikosti odesílaných dat.
Nové vykreslovací zbraně
Velmi snadno můžete propojit formulář s existující šablonou. Stačí
jen doplnit atributy n:name
:
function createComponentSignInForm()
{
$form = new Form;
$form->addText('user')->setRequired();
$form->addPassword('password')->setRequired();
$form->addSubmit('send');
return $form;
}
<form n:name=signInForm class=form>
<p><label n:name=user>Username: <input n:name=user size=20></label>
<p><label n:name=password>Password: <input n:name=password></label>
<p><input n:name=send class="btn btn-default">
</form>
Atribut n:name
lze používat i s elementy
<select>
, <button>
nebo
<textarea>
.
Dále můžete vykreslovat prvky jako je RadioList, Checkbox nebo nový CheckList pěkně po jednotlivých HTML elementech. Říká se tomu partial rendering:
{foreach $form[gender]->items as $key => $label}
<label n:name="gender:$key"><input n:name="gender:$key"> {$label}</label>
{/foreach}
Nebo lze použít klasická makra {input gender:$key}
a
{label gender:$key}
, trik je tom názvu s dvojtečkou.
S tím úzce souvisí i aktualizovaný způsob vykreslování checkboxů a RadioListů. Místo dřívějšího
<label>...</label><input>
se nyní vykreslují v praktičtějším tvaru
<label><input>...</label>
pročež si myslím, že odpadne většina důvodů, proč jste tyto prvky potřebovali vykreslovat po částech.
Zároveň také odpadá nutnost kreslit
checkboxy trošku jinak než jiné prvky, tj. myslet na to, aby label byl na
správném místě. Metoda getLabel()
či makro
{label}
totiž u checkboxů nyní nevrací nic a
getControl()
či {input}
vrací HTML v onom novém
tvaru. Pokud ale potřebujete staré chování, přepněte se do zmíněného
partial renderingu přidáním dvojtečky: {label checkbox:}
a
{input checkbox:}
.
Podpora pro Bootstrap
V příkladech najdete ukázky, jak nakonfigurovat vykreslování formulářů pro Twitter Bootstrap 2 a Bootstrap 3.
Chytřejší validátory
Validační pravidla Form::INTEGER
, NUMERIC
a
FLOAT
rovnou převádí hodnotu na integer resp. float. A dále
pravidlo Form::URL
, které akceptuje i řetězec ve tvaru např.
nette.org
, jej automaticky doplní na plnohodnotné
https://nette.org
.
Přibyla nová validační pravidla Form::BLANK
(prvek nesmí
být vyplněn) a Form::NOT_EQUAL
.
A v argumentech všech validátorů se můžete dynamicky odkazovat na
jiné prvky. Takže třeba tady prvek value
musí být v rozmezí
určeným aktuálními hodnotami prvků min
a max
:
$form->addText('min');
$form->addText('max');
$form->addText('value')
->addRule($form::RANGE, 'from %d to %d', array($form['min'], $form['max']));
Chybové zprávy
Makro {control form}
nyní vypisuje chybové zprávy přímo
vedle souvisejících prvků a nad formulářem se objeví jen ty, které
žádnému prvku nepřiřadíme (tj. když místo
$form['name']->addError()
použijeme
$form->addError()
). Je to mnohem uživatelsky příjemnější a
doporučuji, abyste stejným způsobem vykreslovali i formuláře manuálně,
třeba
takto. Pomůže vám metoda $form->getOwnErrors()
, která
vrací chybové zprávy přiřazené jen k formuláři.
Píšeme vlastní prvky
Výrazného zjednodušení doznala tvorba vlastních formulářových prvků.
Podívejte se na příklad
DateInput, což je prvek pro zadávání data. Zobrazovat se bude jako
trojice políček den, měsíc, rok a z pohledu API bude přijímat a vracet
objekt DateTime
.
Interně se datum reprezentuje jako trojice privátních proměnných
$day, $month, $year
, které metoda getValue()
převede
na požadovaný objekt DateTime
(tedy pokud půjde o platné
datum) a setValue()
naopak vstup do této trojice rozloží.
Přičemž by měla kontrolovat validitu vstupu a v případě chyby vyhodit
výjimku.
Výjimky naopak nevyhazuje loadHttpData()
, která se volá po
odeslání formuláře, a hodnoty, které uživatel odeslal, získá metodou
getHttpData()
a uloží do zmíněné trojice proměnných. Jen
pozor, tentokrát mluvím o metodě třídy BaseControl
, nikoliv
Form
. Každopádně i v tomto případě
getHttpData()
vrací očištěná data.
A nakonec metoda getControl()
generuje HTML. Pokud je prvek
reprezentován jedním HTML elementem, jeho atribut name
určí
metoda getHtmlName()
. Jenže máme prvky tři, tak za název
ještě dolepíme řetězec [day]
, [month]
a
[year]
(včetně těch hranatých závorek). Stejný postfix pak
uvádíme při volání getHttpData()
ve zmíněné
loadHttpData()
.
Co když místo obyčejného textového pole budeme chtít vykreslit
selectbox? Pak oceníte funkci
Nette\Forms\Helpers::createSelectBox()
. Prvním parametrem je pole
nabízených hodnot, druhým pole HTML atributů elementu
<option>
. V příkladu uvedené selected?
s otazníkem znamená, že atribut se uvede pouze u položky s uvedenou
hodnotou. Šlo by také uvést např.
'title:' => array(1 => 'January', 2 => ...)
s dvojtečkou, což dává možnost každé položce dát jiný
title
.
Existuje také obdobná funkce createInputList()
pro
generování skupin inputů. Té lze jako třetí parametr předat pole HTML
atributů pro element label
, taktéž podporující otazník a
dvojtečku.
Dále autoři nových prvků mohou ocenit dvě nové abstraktní třídy ChoiceControl
a MultiChoiceControl
.
A co ještě?
Pomocí $control->setOmitted()
vyjmete prvek z dat, která
vrací $form->getValues()
. To se hodí pro různé hesla pro
kontrolu, antispamové prvky atd. I všechny prvky, které označíte jako
$form->setDisabled()
, budou takto vyjmuty.
Vylepšeno bylo togglování, nyní by mělo fungovat přesně podle
očekávání. Navíc $form->getToggles()
vrátí informaci
o viditelnosti všech id.
Metoda setValue()
u jednotlivých prvků kontroluje datový typ
a dále v případě SelectBoxů a podobně vás nenechá nastavit hodnotu,
která v nabízených není.
V HTML atributech data-nette-rules
se používá čistý JSON,
takže nezapomeňte nasadit aktuální netteForms.js
.
A nakonec – u jednotlivých tlačítek můžete omezit seznam prvků, které se mají při odeslání formuláře tímto tlačítkem validovat:
$form->addSubmit('edit')
->setValidationScope(array($form['name'], $form['password']));
Chcete-li odeslat komentář, přihlaste se