Vykreslení formuláře v jiném presenteru
- zener
- Člen | 17
Tvořím redakční systém, kde mám různé „moduly“ (fotogalegie, články…) a chci k nim mít možnost vkládat komentáře.
Vytvořil jsem si nový modul „komentáře“, který includuji do @layout.phtml. Problém nastává, když v komentářích (např. Komentare.vypis.phtml) použiju továrničku na formulář, něco jako {control pridat}. Logicky to nefunguje, neboť to hledá v aktuálním presenteru (třeba fotogalerie).
Můj dotaz tedy zní… Je možné nějak vkládát továrničku z jiného presenteru? Něco jako {control Fotogalerie:pridat}.
Děkuji.
- petr.pavel
- Člen | 535
Rád bych tohle téma znovu otevřel.
Chápu, proč někdo doporučuje definovat formulář i obslužné funkce v předkovi, a pro některé situace to může být čisté řešení. Když ale budu mít vyhledávací formuláře zákazníků, dodavatelů, materiálu… na jednotlivých stránkách těchto entit, ale současně je budu chtít ještě zopakovat na stránce hlavního velínu, tak by se mi logika vyhledávání v jednotlivých entitách slila ve společném předku. To přece není správné. Jasně, že skutečné vyhledávání bude v modelu, ale i tak.
Asi by šlo definovat pro každý z formulářů samostatnou komponentu, ale to je jako jít na mravence s kanónem. Jestli mi někdo předložíte celé řešení, které nezabírá dvě stránky, tak jsem ochoten připustit opak.
Úplně nejlepší by mi přišlo mít definovaný formulář v presenteru
entity a z velínu ho jen nějak použít. Zenerovo vysněné {control
Fotogalerie:pridat} by bylo super, ale není implementované.
Jinak to sice jde, ale je to prasárna.
Nejbližší lepší postup podle mě je definovat formuláře na úplně jiném místě, ale to pak stejně musíte řešit, kde se budou zpracovávat po odeslání.
Teoreticky by šlo formulář zachycovat v presenteru velínu a přesměrovávat hodnoty jinam, ale to je extra krok navíc.
Osobně se mi zatím nejvíc líbí formulář rovnou odesílat do presenteru/akce, která ho má zpracovat. Probírá se to tady, ale téma pak uklouzlo jinam. Takže bych to rád nějak shrnul a jestli nebudete nikdo proti, připsal bych to i do dokumentace.
Formulář definujte podle příkladu v dokumentaci, ale v továrničce pak místo přidání callbacku do $form->onSuccess zavolejte následující setAction(). Odesílá do presenteru Search, akce default.
$url = $this->link('Search:default', array('do' => $name.self::NAME_SEPARATOR.'submit'));
$form->setAction($url);
Nette Framework 2.0-beta (revision f38d86f released on 2011–08–24)
Editoval petr.pavel (29. 8. 2011 10:43)
- 22
- Člen | 1478
asi bych si udělal vlastní komponentu, která bude obecně umět sestavit vyhledavácí formulář a pak si jen podle potřeby zavolám buď komponentu, pokud rozšiřuji stávajíci vyhledávací form nebo udělám novou komponentu, pokud je form úplně jiný:
public function createComponentSearch()
{
$search = new Search();
$search->add('city', 'Město');
return $search;
}
//rozšíření
public function createComponentSearchMore()
{
$search = $this->getComponent('search');
$search->add('district', 'Kraj');
return $search;
}
no a vždycky mi to vyhledá položky v DB, co vypadnou z formu a do modelu pošlu jen proměnnou $filter
Editoval 22 (29. 8. 2011 11:02)
- petr.pavel
- Člen | 535
@22: Můžeš, prosím, doplnit kód, kterým bys zachytával odeslaný formulář? Nebo jestli je někde k dispozici kompletní řešení, mohl bys poslat odkaz?
- petr.pavel
- Člen | 535
Asi používám blbou terminologii. Při nejjednodušší implementaci formuláře v Nette se vyrobí v createComponentMujFormular() a pomocí třeba $form->onSuccess[] = callback($this, ‚mujFormularOdeslan‘); se pak zpracuje v tom samém presenteru v metodě mujFormularOdeslan(). Tomu říkám zachytit odeslaný formulář – odeslané hodnoty zpracuje mujFormularOdeslan().
Nevím, kde a jak by se v případě komponenty tohle odehrálo a jak by to celé vypadalo. Bavíme se v kontextu tohoto vlákna, ne obecně.
- petr.pavel
- Člen | 535
Přeci jen bych někoho poprosil o kompletní kód:
- úplnou definici komponenty, do formuláře stačí jediná položka + tlačítko
- různé vykreslení ve dvou šablonách; třeba vynechat některé položky, vykreslit vedle sebe, místo v tabulce…
- použití ve dvou presenterech
- zpracování odeslaných hodnot formuláře pouze na jednom místě, tedy asi v komponentě; stačí obdoba dump($form->getValues());
A ještě otázka: jestli tomu dobře rozumím, kompomentu vždycky musím renderovat sám. Nemůžu tedy ji vykreslit v šabloně presenteru/akce pomocí makra {form …}. Jestli je to tak, tak bych mohl bod (2) splnit pouze tak, že bych definoval víc renderovacích metod a volal je ze šablony přes {control mujFormular:nazevVzhledu}.
- Patrik Votoček
- Člen | 2221
tak ještě jendou a lépe:
class MySuperForm extends \Nette\Application\UI\Form
{
/** @var mixed */
private $modelService;
/** @var \Nette\Application\UI\Link */
private $successLink;
public function __construct($modelService)
{
parent::__construct();
$this->modelService = $modelService;
$this->setup();
}
protected fucntion setup()
{
$this->addTextArea('text', "Text");
$this->addSubmit('sub', "Save");
$this->onSuccess[] = callback($this, 'process');
}
public function process()
{
try {
$this->modelService->create($form->values);
} catch (ModelException $e) {
foreach ($e->errors as $name => $messages) {
foreach ($messages as $message) {
$this[$name]->addError($message);
}
}
}
}
}
class ArticlePresenter extends BasePresenter
{
protected function createComponentMyForm()
{
return new MyForm($this->context->articleModelService);
}
}
class GalleryPresenter extends BasePresenter
{
protected function createComponentMyForm()
{
$form = new MySuperForm($this->context->galleryModelService);
$form->addMultileFile('images', "Images");
return $form;
}
}
{* Gallery/default.latte *}
{control myForm}
{* Article/default.latte *}
{form myForm}
{label text /}{input text}
{input sub}
{/form}
- petr.pavel
- Člen | 535
Super, díky Patriku! Netušil jsem, že i v případě formuláře (potomka AppForm) můžu zpracovávat jeho odeslání přímo v jeho třídě.
Upřímně, stránka o komponentách má dost velké mezery. Nevyplynulo mi z ní, že by se potomek AppForm taky nazýval komponenta, v příkladech se dědí jen z Control. Jasně že se tam každou chvíli mluví o formulářích, ale myslel jsem, že to jsou formuláře definované uvnitř nějakého většího celku, který se jmenuje komponenta.
Navíc tvrzení, že se o vykreslení musíme postarat sami v metodě render. Jak to teď chápu, tak můžeme, ale nemusíme.
Pořád ještě nejsem v tomhle dost silný v kramflecích, takže si zdaleka netroufám dokumentaci komponent upravovat sám. Určitě by to ale chtělo. Komponenty do hloubky bych určitě vyčlenil do zvláštní stránky. Je to na mě strašně složité, budu rád, když někdy pochopím tu první část a stránka je už takhle moc dlouhá.
Ještě si ten tvůj kód vyzkouším a doplním pak něco k formulářům v presenteru.
P.S. Tady na fóru nefunguje odkaz do dokumentace dle Jak
zapisovat kód v tomto fóru. Myslím tím [[doc:debugging]]
i
[[Laděnky | doc:debugging]]
. Mohl by to někdo opravit,
prosím?
- 22
- Člen | 1478
Komponenty jsou všechno, co má něco společného s https://api.nette.org/…mponent.html
Presenter je taky komponenta a každý Control je taky komponenta…
- petr.pavel
- Člen | 535
Ještě otázka k Patrikově kódu, nešlo by se nějak obejít bez createComponent…() v presenterech, které ten můj formulář používají v šabloně?
Ve tvém příkladu se ještě doplňují kolonky a předává model, takže createComponent…() potřebuji. Díky, že's to do příkladu uvedl. Kdyby mi ale stačil přesně ten stejný formulář (strukturou) a stejné zpracování, šlo by se nějak obejít bez createComponent…()? Rád bych i nadále vykresloval pomocí makra {form …}
- Patrik Votoček
- Člen | 2221
petr.pavel napsal(a):
Navíc tvrzení, že se o vykreslení musíme postarat sami v metodě render. Jak to teď chápu, tak můžeme, ale nemusíme.
U klasických komponent musíme. Ber to tak že Nette\Application\UI\Form je chytřejší base komponenta pro tvorbu formulářů, kterou můžeš rovnou instancovat.
… Určitě by to ale chtělo. Komponenty do hloubky bych určitě vyčlenil do zvláštní stránky.
Tohle je už moc „hluboké“ takovéhle specifické věci patří do wiki resp. Kuchařky.
P.S. Tady na fóru nefunguje odkaz do dokumentace dle Jak zapisovat kód v tomto fóru. Myslím tím
[[doc:debugging]]
i[[Laděnky | doc:debugging]]
. Mohl by to někdo opravit, prosím?
Co ti na tom nefunguje? mě to funguje.
Ještě otázka k Patrikově kódu, nešlo by se nějak obejít bez createComponent…() v presenterech, které ten můj formulář používají v šabloně?
Můžeš si přetížit Nette\ComponentModel\Container::createComponent() a zautomatizovat to. Nebo si hodit příslušnou továrničku do BasePresenteru.
- petr.pavel
- Člen | 535
Nefunkční odkazy do dokumentace:
Když zkopíruji příklad z návodu
získám něco jiného, než co uvádí návod:
A teď si najeď myší na ty odkazy. Není to platná adresa, ale „doc:cs:debugging“.
Přetížení createComponent(): Jo! To je výborný nápad, díky.
- Filip Procházka
- Moderator | 4668
Přetížení createComponent
může být cestou
do pekel, pokud s tím komponenty nepočítají.