přesná identifikace submit tlačítka
- mlha
- Člen | 58
Připojím do prezenteru submit a pak se zeptám jestli byl form odeslán
tímto tlačítkem.
Pokud byl formulář odeslán, pak Nette tvrdí TRUE, protože je to v tu
chvíli jediný submit ve formu.
PROČ???
Informaci o odeslání/neodeslání formuláře přeci mohu mít i tak.
Automatické označování prvního tlačítka je chybné.
Jaký je váš názor?
- mlha
- Člen | 58
Co když formulář obsahuje několik submit tlačítek.
Při vytváření formuláře se musí testovat, kterým tlačítkem byl
případně odeslán. Tento test ale nelze provést ihned po vložení submitu,
ale až po vložení všech submitů.
Vytvoření submitu a test jeho odeslání tak nelze pořešit samostatnou
metodou :(
- Filip Procházka
- Moderator | 4668
Myslím, že bude problém s tvou logikou, né s formuláři. Budeš muset změnit přístup, nebo si udělat fork a upravit si to :)
- Martin
- Člen | 171
mlha: Teda četl jsem Tvé posty 5×, než mi došlo, k čemu to asi
potřebuješ. Máš pravdu, ale proč to neřešíš přes callbacky
(lépe definovat jako pole)? A nemýlím-li se, callback lze zapsat i inline,
jde-li Ti o vložení tlačítka jednou kdesi jinde předdefinovanou metodou.
Respektive ->onClick[] = array($this, 'method');
použité ve
třídě, odkud si budeš tlačítka vybírat, zafunguje na tamní metodu,
budeš-li mít v továrničce k dispozici instanci této třídy. Nevím,
jestli to lze nějak vymyslet i se self
pro statické metody, ale
většinou stejně v obsluze tlačítka potřebuješ provést něco poměrně
nestatického. Řešil bych to třeba (nekoukej na PHP, to moc neumím, jsem OOP
programátor v jiném jazyce) takto:
namespace MojeNamespace;
use Nette\...;
class MojeKomponentaObsahujiciMojeStandardniTlacikaProFormulare
{
protected __this = NULL;
/*protected $mujAktualniPresenter;*/ // to jen tak, kdybych ho někde potřeboval.
__construct (/*$presenterTovarnicky*/)
{
/*$mujAktualniPresenter = $presenterTovarnicky;*/
__this = $this;
}
public static function addMojeTlacitko1($form, /*$presenterTovarnicky,*/ $parametry) {
$tlacitko = $form->addSubmit(...,...)
->onClick = array(__this, 'obsluhaTlacitka1');
//zde $this v extension metodě asi nebude obsahovat to pravé ořechové...
}
public function obsluhaTlacitka1($button) {
//zde obsluha používající $button, z něj získaný $form a aktuální Presenter, nebo $mujAktualniPresenter
}
}
//Přidám addMojeTlacitko1 do třídy FormControl:
Nette\Forms\FormControl::extensionMethod('addMojeTlacitko1', 'MojeNamespace\MojeKomponentaObsahujiciStandardniTlacikaProFormulare::addMojeTlacitko1');
//A pak v továrničce:
Class NejakyPresenter...
{
...
function createComponentMujForm($name)
{
//Pokud to nejde řešit přes statické callbacky (nevím), musím vytvořit instanci:
$mojeTlacitka = new MojeKomponentaObsahujiciMojeStandardniTlacikaProFormulare(/*$this*/);
$form = new Form($this, $name);
...
$form->addMojeTlacitko1(/*$this,*/ $parametry);
//Zde už by měl callback fungovat - nezkoušel jsem
}
Možná tam ještě budeš muset předávat aktuální Presenter (původně jsem to napsal s tím, ale pak jsem zjistil, že to asi nebude potřeba, tak jsem to vykomentoval v konstruktoru i metodě, měl by se dát v obsluze získat z proměnné $form, je-li už připojena).
Editoval Martin (8. 5. 2011 23:40)
- Patrik Votoček
- Člen | 2221
mlha napsal(a):
Při vytváření formuláře se musí testovat, kterým tlačítkem byl případně odeslán. Tento test ale nelze provést ihned po vložení submitu, ale až po vložení všech submitů.
WTF? Můžeš si přece otestovat:
$form->addSubmit('sub1', "Save");
$form->addSubmit('sub2', "Save as new");
if ($form->values['sub1'] == "Save") {
// save data
} elseif ($form->values['sub2'] == "Save as new") {
// save data as new
}
Výše uvedený kód je jenom ukázka ve skutečnosti to funguje takto:
$form->addSubmit('sub1', "Save")->onClick[] = function(SubmitButton $button) {
$values = $button->form->values;
// save data
};
$form->addSubmit('sub2', "Save as new")->onClick[] = function(SubmitButton $button) {
$values = $button->form->values;
// save data as new
};
POZOR NA TO ABY JSI MĚL U JEDNOTLIVÝCH TLAČÍTEK VYPLNĚNÝ $caption
.
BEZ NĚJ TOTIŽ NEMÁ NETTE ŠANCI DETEKOVAT KTERÝM TLAČÍTKEM BYL FORMULÁŘ
ODESLÁN!!!
- Martin
- Člen | 171
Patrik Votoček: No vida, jde to inline:-) . Po detailním prostudování druhého mlhova postu jsem pochopil, že mu jde o použití externí metody (kterou bude mít někde předpřipravenu pro více formulářů a která už bude mít v sobě zahrnutu obsluhu kliku), pak jeho posty dávají smysl. Možná se mýlím a to nahoře jsem tvořil zbytečně :-) V každém případě nebude nutné zbytečně vytvářet instanci, nějak mi nedošlo, jak to inline zapsat a že array je tam v příkladech použito jen z důvodu větší flexibility. Jak to ten David dělá (míněno ne jak to implementuje, ale jak ho něco tak univerzálně použitelného napadne), že tam lze použít pole, callback i inline funkci, a všechno funguje? Jako všechno v Nette :-)
Editoval Martin (8. 5. 2011 23:45)
- Patrik Votoček
- Člen | 2221
Já to právě nepochopil vůbec. Teď už mlhavě asi chápu. Pak může použít něco takovéhoto (pseudo kód):
$click = function(SubmitButton $button) {
$form = $button->form;
$values = $form->values;
if ($form['sub1']->submittedBy) {
// save data
} elseif ($form['sub2']->submittedBy) {
// save data as new
}
};
$form->addSubmit('sub1', "Save")->onClick[] = $click;
$form->addSubmit('sub2', "Save as new")->onClick[] = $click;
Ale připadá mě to nehezké a spíš bych se pídil po tom proč chce něco takového dělat.
- Martin
- Člen | 171
No třeba vymyslel krásnou metodu, která po stisku tlačítka s celým formulářem provede nějaký úžasný přemet a chce ji teď používat ve všech formulářích včetně jejího extra barevného tlačítka. Ale to, co jsem napsal, lze vlastně úplně jednoduše nahradit pomocí addComponent, kde komponenta bude v konstruktoru tvořit button s hotovou obsluhou onClick. To už není až tak ošklivé, ani zalevýmuchempravourukousedrbající, jako to, co jsem psal nahoře :-)
- mlha
- Člen | 58
Smyslem tohoto všeho je vyčlenit fragment formuláře (s vlastními pomocnými tlačítky) do samostatné metody. Tlačítka fragmentu modifikují (ovlivňují) část formuláře. A celý fragment se ve formuláři může vyskytovat opakovaně. Tento fragment by ale měl být i nadále součástí formuláře a měl by se podílet (jeho data) na běžném zpracování.
Ano je možné, že to, jak hodlám pracovat s formuláři, je už od
základu chybné (snad ne).
Možná je lepší vydat se cestou vlastních komponent (subkomponent), ale
v tom se zatím moc necítím.
Ale hlavní otázka, na kterou se ptám hned na začátku. To, že prohlížeč stiskem ENTER odešle formulář prvním submitem, je ok. Ale proč to samé dělá i Nette? (po prvním vloženém submitu tvrdí že byl submitBy). Přináší to nějakou výhodu?
Moc děkuji všem za příspěvky. Jdu je všechny ještě jednou pozorně prostudovat.
Editoval mlha (21. 6. 2011 10:49)
- Filip Procházka
- Moderator | 4668
Ukaž mi zjednodušený příklad, toho o co se snažíš a já ti ukážu jak to udělat lépe, bez hackování formulářů :)
- David Grudl
- Nette Core | 8227
Tak jsem čekal, kdo první pochopí, co mlha vlastně chce a zachránil to juzna :-)
juzna.cz napsal(a):
Nette se tak chova myslim kvuli chybe v IE. Prohlizec ma pri odeslani formulare enterem automaticky simulavat stisk prvniho tlacitka, coz vsak nektere verze IE nedelaji. Nette to tedy takto obchazi, aby se formulare chovaly stejne ve vsech prohlizecich.
Tohle nešťastné chování, které způsobuje problémy jenž mlha popisuje
(aniž by ho asi někdo chápal) existuje jako workaround pro nepříjemný bug v IE. Druhou možností by bylo
automaticky přidávat do HTML
<input disabled style="display:none">
, což je
takové divné.
…když to teď píšu, napadl mě ještě jeden workaroud, zkusím ho
prověřit.
Zkusím tam dát ten input, co to udělá…