Formular z presenteru presunout do vlastniho souboru

- Skywalk3r
- Člen | 8
Ahoj, mám v presenteru funkční formulář na přidávání produktů, ale potřebuji tam přidat další formulář a už by presenter nebyl tak přehledný.
Mám to zatím takto
presenter
public function createComponentFormProductAdd(){
return new \FormProductAdd($this->database);
}
app/forms/FormProductAdd.php
<?php
use Nette\Forms\Form;
class FormProductAdd extends Nette\Object {
private $database;
public function __construct(Nette\Database\Context $database)
{
$this->database = $database;
$this->createForm();
}
public function createForm(){
$form = new Nette\Application\UI\Form;
$form->addText('name', 'Název:')
->setRequired('Zadejte prosím jméno');
...
$form->addSubmit('send', 'Přidat');
$form->onSuccess[] = $this->process;
return $form;
}
public function process($form){
try {
...
$this->flashMessage('Produkt vložen.');
/* $this->redirect('this'); */
} catch(Exception $e) {
$form->addError('Při vkládání se vyskytla chyba.'/*.$e*/);
if ($e instanceof \Nette\Application\AbortException) {
throw $e;
}
}
}
}
Ale hlásí mi to chybu
Nette\UnexpectedValueException
Method App\BProductsPresenter::createComponentFormProductAdd() did not return or create the desired component.
Pročpak ? :-)
Tohle řešení mi přijde dobré v tom, že z toho můžu rovnou udělat továrničku pokud bych to chtěl v app použít vícekrát.
Editoval Skywalk3r (16. 2. 2014 16:02)

- Šaman
- Člen | 2668
Ty ale v té továrničce v presenteru vytváříš instanci typu
Nette\Object, takže ti to skutečně nevytvoří komponentu (což
metoda createComponentXxx zjistí a reklamuje).
Ukázku funkčního řešení najdeš třeba tady.
Ty tam navíc budeš mít samozřejmě i ten konstruktor kvůli předání
závislosti na db.
Pokud bys nechtěl tvořit komponentu, tak bys musel mít ten formulář jako
poděděný Form a nebo, to je to, co jsi možná chtěl na
začátku vytvořit si továrničku, ale pak v presenteru jen nevytvářej
tovární třídu, ale zavolej její konkrétní metodu, která ti vrátí
nakonfigurovanou instanci Form.
Editoval Šaman (16. 2. 2014 16:14)

- Skywalk3r
- Člen | 8
Šaman napsal(a):
Ty ale v té továrničce v presenteru vytváříš instanci typu
Nette\Object, takže ti to skutečně nevytvoří komponentu (což metoda createComponentXxx zjistí a reklamuje).Ukázku funkčního řešení najdeš třeba tady.
Ty tam navíc budeš mít samozřejmě i ten konstruktor kvůli předání závislosti na db.Pokud bys nechtěl tvořit komponentu, tak bys musel mít ten formulář jako poděděný
Forma nebo, to je to, co jsi možná chtěl na začátku vytvořit si továrničku, ale pak v presenteru jen nevytvářej tovární třídu, ale zavolej její konkrétní metodu, která ti vrátí nakonfigurovanou instanciForm.
Děkuji, teď už mi to funguje až na jednu drobnost.. pokud chci vykreslit ten formulář pomocí výchozího formátování.. tak na {$form->render()} mi to spadne že $form neni definované ? :-)
Jinak mi šlo pouze o přesun kódu, což by vlastně šlo vyřešit
includem což by ale bylo nehezké :-)
Není mi ale jasná jedna věc.. proč ta metoda createComponent (alias
továrnička) kontroluje jestli vypisuje objekt Control když
zde https://forum.nette.org/…nebo-tovarna do ní jde Nette/Object
a zde https://doc.nette.org/cs/forms#… do ní jde UI/Form
a ani u jednoho to nespadne ?
Pro moje účely bude asi nejlepší ta varianta s UI/Forms, protože tam nemusím vytvářet speciální šablonu pro tu Componentu.. za ten odkaz díky dá se z toho dobře naučit jak vytvářet komponenty :-)

- Skywalk3r
- Člen | 8
Tak jsem se pokusil podle toho UI/Form navodu a hazi to nejakou chybu ale netusim co s tim.
<?php
use Nette\Application\UI\Form;
class FormProductAdd extends Nette\Application\UI\Form {
private $database;
public function __construct(Nette\Database\Context $database)
{
$this->database = $database;
return $this->createForm();
}
public function createForm(){
$form = new Nette\Application\UI\Form;
$form->addText('name', 'Název:')
->setRequired('Zadejte prosím jméno');
...
$form->addSubmit('send', 'Přidat');
$form->onSuccess[] = $this->process;
return $form;
}
public function process($form){
$this->flashMessage('Produkt vložen.');
$this->redirect('this');
}
}
a presenter
public function createComponentFormProductAdd(){
return new \FormProductAdd($this->database);
}
pricemz mi to hazi chybu
Notice
Trying to get property of non-object
v souboru File: …\vendor\nette\nette\Nette\Forms\Form.php:206
Editoval Skywalk3r (16. 2. 2014 17:11)

- Milo
- Nette Core | 1283
Nevoláš konstruktor předka. Btw. hezké čtení https://doc.nette.org/…tion/factory

- Šaman
- Člen | 2668
Jestli chceš jenom přesunout továrničku a obslužnou metodu, tak:
- Vytvoř si FooFormFactory. Ta bude mít metodu (často
create()), která vytvoří, nakonfiguruje a vrátí hotový formulář. - Tuto si zaregistruj jako službu a normálně ji předej (injectuj) do
presenteru (řekněme do proměnné
fooFormFactory). - V metodě
createComponentFoo()pak zavoláš něco jakoreturn $this->fooFormFactory->create();.
Jinak ta moje ukázka vytváří komponentu s formulářem, nikoliv samotný formulář. Proto ti nefungoval renderer.