Vytvoření vlastního typu pole

Krom připravených typů formulářových polí si můžete samozřejmě vytvořit své vlastní pole - vlastní typ, nebo lepší implementaci pro již existující typ. Jedinou podmínkou je použití dědičnosti. Každé formulářové pole (respektive jeho třída) musí dědit od třídy Jet\Form_Field. Vaše třídy tedy musí dědit od uvedené třídy, ale samozřejmě mohou dědit od libovolné již existující třídy. Prostě standardní objektově orientované programovaní ❤️

Pozor na jednu důležitou věc. Pokud používáte automatické generování formulářů mapovaných na třídy a chcete vaší novou třídu (nebo celý nový typ) použít i pro tyto formuláře, tak musíte dát vědět příslušné továrně že existuje nový typ, nebo že daný existující typ pole reprezentuje nová třída.

Nová implementace existujícího typu formulářového pole

Jak bylo řečeno, tak stačí vytvořit novou třídu, která může dědit od stávající třídy reprezentující daný typ formulářového pole: namespace JetApplication;

use 
Jet\Form;
use 
Jet\Form_Field_Tel;

class 
MyForm_Field_Tel extends Form_Field_Tel {
    
//.. ... ..    
}
POZOR! Je nutné předat informaci továrně. Volání továren je nutné umístit do inicializace aplikace. Tedy do skriptu ~/application/Init/Factory.php use Jet\Factory_Form;

Factory_Form::setFieldClassNameForm::TYPE_TELMyForm_Field_Tel::class );

Zcela nový typ pole

Nyní pojďme vytvořit novou třídu a především úplně nový typ pole. Třída může mít implementované vlastní metody pro zachytávání a validaci (a případně libovolné další metody). Důležité je, že její vlastnost $_type musí informovat o tom jaký typ formulářového pole představuje. S touto informací se totiž bude operovat i dále. Je dobré si pro typ vytvořit novou konstantu. Zde je pro ukázku použita imaginární konstanta MyForm::MY_NEW_FIELD_TYPE. namespace JetApplication;

use 
Jet\Form;
use 
Jet\Form_Field;
use 
Jet\Data_Array;

class 
MyForm_Field_NewType extends Form_Field
{
    
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    
protected string $_type MyForm::MY_NEW_FIELD_TYPE;
    
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    
    
public function catchInputData_Array $data ): void
    
{
        
//... ... ... 
    
}
    
    public function 
validate(): bool
    
{
        
//... ... ...
    
}
    
    public function 
getRequiredErrorCodes(): array
    {
        
//... ...
    
}
}

Třídu tedy máme. Ale ještě je nutné udělat několik věcí:

  • Zaregistrovat nový typ / novou třídu do továrny formuláře. (jinak by typ nemohl být použit například pro automaticky generované formuláře).
  • Zaregistrovat jaké renderery bude pro nový typ pole použit.
  • Zaregistrovat jaké view skripty budou pro daný typ použity.

Registrace typu do továrny

Registraci typu do továrny provedeme takto: use Jet\Factory_Form;

Factory_Form::setFieldClassNameMyForm::MY_NEW_FIELD_TYPEMyForm_Field_NewType::class );

POZOR! Volání továren je nutné umístit do inicializace aplikace. Tedy do skriptu ~/application/Init/Factory.php.

Registrace rendererů

Nyní je nutné továrně říct jaké renderery budou pro nový typ pole použity.

Opět budeme pracovat s továrnou, tedy ve skriptu ~/application/Init/Factory.php

Kompletní volání může mít tuto podobu: Factory_Form::setRendererFieldClassNameMyForm::MY_NEW_FIELD_TYPE'field'Form_Renderer_Field::class );
Factory_Form::setRendererFieldClassNameMyForm::MY_NEW_FIELD_TYPE'container',Form_Renderer_Field_Container::class );
Factory_Form::setRendererFieldClassNameMyForm::MY_NEW_FIELD_TYPE'error'Form_Renderer_Field_Error::class );
Factory_Form::setRendererFieldClassNameMyForm::MY_NEW_FIELD_TYPE'help'Form_Renderer_Field_Help::class );
Factory_Form::setRendererFieldClassNameMyForm::MY_NEW_FIELD_TYPE'input'Form_Renderer_Field_Input_Common::class );
Factory_Form::setRendererFieldClassNameMyForm::MY_NEW_FIELD_TYPE'label'Form_Renderer_Field_Label::class );
Factory_Form::setRendererFieldClassNameMyForm::MY_NEW_FIELD_TYPE'row'Form_Renderer_Field_Row::class );
Uff ... To je ale poněkud zdlouhavé volání. Ovšem je dobré si jej pro představu a úplnost ukázat.

Ukažme si ale praktičtější volání, která nahradí vše co jsme si do teď ukázali a provede vše potřebné. Factory_Form::registerNewFieldType(
    
field_typeMyForm::MY_NEW_FIELD_TYPE,
    
field_class_nameMyForm_Field_NewType::class,
    
renderers: [
        
'input' => MyForm_Renderer_Field_Input_Special::class
    ] 
);
Tento kus kódu provede vše potřebné - takto se reálně a jednoduše registruje nový typ. Jiná volání nejsou nutná! Tato metoda zaregistruje třídu i renderery pro nový typ. Všimněte si prosím, že v seznamů elementů a rendererů je uveden pouze element input. Pokud chcete pro ostatní elementy použít výchozí renderery, tak není nutné je uvádět a budou doplněny výchozí hodnoty.

Záměrně jsme si ukázali oba způsoby, i když praktičtější je určitě ten druhý.

Registrace view skriptů

Poslední co nám zbývá je říct systému jaké výchozí view skripty bude nový typ pole mít. To musíme dát vědět systémové konfiguraci.

Pro pořádek je dobré udělat to také ve skriptu ~/application/Init/Factory.php

Princip je stejný jako u registrace rendererů a také je možné použít volání několika metod pro každé view zvlášť, ale tím vás již zde trápit nebudu a rovnou si ukažme optimální způsob jak to udělat: SysConf_Jet_Form_DefaultViews::registerNewFieldType(
    
field_typeMyForm::MY_NEW_FIELD_TYPE,
    
views: [
        
'input' => 'field/input/my-special'
        'label' 
=> 'field/label-my-special'
    
]
);
Jak je vidět, tak i zde není nutné vyjmenovávat všechna view, ale pouze tak, která chcete mít nastavena jinak než jsou výchozí hodnoty systému.

Tedy celá registrace nového typu má ve finále tuto podobu: namespace JetApplication;

use 
Jet\Factory_Form;
use 
Jet\SysConf_Jet_Form_DefaultViews;

Factory_Form::registerNewFieldType(
    
field_typeMyForm::MY_NEW_FIELD_TYPE,
    
field_class_nameMyForm_Field_NewType::class,
    
renderers: [
        
'input' => MyForm_Renderer_Field_Input_Special::class
    ]
);

SysConf_Jet_Form_DefaultViews::registerNewFieldType(
    
field_typeMyForm::MY_NEW_FIELD_TYPE,
    
views: [
        
'input' => 'field/input/my-special'
    
]
);

Nový parametr vašeho formulářového pole

Obecný princip vytvoření nového typu pole již znáte, ale vraťme se ještě jednou na začátek. Uvedený příklad zatím počítal pouze s tím, že budete mít vlastní implementaci zachycení dat a validace.

Ale to u složitějších typů polí zdaleka nemusí stačit. V reálném světě budete potřebovat aby nový typ pole měl i své parametry. Podobně jako u číselných typů lze určit rozmezí od - do, u souborů povolené typy nahrávaných souborů a tak dále. Viz typy formulářových polí.

V podstatě je to jednoduché. Prostě přidáte třídě představující typ formulářového pole potřebnou vlastnost, getter a setter a pochopitelně implementujete logiku použití daného parametru - zejména při validaci. Ano, takto to stačí a bude to fungovat.

Ovšem pokud jste si již zkoušeli Jet Studio, tak jste nalezli nástroj na mapování formulářů na třídy. A pokud budete chtít aby tento nástroj znal i váš nový typ formulářového pole, tak jej musíte správně zaregistrovat. Ale nejen to, musíte i definovat parametry vašeho nového pole. Tak aby například Jet Studio poznalo že se jedná o parametr formuláře a umělo s ním pracovat (tedy aby bylo možné "naklikávat" i váš nový vstupní element).

Jak to udělat? Dát vlastnosti, která představuje nový parametr, příslušné atributy. Rovnou si ukažme reálný příklad přímo z Jet. Tento trait se používát pro číselná formulářová pole, kde může figurovat rozsah platných číselných hodnot: namespace Jet;

trait 
Form_Field_Part_NumberRangeInt_Trait
{
    
    #[
Form_Definition_FieldOption(
        
typeForm_Definition_FieldOption::TYPE_INT,
        
label'Minimal value',
        
getter'getMinValue',
        
setter'setMinValue',
    )]
    protected ?
int $min_value null;
    
    #[
Form_Definition_FieldOption(
        
typeForm_Definition_FieldOption::TYPE_INT,
        
label'Maximal value',
        
getter'getMaxValue',
        
setter'setMaxValue',
    )]
    protected ?
int $max_value null;
    
    #[
Form_Definition_FieldOption(
        
typeForm_Definition_FieldOption::TYPE_INT,
        
label'Step',
        
getter'getStep',
        
setter'setStep',
    )]
    protected ?
int $step null;

    
// ... ... ...
}

Jak vidíte, tak k definici slouží atributy a je to poměrně triviální definice.

Parametry definice

Parametr Význam
type O jaký typ se jedná.
Seznam typů viz dále.
label Popis parametru. Popis je určen pro nástroj jako je Jet Studio.
setter Název metody - setteru v rámci třídy představující formulářové pole, pomocí kterého lze parametr nastavit.
getter Název metody - getteru v rámci třídy představující formulářové pole, pomocí kterého lze zjistit nastavenou hodnotu parametru.

Typy parametrů

Typ Význam
Form_Definition_FieldOption::TYPE_STRING Hodnota typu string
Form_Definition_FieldOption::TYPE_INT Hodnota typu int
Form_Definition_FieldOption::TYPE_FLOAT Hodnota typu float
Form_Definition_FieldOption::TYPE_BOOL Hodnota typu bool
Form_Definition_FieldOption::TYPE_CALLABLE Volání - fakticky pole o dvou pozicích. První pozice (index 0) může být:
  • self::class
    jedná se pak o statické volání sebe sama.
  • řetězec 'this'
    jedná se o volání sebe sama přes $this.
  • Konkrétní název třídy (buď jako řetězec, nebo jako NameSpace\Class:class).
Form_Definition_FieldOption::TYPE_ARRAY Prosté pole.
Form_Definition_FieldOption::TYPE_ASSOC_ARRAY Asociované pole.
Předchozí kapitola
Jet\Form_Definition_SubForms
Další kapitola
Jet\Form_Definition_FieldOption