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 (17 dílů)

  1. Nette Framework: zvyšte svoji produktivitu 10.3.2009
  2. Nette Framework: Odvšivujeme 17.3.2009
  3. Nette Framework: MVC & MVP 24.3.2009
  4. Nette Framework: Refactoring 31.3.2009
  5. Nette Framework: Chytré šablony 7.4.2009
  6. Nette Framework: adresářová struktura aplikace 14.4.2009
  7. Nette Framework: AJAX 21.4.2009
  8. Nette Framework: AJAX (pokračování) 28.4.2009
  9. Nette Framework: AJAX (dokončení) 5.5.2009
  10. Nette Framework: Sessions 12.5.2009
  11. Nette Framework: Přihlašování uživatelů 19.5.2009
  12. Nette Framework: Ověřování oprávnění a role 26.5.2009
  13. Nette Framework: Neprůstřelné formuláře 2.6.2009
  14. Nette Framework: Neprůstřelné formuláře II 9.6.2009
  15. Nette Framework: Neprůstřelné formuláře III 16.6.2009
  16. Nette Framework: Cache 23.6.2009
  17. Nette Framework: Co se do seriálu nevešlo? 30.6.2009

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č NetteFormsCon­ventionalRende­rer.

Díky tomu je vzhled formulářů plně ve vašich rukou. Máte celou řadu možností, jak vykreslování ovlivnit:

  • využít ConventionalRen­derer, který je bohatě konfigurovatelný
  • vytvořit vlastní renderer
    • třeba tak, že vytvoříte potomka ConventionalRen­derer
    • 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.

NetteFormsCon­ventionalRende­rer

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 ConventionalRen­derer 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:

Nette formulář

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í

ConventionalRen­derer 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 CurlyBracketsFil­ter, 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í NetteITranslator . 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í.

David Grudl školí, je autorem PHP knihoven Nette Framework, databázové vrstvy dibi a formátovače HTML kódu Texy!.

Věděli jste, že nám můžete zasílat zprávičky? (Jen pro přihlášené.)

Komentáře: 11

Přehled komentářů

v6ak implements ITranslator
PetrP chybka zařazení
Martin Hassman Re: chybka zařazení
cckar formatovani elementu formulare tabulkami
cckar Re: formatovani elementu formulare tabulkami
mlady Re: formatovani elementu formulare tabulkami
blizz.boz Re: formatovani elementu formulare tabulkami
David Grudl Re: formatovani elementu formulare tabulkami
Jakub Vrána Re: formatovani elementu formulare tabulkami
Mejla Re: formatovani elementu formulare tabulkami
Makeš Re: formatovani elementu formulare tabulkami
Zdroj: https://www.zdrojak.cz/?p=3033