Formulare jako tovarnicky – vlastni vykresleni formulare nefunguje
- Ja
- Člen | 260
Zdravim,
udelal jsem si tovarnicky dle tohoto navodu:
https://doc.nette.org/…s/form-reuse
jenze kdyz se snazim vyrenderovat form rucne {form newsletterForm} …
{/form}
Jenze $form obsahuje instanci NewsletterForm tridy a ne Form, proto nejde vykreslit.
Jak to resite? Delam neco spatne?
Diky za postrceni.
- Ja
- Člen | 260
@bazo : jo dik, to by mohlo fungovat, v tuto chvili ten vlastni render probiha skrze echo $this[‚form‘]; primo v te komponente
@JanEndel :
<?php
protected function createComponentNewsletterForm()
{
$form = $this->newsletter_form_factory->create();
$form->onSuccess[] = function ($form, $status) {
// vypusteno
};
return $form;
}
?>
- Šaman
- Člen | 2668
Ten návod je dobrý, ale osvědčilo se mi důsledně rozlišovat
Form
, Control
a Factory
.
Podle názvu by ta tvoje NewsletterForm
měla extendovat
Form
, ale ona je to asi buď komponenta (pak to pojmenuj
NewsletterFormControl
) a nebo továrna (pak je to
NewsletterFormFactory
). A pokud by to byla továrna, která vrací
komponentu, pak je vhodný, i když dlouhý název
NewsletterFormControlFactory
.
Vykreslení pomocí makra {form NewsletterForm}…{/form}
funguje jen u Form
u, komponenta zase lze vykreslit pomocí
{control NewsletterFormControl}
.
Jinak osvědčilo se mi mít továrny přímo na formuláře. Komponenty
vytvářet jen tehdy, pokud stejně naformátovaný formulář budu
chtít na více místech. Pokud mu však na backendu jen přiřadím nějaký
umiverzální renderer a na frontendy ho vykresluji přímo oživením inputů
v dodaných šablonách, pak se lépe pracuje se instancí Form
,
než FormControl
.
Editoval Šaman (3. 3. 2015 22:25)
- Ja
- Člen | 260
Jj, ok diky, jako je to komponenta, ale je to z toho duvodu, abych si mohl vytvorit svuj vlastni event onSuccess[], abych odchytil, zda se email do newsletter pridal, nebo odebral. Proto je to udelano skrze tento navod. Pokud bych mel jen tovarnu, jako mam u ostatnich formu, tak se mi ten onSuccess[] nedarilo vytvorit a pouzit.
- Ja
- Člen | 260
@Šaman : heled, to onSuccess[] funguje, jen mi nejde nastavit vlastni event. Ted jsem to kratce zkoumal a prave problem je, ze pokud automaticky vytvarim form pres tovarnu, tak se mi vrati ‚Form‘, ale pokud to vytvarim skrze ten interface, tak mi to vraci ‚NewsletterForm‘, diky cemuz se dostanu k tomu svymu event handleru. Takze nejak nevim jak z toho ven.
(kazdopadne co ja vlastne jsem puvodne resil, tak bylo to, abych prave si pri odeslani/zpracovani formulare dokazal v presenteru vytahnout, co se vlastne stalo a adekvatne na to zareagovat hlaskou [email byl smazan/pridan/atd..])
- Šaman
- Člen | 2668
Jenomže jestli to správně chápu, tak NewsletterForm
není
instance Form
.
Nevím s čím máš problém a o jakých eventech vlastně mluvíš. Jestli
třeba Kdyby\Events
, tak ty zatím nepoužívám a nedokážu
poradit. Ale na normální navěšování událostí na onSubmit
kdekoliv (v továrně, komponentě i presenteru) nepotřebuješ, aby ten
Form
byla komponenta.
(Komponenta je fajn, když potřebuješ komponentu, ale když chceš jen
Form
, tak je to zbytečné obalování které může přinést
problémy.)
Ukázku máš tady: Tovární
třída na čistý formulář a její použití
v presenteru i s další navěšenou událostí.
(Jen upozorňuji, že tahle továrna dědí od Nette\Object
,
jinak by nefungoval ten zápis kde se navěšuje událost na
onSuccess
. V čistém PHP by bylo potřeba použít pole.
A taky těmi traity se asi neispiruj, dneska už je nepoužívám, zvytečně
znepřehledňují kód. Takže na aktuálních projektech si úplně obyčejně
tu továrnu injectnu.)
- Ja
- Člen | 260
@Šaman : jj, chapes to spravne
ad. eventy – jj eventy = udalosti, nemyslim kdyby/events.. myslim tim treba
napr. onSuccess[], jenze ja do toho onSuccess[] (nebo jineho vlastniho eventu)
potrebuju dostat informaci, co se s emailem stalo a nechat to probublat az do
presenteru
co se tyce tovarny, pouziti zde by melo bejt v poradku, tento form se pouziva na vice mistech v systemu… a pokazde by se mel tedy i jinak renderovat (cimz se vracime na zacatek – v soucasnosti je to komponenta dedici od ‚Control‘ (diky cemuz mi to dovoli definovat vlastni udalost – napr. onSave[], je vytvarena tovarnou a v sablone ji vykresluju skrze {control newsletterForm}.
Abych to shrnul:
- komponenta tvorena tovarnou – vraci se mi objekt NewsletterForm (tj. ta komponenta), tam si navesim svoji vlastni udalost onSave[] napr., do ktere si hodim informaci, ze newsletter byl smazan nebo pridan
- druha moznost je tedy samotna trida jakozto samotna tovarna, ktera form vraci pri pouziti metody $tovarna->create(), vraci objekt ‚Form‘, ale nejsem schopen tam navesit moji vlastni udalost onSave[].. ALE zase jde vykreslit rucne pres {form newsletterForm}{/form} :)
(snad je to nyni srozumitelne)
a teď babo raď, jak z toho ven :)
EDIT: Samane, jeste jsem koukal na ten tvuj snippet z projektu todolist na githubu, presne takle normalne formy vytvarim, coz je ten zpusob b. co jsem popsal o par radku vyse
Editoval Ja (4. 3. 2015 10:48)
- Šaman
- Člen | 2668
Pořád nechápu v čem je problém
Jediné, so mě u tebe zarazilo je ta proměnná $status. Jestli to není tím, tak ukaž asi celý kód a co ti to hlásí za chybu. Musí na to jít navěsit události jak z továrny, tak z komponenty/presenteru, běžně to tak používám.
<?php
protected function createComponentNewsletterForm()
{
$form = $this->newsletter_form_factory->create();
$form->onSuccess[] = function ($form, $status) { # <-- funkce dostane parametry $form a $values!
// vypusteno
};
return $form;
}
?>
- Ja
- Člen | 260
@Šaman :
komponenta:
<?php
class NewsletterForm extends Control
{
// nejaka DIcka - vypusteno
public $onSuccess; // vlastni udalost, klidne by se mohla jmenovat onSave... takle asi prepisuju standardni udalost onSuccess z Control
// createComponentForm metoda - vypusteno
public function formSucceeded($form, $values)
{
if($this->newsletter->findBy($values)) {
$this->newsletter->deleteBy($values);
$this->onSuccess($this, DbStatus::DELETED); // timto si dostanu do presenteru informaci o tom, ze je newsletter smazan, vytahnu si to
}
else{
$this->newsletter->save($values);
$this->onSuccess($this, DbStatus::SAVED);
}
}
?>
vstriknuti objektu v presenteru:
<?php
/** @var INewsletterFormFactory @inject */
public $newsletter_form_factory;
?>
tvorba komponenty v presenteru pres tovarnu pro vykresleni v sablone:
<?php
protected function createComponentNewsletterForm()
{
$form = $this->newsletter_form_factory->create();
$form->onSuccess[] = function ($form, $status) {
if($status == DbStatus::DELETED) {
$this->flashMessage('E-mail byl odstraněn.');
}
else if($status == DbStatus::SAVED){
$this->flashMessage('E-mail byl přidán.');
}
$form->getPresenter()->redirect('default');
};
return $form;
}
?>
jeste tedy pro uplnost ten interface:
<?php
interface INewsletterFormFactory
{
/**
* @return NewsletterForm
*/
function create();
}
?>
je to takto jasnejsi? v tuto chvili dostavam NewsletterForm objekt na kterem muj vlastni onSuccess[] funguje, ale zas ten form rucne nevyrenderuju
diky moc
Editoval Ja (4. 3. 2015 11:46)