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

Odebírat
Upozornit na
guest
11 Komentářů
Nejstarší
Nejnovější Most Voted
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.

Odysseus: PewDiePie vydal open-source AI workspace, který běží na vašem vlastním hardwaru

AI
Komentáře: 0
Felix Kjellberg, youtuber se 110 miliony odběratelů, strávil rok učením se programovat a fine-tuningem vlastních AI modelů. Výsledkem je Odysseus – bezplatný, open-source workspace pro práci s umělou inteligencí, který neposílá žádná data do cloudu. Projekt má týden, přes 61 000 hvězdiček na GitHubu a znovu otevírá otázku, komu vlastně patří váš digitální kontext.

Když Git už nestačí: jak izolovat databázový stav pro pokusy AI agentů

Gitová větev vývojářům oddělí kód, ale databáze často zůstává společná. U AI agentů je to slabé místo: rychle spouštějí migrace, mění data a zkoušejí víc cest najednou. Databázová větev jim dá vlastní pracovní prostor, jenže tím práce nekončí. Ještě je potřeba řešit citlivá data, oprávnění, životnost větve i zbytek stavu aplikace.

GitHub vyhrál pohodlím. Stejné pohodlí dnes ztěžuje odchod

GitHub kdysi působil jako přesný opak SourceForge: rychlý, přehledný a přirozený. Dnešní projekt na něm ale často nemá jen kód. Má tam issues, pull requesty, CI, balíčky, bezpečnostní pravidla i AI agenty. Lock-in nevzniká tím, že by nešel odnést Git repozitář, ale tím, že se běžný provoz týmu postupně přesune do jedné platformy.