Dynamicky tvořené formuláře
- be
- Člen | 3
Zdravím, chtěl bych se zeptat více ze široka, snad položit dvě otázky najednou.
První je jakým způsobem lze korektně a s cestou nejmenšího odporu implementovat do Nette (nebo s prostě s Nette) dynamické formuláře. Přesněji, jaké jsou obecně možnosti zpracování nebo například konkrétní rozšíření. Zde na fóru jsem naše několik otázek, ale nevím, jestli jsou vlastně aktuální odpovědi ještě aktuální.
Druhá otázka souvisí s mým konkrétním případem, mám relativně jednoduchý formulář, do kterého bych měl mít možnost vložit opakující se inputy na několika místech. Použil jsem následující rozšíření: https://github.com/…master/.docs#…, kde jsem se snažil použít první příklad ze sekce „Usage“ což mi umožnilo načítat tyto položky jako samostatný formulář. Místo samostatného formuláře potřebuji načítat dynamické formuláře na několik místech, v jednom formuláři. Jestli tomu rozumím správně, potřeboval bych načítat dynamické formuláře do konteinerů daného formuláře.
Rád obratem odpovím na jakékoli doplňující otázky.
- Michal Kumžák
- Člen | 106
Zdar
Form multiplier ti vytváří kopie jedné komponenty, u tebe formuláře. V dokumentaci je ukázaná i praktická ukázka.
Co si představuješ pod pojmem dynamické formuláře? Prosím o konkrétní příklad.
Editoval Michal Kumžák (5. 8. 2021 12:30)
- be
- Člen | 3
Michal Kumžák napsal(a):
Zdar
Form multiplier ti vytváří kopie jedné komponenty, u tebe formuláře. V dokumentaci je ukázaná i praktická ukázka.
Co si představuješ pod pojmem dynamické formuláře? Prosím o konkrétní příklad.
Snad jsem pojem „dynamické formuláře“ pochopil správně, popřípadě se omlouvám. Myslím tím formuláře/inputy/části formuláře, které se v průběhu editace uživatelem mohou přidávat nebo odebírat, v tomto úhlu pohledu, aby se buď množily, nebo aby se odstranily. Uživatel tak navštíví tvorbu nového záznamu a v tomto formuláři může konkrétní prvky takto množit či odstraňovat s tím, že na stránce bude vždy minimálně jeden tento prvek či skupina prvků například v řádku, která se bude množit.
Co jsem pochopil z dosavadních dotazů tak následující rozšíření, by
to měly zajistit:
https://github.com/…/en/index.md
https://github.com/…s-multiplier
- Martk
- Člen | 661
Nemůžeš vložit jeden celý formulář do druhého formuláře, ale můžeš vložit část formuláře do druhého, aby se zachovala znovupoužitelnost. Asi takhle:
public function createProductPart(Container $container, Form $form): void
{
$container->addText('name', 'Product name');
$container->addInteger('price', 'Product price');
// eventy
$form->onSuccess[] = function () use ($container): void {
bdump($container->getValues());
};
}
public function createFormWithMultiplier(): Form
{
$form = new Form();
$products = $form->addMultiplier('products', fn (Container $container) => $this->createProductPart($container, $form));
$products->addCreateButton('Add product');
$products->addRemoveButton('Remove product');
return $form;
}
public function createProductForm(): Form
{
$form = new Form();
$this->createProductPart($form, $form);
return $form;
}
Editoval Martk (5. 8. 2021 13:57)
- be
- Člen | 3
Martk napsal(a):
Nemůžeš vložit jeden celý formulář do druhého formuláře, ale můžeš vložit část formuláře do druhého, aby se zachovala znovupoužitelnost. Asi takhle:
public function createProductPart(Container $container, Form $form): void { $container->addText('name', 'Product name'); $container->addInteger('price', 'Product price'); // eventy $form->onSuccess[] = function () use ($container): void { bdump($container->getValues()); }; } public function createFormWithMultiplier(): Form { $form = new Form(); $products = $form->addMultiplier('products', fn (Container $container) => $this->createProductPart($container, $form)); $products->addCreateButton('Add product'); $products->addRemoveButton('Remove product'); return $form; } public function createProductForm(): Form { $form = new Form(); $this->createProductPart($form, $form); return $form; }
Děkuji za radu. S tím formulářem ve formuláři jsem se pravděpodobně upsal, myslel jsem nějakou jeho část, například ten konteiner (jestli to píšu správně).
Takže zde(createProductForm()) nebude createComponentProductForm? Po použití v šabloně {control ProductForm}, {control productForm} nebo {form ProductForm}, {form productForm} totž laděnka vypíše hlášku: Component with name ‚productForm‘ does not exist, když přidám za „create“, „createComponent“ (createComponentProductForm()), vypíše se chybová hláška: což řeším přidáním nahoru do souboru v presenteru: use Nette\Application\UI\Form, po obnovení to vede k chybě: Argument 1 passed to App\Presenters\HomepagePresenter::createProductPart() must be an instance of App\Presenters\Container, instance of Nette\Application\UI\Form given, called in cesta. Jsem opravdu začátečník, jakým způsobem je možné tuto chybu prosím vyřešit?
Ještě jednou děkuju.
public function createProductForm(): Form
{
$form = new Form();$this->createProductPart($form, $form);
return $form;
}
Editoval be (6. 8. 2021 8:46)
- Martk
- Člen | 661
To jsou jen metody pro továrnu tzn. z těch metod uděláš továrny
class ProductFormPartsFactory {
public function createProductPart(Container $container, Form $form): void
{
$container->addText('name', 'Product name');
$container->addInteger('price', 'Product price');
// eventy
$form->onSuccess[] = function () use ($container): void {
bdump($container->getValues());
};
}
}
class ProductFormFactory {
public function __construct(
private ProductFormPartsFactory $productFormPartsFactory,
// muzes injectnou třeba více partů
)
{
}
public function createFormWithMultiplier(): Form
{
$form = new Form();
$products = $form->addMultiplier('products', fn (Container $container) => $this->productFormPartsFactory->createProductPart($container, $form));
$products->addCreateButton('Add product');
$products->addRemoveButton('Remove product');
return $form;
}
public function createProductForm(): Form
{
$form = new Form();
$this->productFormPartsFactory->createProductPart($form, $form);
return $form;
}
}
a registruješ jako služby do neon
services:
- ProductFormPartsFactory
- ProductFormFactory
A v presenteru pak:
class ProductPresenter extends Presenter {
public function __construct(
private ProductFormFactory $productFormFactory,
)
{
parent::__construct();
}
protected function createComponentProductForm() {
return $this->productFormFactory->createProductForm();
}
protected function createComponentProductMultiplierForm() {
return $this->productFormFactory->createFormWithMultiplier();
}
}