[help needed] Jak přidat generika do formulářů?
- David Grudl
- Nette Core | 8227
Myslím, že by mohlo být fajn pomocí generik definovat správný typ pro
parametr $value
v metodě setValue()
/
setDefaultValue()
a návratovou hodnotu getValue()
.
Mohlo by to fungovat třeba nějak takto (viz anotace @return
):
class Container
{
/**
* @return Controls\TextInput<string>
*/
public function addText(string $name, $label = null): Controls\TextInput
{
return $this[$name] = (new Controls\TextInput($label, $maxLength))
->setHtmlAttribute('size', $cols);
}
/**
* @return Controls\TextInput<int>
*/
public function addInteger(string $name, $label = null): Controls\TextInput
{
return $this[$name] = (new Controls\TextInput($label))
->setNullable()
->addRule(Form::Integer);
}
/**
* @return Controls\TextInput<float>
*/
public function addFloat(string $name, $label = null): Controls\TextInput
{
return $this[$name] = (new Controls\TextInput($label))
->setNullable()
->setHtmlType('number')
->setHtmlAttribute('step', 'any')
->addRule(Form::Float);
}
Zároveň u tříd jako Checkbox
by definice generika mohla
být přímo součástí třídy, aby nebylo nutné uvádět v tomto případě
anotaci @return Checkbox<bool>
public function addCheckbox(string $name, $caption = null): Controls\Checkbox
{
return $this[$name] = new Controls\Checkbox($caption);
}
Zhostíte se toho někdo a pošlete PR?
- Marek Bartoš
- Nette Blogger | 1274
@DavidGrudl Zkouším to teď implementovat. V ideálním případě by generika měla být kompletně součástí třídy a vně by je uživatel nemusel definovat vůbec.
Mohl bys mi sepsat seznam možných typů hodnot pro všechny prvky?
Pokud se liší možné hodnoty v set a get kvůli transformacím (např.
HiddenField), tak i včetně toho.
Typ by se též měl změnit podle toho, zda je prvek nullable, disabled (u toho afaik záleží, zda se první volá setValue() nebo setDisabled()?) nebo je volání v podmínce $control->isFilled(). Teoreticky by mělo být možné typy pomocí volání metod rozširovat/zužovat, ale nevím, zda znám všechny případy, kdy se typ mění.
Velký problém s generiky ale je, že se obvykle nepřistupuje k instancím prvků přímo, ale přes formulář a ten vrací jen obecné IComponent. Asi by šlo doplnit generika i do formuláře, aby typy prvků byly známé, ale takový generický typ bude obří a dobře by se s ním pracovalo pouze v rámci jedné funkce.
Co by pomohlo s typovými formuláři nejvíce by byly deklarativní, striktně typované formuláře, ale nevím, zda bych to dovedl snadno vytvořit s aktuálním interface. Posledně když jsem zkoušel udělat nadstavbu nette/security, tak z toho vzniklo orisai/auth.
// Jen rychlý, nepromyšlený example
class RegistrationForm {
#[FormField(label: "Username", validationRule: "required")]
private TextControl $username;
#[FormField(label: "Email", validationRule: "required|email")]
private EmailControl $email;
#[FormField(label: "Birthdate", validationRule: "date")]
private DateTimeControl $birthdate;
}