Definice formulářů

Jak jsme si řekli v předchozí kapitole, tak formuláře je nutné definovat a je jedno zda se chystáme formulář použít pouze pro zachycení a validaci dat, nebo i pro zobrazení. Základní definice je vždy společná.

Princip definice je vlastně naprosto triviální. Formulář je reprezentován instancí třídy Jet\Form. Formulářové pole je obecně reprezentováno abstraktní třídou Jet\Form_Field, ovšem vždy má konkrétní typ formulářového pole (tedy i konkrétní účel, vlastnosti a celkové chování formulářového pole), který je reprezentován jednou ze tříd. Přehled typů polí a jejich tříd najdete zde. Toto je obecný princip, ale pojďme si k tomu říct několik detailů.

Vytvoření instance pole

Pro vytvoření pole jsou dvě možnosti. Buď tradiční vytvoření instance:

use Jet\Form;
use 
Jet\Form_Field_FileImage;

$img_field = new Form_Field_FileImage(
    
name'image'
    
label'Image:'
    
is_requiredtrue
);
$img_field->setMaximalFileSize2048 );
$img_field->setMaximalSizemaximal_width800maximal_height600 );
Nebo prostřednictvím příslušné továrny: use Jet\Form;
use 
Jet\Form_Field;
use 
Jet\Form_Field_FileImage;
use 
Jet\Factory_Form;

/**
 * @var Form_Field_FileImage $img_field
 */
$img_field Factory_Form::getFieldInstance(
    
typeForm_Field::TYPE_FILE_IMAGE,
    
name'image',
    
label'Image',
    
is_requiredtrue
);
$img_field->setMaximalFileSize2048 );
$img_field->setMaximalSizemaximal_width800maximal_height600 );
V ukázkové aplikaci můžete vidět, že v rámci aplikačního prostoru je používán klasický přístup přímého použití názvu třídu a naopak uvnitř knihovny Jet (tedy v adresáři ~/library/Jet) jsou striktně používány továrny. Kdysi jsme používal továrny i v aplikačním prostoru pro zachování konzistence, ale to se ukázalo jako nepraktické a tak trochu otravné.

Smyslem továren je snadné nahrazení tříd bez zásahů do jádra celé platformy. Tedy musíte mít možnost třeba třídu Jet\Form_Field_Tel nahradit svou vlastní třídou a to i když často používáte automatické generování formulářů pomocí mapování na třídy. Tam jsou továrny prostě nezbytné.

Ovšem v aplikačním prostoru máte vše pod kontrolou a je jen na vás jakou instanci čeho vytvoříte a případná výměna třídy za jinou není v dobách moderních IDE problém - je to práce pár okamžiků. Tedy z toho důvodu platí, že vnitřně Jet pro vytváření formulářů používá továrnu, ale v aplikačním prostoru (včetně mikroaplikací jako je například instalátor) se vytváří z důvodu praktičnosti instance přímo.

Název pole

Proč se zabývat názvem formulářového pole? Jedna důležitá specialita tu je. Například pro psaní tohoto textu potřebuji v redakčním systému tohoto webu například tyto pole: <input type="text" name="content[cs_CZ-initial][title]">
<
textarea name="content[cs_CZ-initial][annotation]"></textarea>
<
textarea name="content[cs_CZ-initial][description]"></textarea>
<
textarea name="content[cs_CZ-initial][key_words]"></textarea>
<
textarea name="content[cs_CZ-initial][text]"></textarea>

Teď si na chvíli představme, že nejsme v Jet aplikaci, ale je použito čisté PHP a já chci z požadavku získat český text tohoto článku. Udělám to takto: $text $_POST['content'][$locale.'-'.$version]['text'];
Prostě a jednoduše řečeno: S formuláři a jejich daty potřebujeme operovat jako s N rozměrným polem.

Ovšem jak již asi víte, tak v Jet aplikaci se k superglobálním polím $_GET a $_POST ani nedostanete (v běžném nastavení) a pokud už by bylo teoreticky nutné "sahat" na POST přímo (což při práci s formuláři nutné není a je to nežádoucí - ale pro názornost to udělejme), tak lze data získáme takto: $text Http_Request::POST()->getString('/content/'.$locale.'-'.$version.'/text');

Jak vidíte, tak k datům v poli se přistupuje pomocí cesty. Je to univerzální přístup, který se v Jet používá všude a vychází ze základní třídy Jet\Data_Array.

A asi nikoho nepřekvapí, že zcela totožným způsobem bude pojmenováno formulářové pole v definici. Tedy: foreach( Application_Web::getBase()->getLocales() as $locale ) {
    
    
//*******************************************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    
$text_field = new Form_Field_Textarea('/content/'.$locale.'-'.$version.'/text''Text:');
    
//*******************************************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    
    
$text_field->setDefaultValue$this->getContent($locale)->getText() );
    
    
$text_field->setFieldValueCatcher( function( $value ) use ($locale$version) {
        
$this->getContent($locale)->setText$value );
    });
    
    
//... ... ...
    
    
$form->addField$text_field );
}

Poznámka: V ukázce trochu předbíhám téma a je tam rovnou kázáno i zachycení dat (předání hodnoty nějaké instanci). O tom si víc povíme v extra kapitole. Ale když už jsem zde pro demonstraci ukázal ne zcela ideální přístup, tak jsem musel rovnou ukázat i ten správný ;-)

Přidávání pole do formuláře

Formulářový prvek musí být v nějakém formuláři a formulář potřebuje formulářové prvky. To dá rozum. Ale i zde si ukážeme pár zajímavých možností.

Přidání polí rovnou

Základní a asi nejčastější možnost je přidání polí do formuláře rovnou při vytvoření jeho instance: use Jet\Form;
use 
Jet\Form_Field_Input;
use 
Jet\Form_Field_Tel;

$name_field = new Form_Field_Input('name''Name:');
$tel_number_field = new Form_Field_Tel('tel_number''Tel. number:');

$form = new Formname:'contact_form'fields: [
    
$name_field,
    
$tel_number_field
]);

Přidání polí do existujícího formuláře

Z různých důvodů můžeme potřebovat přidat pole do již existujícího formuláře. Například může jít o formulář vytvořený rodičovskou třídou, který si v potomkovi potřebujeme upravit a tak dále. Možností je celá řada. use Jet\Form;
use 
Jet\Form_Field_Input;
use 
Jet\Form_Field_Tel;

//... ... ...

$name_field = new Form_Field_Input('name''Name:');
$tel_number_field = new Form_Field_Tel('tel_number''Tel. number:');

$form->addField$name_field );
$form->addField$tel_number_field );

Dokonce je možné dělat takové věci, jako vzít pole z formuláře prvního, to přejmenovat a umístit jej do formuláře druhého: $clone_field = clone $form_a->field('some_field');

$clone_field->setName('new_name');

$form_b->addField$clone_field );

Odebírání pole

Není to častá situace, ale v praxi narazíte na situaci, kdy je naopak nutné / vhodné pole z formuláře odstranit. I tato možnost samozřejmě existuje: $form->removeField'some_field' );

Název formuláře

Jak jste si již jistě všimli v příkladech, tak nejen pole, ale i formulář samotný má své jméno: use Jet\Form;

$form = new Formname:'some_form_name'fields: [
    
//... ... ...
]);

K čemu je to dobré? Pokud na stránce budete mít více jak jeden formulář, tak musí být jasné který formulář je právě odeslán a tedy má být zachycen a zpracován. Název formuláře se pak používá jako hodnota skrytého pole. Název tohoto speciálního skrytého pole lze samozřejmě změnit a to buď globálně pro celou aplikaci, nebo pro každý formulář zvlášť. Výchozí název tohoto pole je: _jet_form_sent_.

Pozor! I když formulář název mít musí, tak existence skrytého pole s názvem formuláře není podmínkou. Ostatně pro takové REST API, kde jsou formuláře také používány pro zachycení a validaci, by to bylo dosti nešťastné. Formulář lze zachytit i bez tohoto pole, ale to si ukážeme v jiné kapitole.

Kam dál?

Teď už znáte obecný princip definice formuláře. Ovšem než se pustíte do zajímavé problematicky zachytávání a validace formulářů stejně tak jako jejich zobrazování, tak doporučuji kouknout na referenci k třídy Jet\Form a také se prosím seznamte s třídou Jet\Form_Field a typy formulářových polí.

Předchozí kapitola
Formuláře
Další kapitola
Jet\Form