Přejít k navigační liště

Zdroják » PHP » Nette Framework: Neprůstřelné formuláře III

Nette Framework: Neprůstřelné formuláře III

Články PHP, Různé

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.

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í.

Komentáře

Subscribe
Upozornit na
guest
11 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
v6ak

Toto mi v příkladu chybí.

PetrP

Článek není součástí serialu

Martin Hassman

Pravda, tak ted uz je.

cckar

mohl bych si rypnout? proc je formatovani reseno pomoci tabulky a ne cele pomoci
CSS? Doba, kdy se rozlozeni stranky resilo tim, ze se elementy nacpaly do ruzne
vnorenych tabulek, je snad za nami :) Nemely by se tagy

cckar

/grr, ted mi to useklo comment po napsani tagu tables./

…tagy tables pouzivat jen pro skutecne tabulky? takhle mi to zrusi validitu
CSS stranky.

mlady

Mozes si to predsa lahko zmenit cez $wrappers ako sa pise v clanku:

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:

blizz.boz

a čo to je to „CSS stránka“? a ako „tabulky narušujú validitu“?
vieš o tom xxx ale ideš tu niekoho poučovať… použitie tabuliek v tomto
príapade je úplne opodstatnené…

16. 6. 2009 20:46 redakčně upravil Martin Hassman, důvod: Drobne umravneni
Jakub Vrána

Jeden formulář přece není celá stránka. A podle určité filozofie (ke
které se hlásím) většina formulářů charakter tabulky skutečně má. Je
to vlastně přehled popisků, jejich hodnot a jejich případných chyb.

Mejla

Přesně tak – dokonce bych řekl, že použití tabulky u formů je hodně použitelné. Jen tak se totiž v tabulce formátování nerozhodí obzvláště při vypisování různých chybových hlášení a poznámek k inputům.

Makeš

Ano, hlavně pokud chcete vypisovat chybové hlášky pod každý jednotlivý element tak jsou buňky tabulky příjemnější, jednodušší a řekl bych i lepší.

Myslím, že není důvod mít celou aplikaci bez jediné tabulky – když je vhodný případ.

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.