Vykreslování
Ve výchozím nastavení Nette formuláře nabízí automatické vykreslování pomocí tzv. DefaultFormRenderer. Dále je možné formulář vykreslovat ručně, což je vhodné zejména ve chvílích, kdy je formulář složitý a jeho vizuální podoba má být nestandardní.
Přizpůsobení HTML výstupu formulářových prvků
Pro přizpůsobení HTML vlastností políčka použijeme metodu getControlPrototype(). Získáme tak šablonu, podle které bude políčko vyrobeno v podobě Nette\Utils\Html objektu.
$form->addText('name', 'Název');
$controlPrototype = $form['name']->getControlPrototype(); //instance Nette\Utils\Html
$controlPrototype->class('big')->style(array('color' => 'red'));
Totéž lze napsat bez použití proměnné pro instanci HTML prototypu.
$form->addText('name', 'Název')
->getControlPrototype()
->class('big')
->style(array('color' => 'red'));
Je důležité uvědomit si, že na zavoláním poslední metody (style) dostáváme instanci objektu Nette\Utils\Html, tudíž následně není možné upravit formulářový prvek plynulým zápisem. Je proto nutné provést potřebnou konfiguraci před úpravou html prvku nebo následně získat jeho znovu instanci (první způsob).
Pro label je postup obdobný, liší se pouze název metody getLabelPrototype():
$form->addText('name', 'Název')->getLabelPrototype()->class('label-big');
Obdobně můžeme upravit i HTML element samotného formuláře:
$form->getElementPrototype()->class('very-nice-form');
Skupiny
Formulářové prvky lze seskupovat i čistě vizuální cestou (tedy ne
pomocí kontejneru). Slouží k tomu skupiny a metoda addGroup($name).
Jedná se o Nette ekvivalent k <fieldset> a
<legend>, který bude obsahovat data z parametru
$name. Jejich chování se od prvků značně liší:
- přidávají se na formulář
- nijak neovlivňují strukturu dat
- jsou vykreslovány v pořadí v jakém byly přidány
- pokud existuje alespoň jedna skupina, prvky bez skupiny se vykreslují až po vykreslení skupin
K práci se skupinami se používají tyto metody:
- addGroup: slouží k přidání nové a otevření skupiny
- setCurrentGroup: otevře již existující skupinu
- removeGroup: odstraní skupinu
$form->addGroup('Osobní info');//následující prvky spadají do této skupiny
$form->addText('name', 'Jméno a příjmení');
$form->addText('email', 'E-mail');
$form->setCurrentGroup(NULL); //následující prvky nejsou v žádné skupině
$form->addSelect('question', 'Máte rádi psy?', array(
'yes' => 'Ano',
'no' => 'Na talíři',
));
DefaultFormRenderer
Wrappery
Příklad viz distribuce Nette/Examples/Forms
Toggle
Jak už název napovídá, skrývá a zobrazuje prvky formuláře, nebo
stránky. Je rozšířením validačních pravidel a proto je pro fungování
nezbytné, aby ve stránce byl připojen script netteForms.js.
Prvky automaticky po načtení stránky podle potřeby schová, nebo zobrazí
javascriptem, na základě hodnot formuláře a definovaných pravidel.
Nejčastěji je aplikován na skupinu ($form->addGroup()).
Jako argument se předává #id elementu stránky, se kterým má
pracovat.
$subjects = array(
1 => "Právnická Osoba",
2 => "Fyzická osoba"
);
$form->addGroup(); // nutné, jinak by se ostatní skupiny zobrazili nad touto
$form->addRadioList("subject", "Jsem", $subjects)
->addCondition(Form::EQUAL, 1)
->toggle("PO") // zobrazíme skupinu s id "PO"
->elseCondition()
->toggle("FO"); // zobrazíme skupinu s id "FO"
$form->addGroup()->setOption('container', Html::el('fieldset')->id("PO"));
$form->addText("ico", "IČO");
$form->addGroup()->setOption('container', Html::el('fieldset')->id("FO"));
$form->addText("rn", "Rodné číslo");
Jelikož je toggle js funkce, která je aktivována při
načtení stránky, schovaný obsah vždy problikne, což není moc pěkné.
Řešením je přidání display:none pro danou skupinu, což
můžeme přidat buď ručním renderováním, nebo přímo na skupinu při
vytváření formuláře:
$form->addGroup()->setOption('container', Html::el('fieldset')->id("PO")->style("display:none"));
Pokud uživatel zvolí, že je fyzická osoba, budeme po něm vyžadovat rodné číslo a naopak. Bylo by matoucí, kdyby měl vyplňovat rodné číslo a input by na stránce nebyl. Podmíníme proto validační pravidla výběrem typu osoby.
$form->addText("rn", "Rodné číslo:")
->addConditionOn($form["subject"], Form::EQUAL, 2) // zvolena FO
->addRule(Form::FILLED, "Vyplňte rodné číslo");
„Vnořený“ toggle
Tedy pokud chceme v již vybrané skupině rozlišit mezi dalšími 2 skupinami.
Doručovací adresa je součástí skupiny „PO“
$form->addText("street");
// ...
Ve výchozím stavu je další adresa schovaná, protože předpokládáme, že je stejná
$form->addCheckbox("invoiceSame")
->setDefaultValue("on")
->addCondition(Form::EQUAL, 0)
->toggle("invoiceAddress"); // pro funkčnost musíme přidat i původní skupinu
$form->addGroup()->setOption('container', Html::el('fieldset')->id("invoiceAddress"));
$form->addText("streetInvoice");
// ...
Pro adresu je výhodnější použít samostatný container.
„Sdílený“ toggle
Pokud máme 2 možnosti, které něco sdílí, můžeme vytvořit třetí skupinu a tu zobrazovat pro obě volby. Využití najdete v případě, kdy máte na počátku ještě 3. možnost, která tuto třetí skupinu nepotřebuje.
$subjects = array(
1 => "PO",
2 => "FO"
);
$form->addRadioList("subject", "Jsem:", $subjects)
->addCondition(Form::EQUAL,1)
->toggle("PO")
->endCondition() // ukončení podmíny
->addCondition(Form::EQUAL,2)
->toggle("FO")
->endCondition() // ukončení podmíny
->addCondition(Form::IS_IN,array(1,2)) // tímto zobrazíme adresu pro obě skupiny
->toggle("address");
Ruční vykreslení toggle
Toggle pracuje id v css, stačí tedy příslušnému bloku
nastavit jeho hodnotu. Využijeme výše uvedeného formuláře.
Vhodné je daný box schovat pomocí css na prvku (jiný zápis
není možný, jelikož js pracuje právě s display
na prvku), aby nedošlo při načítání stránky k probliknutí při jeho
schování js.
{form toggleForm}
<div>
{label subject /}</td><td>{input subject}</td>
</div>
<div id="PO" style="display:none">
<!-- zde vykreslíme prvky pro PO -->
</div>
<div id="FO" style="display:none">
<!-- zde vykreslíme prvky pro FO -->
</div>
{/form}
Options
…
InstantClientScript
…
Ruční vykreslování
{form myForm}
{label login /} {input login}
{label password /} {input password}
{/form}
Jednotlivým prvkům můžeme přidávat různé hodnoty. Lze tak možné přenést stylování z presenteru přímo do šablony.
{input search, class => searchInput, size => 30, text => "Hledání:", value => "Najděte, co hledáte"}
Nastavovat hodnotu prvku lze libovolně, výjimkou je prvek hidden, kde to možné není. Tento nedostatek, lze řešit pomocí addDynamic, nebo „natvrdo“ u daného prvku.