Vlastni Presenter pro kazdou akci

markoska
Člen | 12
+
+1
-

Zdravim,

mam presenter pro (vicemene) kazdou DB tabulku (EmailPresenter, PhonePresenter, PersonPresenter, …) a v nich akce renderDefault(), renderShow(), renderEdit(), …

Problem je, ze zakaznik si preje mit jeden veliky formular, kde zada nejenom udaje o osobe, ale i veskere jeji adresy, telefony, ucty, sluzby… Takze mi PersonPresenter zacal hrozive bobtnat

Vsiml jsem si, ze v dokumentaci radite vytvaret presentery s jedinou akci. To stejne radi i na itnetwork. Tak jsem si presenter rozsekal na PersonShowPresenter, PersonEditPresenter, …

Problem ale je, ze ted mam createComponentPersonForm() jak v PersonCreatePresenter tak v PersonEditPresenter

Napadlo me presunout formular do modelu Person, nevim ale, jestli tam vubec patri, zvlast kdyz obsahuje policka i jinych modelu.

Mate prosim nekdo toto vyresene?

Dekuji za nakopnuti spravnym smerem

Editoval markoska (2. 4. 2022 10:23)

Pepino
Člen | 249
+
+3
-

@markoska co vytvořit třídu PersonForm?

markoska
Člen | 12
+
0
-

Pepino napsal(a):

@markoska co vytvořit třídu PersonForm?

Aha! A tu si pres DI pridat do Create/Edit Presenteru a v ni mit jak createComponentPersonForm() tak i personFormSucceeded() ?

Vida, to me vubec nenapadlo. Diky moc!

Marek Znojil
Člen | 76
+
+3
-

Zde máš popsány různé způsoby znovu použitelnosti formulářů:
https://doc.nette.org/…s/form-reuse

markoska
Člen | 12
+
0
-

Marek Znojil napsal(a):

Zde máš popsány různé způsoby znovu použitelnosti formulářů:
https://doc.nette.org/…s/form-reuse

Jeste bych se s dovolenim zeptal…

Vytvoril jsem si tedy tovarnu, presne podle toho navodu „form-reuse“, presunul do ni jak metodu, ktera formular vytvori, tak i metodu, ktera formular zpracuje.

V presenteru mi zustalo akorat:

protected function createComponentPersonForm(): Form
{
    $form = $this->PersonFormFactory->create();
    $form->onSuccess[] = function (Form $form) {
        $this->redirect('this');
    };
    return $form;
}

Akorat, ze kdyz tu personu edituji, tak potrebuji nejak predat jeji ID. Predtim jsem mel v Presenteru toto:

public function personFormSucceeded(Form $form, \stdClass $values): void
{
    $values->id = $this->getParameter('id');
    try
    {
        $person = $this->Person->save($values);
    ....

Ted kdyz mam zpracovani formulare v tovarne, tak mi to samozrejme hlasi chybu:

Call to undefined method app\Modules\Is\Factory\PersonFormFactory::getParameter()

Jak si tam ted predam ID, ktere se mi vraci jako parametr z URL?

Dekuji

Pepino
Člen | 249
+
0
-

V actionDefault můžeš id tomu fomuláři nasetovat. $this[personForm]->personId = $id;

Samozřejmě v té třídě si vytvoř public $personId

markoska
Člen | 12
+
0
-

Pepino napsal(a):

V actionDefault můžeš id tomu fomuláři nasetovat. $this[personForm]->personId = $id;

Samozřejmě v té třídě si vytvoř public $personId

Ja se omlouvam, ale jde mi z toho hlava trochu kolem. Predesilam, ze i samotne OOP je pro mne dosud terra incognita

Kde se mi v presenteru vezme:

$this[personForm]

kdyz ho nikde nenastavuji?

A tenhle kod prosim udela co?

$form->onSuccess[] = function (Form $form) {
    $this->redirect('this');
};

Resp. kam mam ted vrazit nasledujici kod, ktery predtim take patril do Presenteru?

$this->flashMessage('Osoba byla úspěšně uložena.', 'success');
$this->redirect('PersonShow:default', $person->id);

Jeste jednou diky a uz dam dneska opravdu pokoj

Editoval markoska (2. 4. 2022 13:25)

Marek Bartoš
Nette Blogger | 1165
+
+1
-

$this['personForm'] funguje díky tomu, že Component (ze které Control a Presenter dědí) implementuje ArrayAccess. Díky tomu lze přistupovat k objektu jako k poli. V Nette komponentách je to implementované tak, že při prvním přístupu k $this['personForm'] se zavolá createComponent('personForm') a z ní se v komponentě zavolá metoda createComponentPersonForm()

Při úspěšném odeslání formuláře se provede redirect na aktuální stránku – brání tak znovuodeslání formuláře při stisknutí F5.

$form->onSuccess[] = function (Form $form) {
    $this->redirect('this');
};

Resp. kam mam ted vrazit nasledujici kod, ktery predtim take patril do Presenteru?

Ideálně redirect nechat v presenteru a do komponenty si jej předat v konstruktoru pomocí anonymní funkce (callable/Closure). Tak zůstane komponenta nezávislá na konkrétním presenteru. Případně lze na prasáka zavolat $this->getPresenter()->redirect()

Marek Znojil
Člen | 76
+
+1
-

Na předávání závislostí do komponent se můžeš podívat tady:
https://doc.nette.org/…n/components#…

Taky je fajn brát v potaz zmínku od @MarekBartoš. Je lepší nechávat události co se má dít po odeslání formuláře na prezenterech.

Pokud budeš mít formulář, který nedědí Nette\Application\UI\Control nebo nepoužívá traitu Nette\SmartObject, můžeš callbacky událostí po odeslání předávat do metody, kterou navrací metoda createComponent<Name>() v prezenteru.

Viz:
https://github.com/…mFactory.php#L28
https://github.com/…resenter.php#L34