Nette Framework: Neprůstřelné formuláře III
Vzhled formulářů může být velmi pestrý a různorodý. Dnes si
ukážeme, jak tuto různorodost pochytit v Nette Framework a na závěr
ještě zabrousíme k tématu lokalizace.
Seriál Začínáme s Nette Framework
- Nette Framework: Neprůstřelné formuláře
- Nette Framework: Neprůstřelné formuláře II
- Nette Framework: Neprůstřelné formuláře III
- Nette Framework: Cache
- Nette Framework: Co se do seriálu nevešlo?
V předchozím díle seriálu o Nette Framework jsme vytvořili kompletní formulář s validačními pravidly. Dnes se podíváme, jak formulář vykreslit.
V praxi můžeme narazit na dva extrémy. Na jedné straně stojí potřeba v aplikaci vykreslovat řadu různých formulářů, které jsou si vizuálně podobné jako vejce vejci. V takovém případě oceníme, když úkony spojené s vykreslením formuláře budou co nejjednodušší. Jde obvykle o případ administračních rozhraní.
Na druhé straně tu jsou rozmanité formuláře, kde platí: co kus, to originál. Jejich podobu nejlépe popíšeme jazykem HTML. A samozřejmě kromě obou zmíněných extrémů narazíme na spoustu formulářů, které se pohybují někde mezi.
Nette Framework se přitom snaží vyhovět všem požadavkům. Jak toho dosahuje?
Renderer
V zájmu variability a čistoty kódu frameworku není vykreslování přímo součástí třídy Form, ale má jej na starosti speciální objekt nazývaný renderer. Ten lze nastavit metodou $form->setRenderer(). Předá se mu řízení při zavolání metody $form->render() (nebo alternativně echo $form).
Pokud žádný renderer nenastavíme, bude použit výchozí vykreslovač Nette\Forms\ConventionalRenderer.
Díky tomu je vzhled formulářů plně ve vašich rukou. Máte celou řadu možností, jak vykreslování ovlivnit:
- využít ConventionalRenderer, který je bohatě konfigurovatelný
- vytvořit vlastní renderer
- třeba tak, že vytvoříte potomka ConventionalRenderer
- napíšete si vlastní renderer na míru
- stáhnete si hotový renderer z internetu
- a nebo vykreslíte formulář manuálně
Začněme u výchozího vykreslovače.
Nette\Forms\ConventionalRenderer
Dovoluje nám vykreslit formulář tou nejsnadnější cestou. Stačí napsat:
echo $form;
a formulář je na světě. Prvky formuláře se vykreslí do HTML tabulky. Výstup vypadá takto:
<table><tr class="required">
<th><label class="required" for="frm-name">Jméno:</label></th>
<td><input type="text" class="text" name="name" id="frm-name" value="" /></td></tr><tr class="required">
<th><label class="required" for="frm-age">Věk:</label></th>
<td><input type="text" class="text" name="age" id="frm-age" value="" /></td></tr><tr>
<th><label>Pohlaví:</label></th>
...
Hezky naformátované, viďte? :-)
Zda použít nebo nepoužít pro kostru formuláře tabulku je sporné a řada webdesignerů preferuje jiný markup. Například definiční seznam. Pokusíme se ConventionalRenderer překonfigurovat tak, aby formulář v podobě seznamu vykreslil. Konfigurace se provádí editací pole $wrappers . První index vždy představuje oblast a druhý její atribut. Jednotlivé oblasti znázorňuje obrázek:
Některé oblasti z pole $wrappers.
Standardně je skupina prvků controls obalena tabulkou ( table), každý pair představuje řádek tabulky ( tr) a dvojice label a control jsou buňky ( th a td). Nyní obalovací elementy změníme. Oblast controls vložíme do kontejneru dl, oblast pair necháme bez kontejneru, label vložíme do dt a nakonec control obalíme značkami dd:
$renderer = $form->getRenderer();
$renderer->wrappers['controls']['container'] = 'dl';
$renderer->wrappers['pair']['container'] = NULL;
$renderer->wrappers['label']['container'] = 'dt';
$renderer->wrappers['control']['container'] = 'dd';
echo $form;
Výsledkem je tento HTML kód:
<dl>
<dt><label class="required" for="frm-name">Jméno:</label></dt>
<dd><input type="text" class="text" name="name" id="frm-name" value="" /></dd>
<dt><label class="required" for="frm-age">Věk:</label></dt>
<dd><input type="text" class="text" name="age" id="frm-age" value="" /></dd>
<dt><label>Pohlaví:</label></dt>
...
V poli wrappers lze ovlivnit celou řadu dalších atributů:
- přidávat CSS třídy jednotlivým typům formulářových prvků
- rozlišovat CSS třídou liché a sudé řádky
- vizuálně odlišit povinné a volitelné položky
- určovat, zda se chybové zprávy zobrazí přímo u prvků nebo nad formulářem
- atd…
Manuální vykreslování
ConventionalRenderer nám umožňuje bleskově renderovat formuláře se standardním vzhledem. Jak ale vykreslit formulář, který lze jen těžko postihnout polem $wrappers nebo vlastním rendererem? Asi nejpragmatičtější řešení je takový formulář popsat přímo HTML šablonou.
Jak už víte, jednotlivé prvky formuláře lze adresovat podobně jako prvky pole (tj. třeba $form['name']). Co možná nevíte, tak že každý prvek disponuje metodami getLabel() a getControl(), které vracejí HTML kód popisky a samotného prvku. A jak jsme si ukázali už dříve, Nette Framework dovoluje ke getterům přistupovat podobně, jako by to byly proměnné, takže stačí psát jen label a control. Dejme tyto informace dohromady a máme tu manuální renderování:
<?php $form->render('begin') ?>
<?php $form->render('errors') ?>
<table><tr class="required">
<th><?php echo $form['name']->label ?></th>
<td><?php echo $form['name']->control ?></td></tr><tr class="required">
<th><?php echo $form['age']->label ?></th>
<td><?php echo $form['age']->control ?></td></tr><tr>
<th><?php echo $form['gender']->label ?></th>
<td><?php echo $form['gender']->control ?></td></tr><tr>
<th><?php echo $form['email']->label ?></th>
<td><?php echo $form['email']->control ?></td></tr>
...
</table>
<?php $form->render('end') ?>
V tuto chvíli jste naprostým pánem vygenerovaného kódu. Formulář si vykreslíte přesně na míru.
Když do vykreslování zapojíme ještě filtr CurlyBracketsFilter, může výsledná šablona vypadat takto:
<table><tr class="required">
<th>{!$form['name']->label}</th>
<td>{!$form['name']->control}</td></tr>
....
Nyní už máte základní přehled v tom, jak lze v Nette Framework vykreslit formulář.
Automatický překlad formulářů
Pokud programujete multijazyčnou aplikaci, budete nejspíš potřebovat stejný formulář vykreslit v různých jazykových mutacích. Formuláře v Nette Framework disponují podporou pro snadný překlad. Stačí, když formuláři nastavíte tzv. překladač, což je objekt implementující rozhraní Nette\ITranslator . Rozhraní má jedinou metodu translate().
class MyTranslator extends Object
{
/**
* Translates the given string.
* @param string message
* @param int plural count
* @return string
*/
public function translate($message, $count = NULL)
{
return ...;
}
}
$form->setTranslator($translator);
V tu chvíli se nejen všechny labely, ale i všechny chybové hlášky nebo položky select boxů transparentně přeloží do jiného jazyka.
Jako konkrétní implementaci překladače můžete použít například GNU gettext nebo Zend_Translate.
Autor článku je vývojář na volné noze, specializuje se na návrh a programování moderních webových aplikací. Vyvíjí open-source knihovny Texy, dibi a Nette Framework a pravidelně pořádá školení pro tvůrce webových aplikací, které od podzimu 2009 nabídne kurz vývoje AJAXových aplikací.
Školení Google+ pro firmy

- Jak využít Google+ pro firemní komunikaci a marketing.
- Čím se liší Google+ od Twitteru a Facebooku z pohledu firemního využití.
- Jak využít Google+ v souladu s pravidly užívání.
- Založení Google+ Page (Stránky) krok po kroku, včetně praktických tipů.
Detailní informace o školení Google+ »
Seriál Začínáme s Nette Framework
- Nette Framework: Neprůstřelné formuláře
- Nette Framework: Neprůstřelné formuláře II
- Nette Framework: Neprůstřelné formuláře III
- Nette Framework: Cache
- Nette Framework: Co se do seriálu nevešlo?
Přehled názorů
Tento text je již více než dva měsíce starý. Chcete-li na něj reagovat v diskusi, pravděpodobně vám již nikdo neodpoví. Pro řešení aktuálních problémů doporučujeme využít naše diskusní fórum.
