form action – podivná filtrace vygenerovaného linku

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
maarlin
Člen | 207
+
0
-

Při nastavení action formuláře:

$form->setAction($this->link('Uzivatel:submitLoginForm'));
NDebug::dump($form->getAction());

Dostanu z laděnky správný výpis:
"/uzivatel/submit-login-form/"
Ovšem když se podívám následně do kódu, je tam toto:

<form action="/?do=smallLoginWindow-submit"...

Tedy URL aktuální strany s jedním parametrem ‚do‘…

Čili odeslání formuláře na zpracovací metodu pak nefunguje… :(

Formulář je generován továrničkou v BasePresenteru:

abstract class BasePresenter extends NPresenter
{
    public function createComponentSmallLoginWindow()
    {

Editoval maarlin (1. 1. 2010 18:08)

Ondřej Mirtes
Člen | 1536
+
0
-

Zdá se mi, že mícháš actiony a handlery (pro signály a zpracování formulářů). Nemůžeš vytvářet link na adresu, kam se odesílá formulář.

maarlin
Člen | 207
+
0
-

Jak bych ten widget tedy měl nasměrovat na handler pro zprac. formuláře?

Ondřej Mirtes
Člen | 1536
+
0
-

Jaký widget? Popiš, co potřebuješ udělat :) Jestli potřebuješ nějakou zpracovávací metodu pro odeslaný formulář, tak v továrničce napiš:

$form->onSubmit[] = array($this, 'formSubmitted');

A metoda má pak vypadat nějak takto:

public function formSubmitted(AppForm $form) {
	$values = $form->values;
	//...zpracování
	$this->flashMessage('Úspěch!');
	$this->redirect('this');
}

Editoval Ondřej Mirtes (1. 1. 2010 19:57)

maarlin
Člen | 207
+
0
-

Ano, pochopil jsi mě :) Ovšem potíž vzniká pro mě v tom, že ta zpracovávací metoda pro odesílací formulář je v jiném presenteru, než je samotný formulář…

Tudíž logicky nefunguje toto, protože odesílací metoda formSubmitted se hledá v aktuálním presenteru:

$form->onSubmit[] = array($this, 'formSubmitted');

Formulář se generuje v BasePresenteru, aby se mohl zobrazovat na všech stranách webu a zpracovávací metoda zůstává v UzivatelPresenteru.

Dělám to špatně?

Tomik
Nette Evangelist | 485
+
0
-

Tak to zpracování dej také do BasePresenteru.

Pak $form->onSubmit[] = array($this, 'formSubmitted'); bude fungovat…

maarlin
Člen | 207
+
0
-

Tomik napsal(a):

Tak to zpracování dej také do BasePresenteru.

Pak $form->onSubmit[] = array($this, 'formSubmitted'); bude fungovat…

Taky mě to napadlo, ovšem to zrovna nezní jako DRY… :)
To opravdu není jiné řešení, než zkopírovat stejnou část kódu na dvě místa?

Tomik
Nette Evangelist | 485
+
0
-

maarlin napsal(a):

Taky mě to napadlo, ovšem to zrovna nezní jako DRY… :)
To opravdu není jiné řešení, než zkopírovat stejnou část kódu na dvě místa?

Nerozumím. Definice formuláře i jeho zpracování bude pouze jednou a to v BasePresenteru. Ostatní presentery to budou pouze vypisovat, přesně podle DRY.

maarlin
Člen | 207
+
0
-

V UzivatelPresenteru to zpracování formuláře není jen tak pro srandu králíkům :)
Existuje samostatný formulář, resp. samostatné view – //Uzivatel:prihlasitSe , což je výchozí stránka pro přihlášení a především vypisování chyb, ovšem z praktických důvodů je k dispozici to malé přihlašovací okno na každé straně. Tudíž formuláře jsou dva, prakticky stejné, jen jinak vykreslené – malý formulář, co se zobrazuje na každé straně webu někde po straně a pak formulář pro jediné view, kde se zobrazí ty chybové hlášky – //Uzivatel:prihlasitSe

Tomik
Nette Evangelist | 485
+
0
-

maarlin napsal(a):

V UzivatelPresenteru to zpracování formuláře není jen tak pro srandu králíkům :)
Existuje samostatný formulář, resp. samostatné view – //Uzivatel:prihlasitSe , což je výchozí stránka pro přihlášení a především vypisování chyb, ovšem z praktických důvodů je k dispozici to malé přihlašovací okno na každé straně. Tudíž formuláře jsou dva, prakticky stejné, jen jinak vykreslené – malý formulář, co se zobrazuje na každé straně webu někde po straně a pak formulář pro jediné view, kde se zobrazí ty chybové hlášky – //Uzivatel:prihlasitSe

Pak budeš mít dvě definice formuláře, tomu se nevyhneš, chceš-li mít dva formuláře, ale metoda pro zpracování stačí jedna. Tedy DRY. :)

Jak na to?

V BasePresenteru budeš mít jak továrničku na nějaký loginForm, pak metodu doLogin, která zpracovává data z loginovacího formuláře. V té továrničce pak nastavíš $form->onSubmit[] = array($this, 'doLogin');. Zatím ok. Tento widget (resp. formulář) pak můžeš vykreslit úplně všude (protože díky tomu, že je definován v BasePreseteru, je všude dostupný – tedy za předpokladu, že Tvé Presentery od BasePresenteru dědí – což by měly :D).

Nyní k tomu konkrétnímu Presenteru, např. tedy UsersPresenter, ten bude mít továrničku na ten velký loginovací formulář, a v ní se bude definovat opět $form->onSubmit[] = array($this, 'doLogin'); a díky tomu, že tento presenter dědí od Basu, sdědil i metodu doLogin, tudíž pokud budou mít oba formuláře stejné prvky, bude vše fungovat, jak to bylo zamýšleno. Tedy za předpokladu, že jsem to, co chceš udělat, pochopil správně. :)

maarlin
Člen | 207
+
0
-

Jo, to je fajn, ani mi v tu chvíli (rozuměj v zápalu boje) nedošlo, že ostatní Presentery dědí od BasePresenteru všechny metody… :)

Ale stejně by se mi to víc líbilo, kdyby ta zpracovací metoda byla v UsersPresenteru, jelikož se to týká Users, a nikoliv všech presenterů… ale to už je spíš polemizování nad tím, jak lze chápat logiku frameworku… :)

Ed
Člen | 5
+
0
-

Tento topik se asi nejvice blizi memu problelmu s formulari, tak se pokusim popsat s cim valcim a pokud by nekdo vedel v cem je zakopany pes…
tedy.. nevim jak pridat do action fromulare nejaky GET parametr :)
pro nastaveni akce je treba $form->setAction($url), ale to mi nenastavi potrebny obzlusny signal (tj chyb do=…). url se snazim ziskat pres $this->link() ($this je neni presenter ale potomek Control)
pokud v sablone zavolam jen {$form} a nenastavim svou url do url se pouziji jen perzistentni parametry + signal do… ovsem pokud je zobrazeni formulare podmineno vyskytem parametru v get, tak se formular nezobrazi jak ma…

konkretni priklad url:
url stranky je: /admin/pages/?activeItem=2&subMod=local&lg=cz
url formulare je: /admin/pages/?activeItem=2&subMod=local&do=sub_pages-editCategoryForm-submit
vypadne tedy parametr lg, ktery nevim jak pridat. parametr lg je podstatny jen pro tento formular a tedy davat ho perzistentni mi neprijde vhodne.

predpokaldam ze problem bude asi nekde v tom, ze obsluzna funkce signalu neni namem jak se vsude uvadi v presenteru, ale v primo v objektu formulare a jen nevim jake predat parametry funkci ->link(..) pro vytvoreni signalu …

predem dik za radu

Ondřej Mirtes
Člen | 1536
+
0
-

Filozofie formulářů v Nette MVC je taková, že vygenerovanou URL by ses vůbec neměl zabývat, prostě seš od tvorby URL odstíněný a framework ti zařídí, že se ti zavolá taková metoda, jakou potřebuješ. Proto ty čachry, když saháš na setAction, způsobují, že to přestane fungovat – tahle metoda je primárně určená pro práci s Form, tj. bez MVC :) (v MVC se dá použít např. pro přidání anchoru, ale rozhodně ne pro přidávání parametrů).

Ten parametr lg bych předával asi jako hidden pole.

$form->addHidden('lg')->setValue('cz');
Ed
Člen | 5
+
0
-

No ja bych prave se o tu url rad nestaral, jen bych potreboval, aby se formular odeslal na aktualni stranku se vsemy GET parametry (nejen temi urcenymi jako perzistentni) a jen se „pridal“ signal do :)

PetrP
Člen | 587
+
0
-

Taky by se mi hodilo odesílat formulář na url u ze všema parametrama.

Jinak když si chceš upravit action u AppForm tak to musíš udělat až po připojení na presenter, protože po tom připojení si form nastaví action automaticky sám a přepíše ti ho.

Protože se action nastavuje jako třída Link tak mužeš snadno přidat parametry.

protected function createComponentForm($name)
{
	$form = new AppForm($this, $name); // ted je pripoji na presenter a nastavi action
	$form->action->setParam('sameParam', $this->getParam('sameParam'));
	...
}

Link::setParam()

Editoval PetrP (20. 1. 2010 9:56)

Ondřej Mirtes
Člen | 1536
+
0
-

A nefunguje to tak náhodou? Jsem například na ?presenter=Test&action=test&id=5, odešlu formulář a na tom samém linku se zase objevím…

Filip Procházka
Moderator | 4668
+
0
-

Moje oblíbená rada, aktualizuj framework, mě to taky funguje tak, že to předá celou aktuální url a přidá DO :)

Ondřej Mirtes
Člen | 1536
+
0
-

Možná bude problém v tom, že nepředáváte ty GET parametry jako parametry render metod, ale nějak obcházíte framework…

PetrP
Člen | 587
+
0
-

Tuhle mi to nefungovalo ani když jsem to měl v renderDefault($neco), byla ± týden stará verze. Poznamenávám si to a hned jak budu mít chvilku tak to vyzkouším a dám vědět jestli to je bug u mě.

Ondřej Mirtes napsal(a):

Možná bude problém v tom, že nepředáváte ty GET parametry jako parametry render metod, ale nějak obcházíte framework…

Jinak to podle mě obcházení FW není, protože já osobně mívám render metody dost vyjímečně, většinu řesím přes supertovárničky (a nebudu sám.)

Editoval PetrP (21. 1. 2010 11:16)

Ondřej Mirtes
Člen | 1536
+
0
-

Máš parametry render metod, máš parametry signálů (a parametry signálů komponent) a máš persistentní parametry. Tohle jsou frameworkem podporované cesty a díky nim se nemusíš starat o tvar URL. Co víc potřebuješ? :)