Form: setDefaults() a nezpracování požadavku
- jakubkulhan
- Člen | 55
Pokud použiju setDefaults()
před přidáním všech
formulářových polí, veškerá další pole za zavoláním
setDefaults()
jsou ignorována při zpracování požadavku:
$form = new Form;
$form->addText('foo', 'foo:');
$form->setDefaults(array('foo' => 'bar'));
$form->addText('baz', 'baz:');
$form->addSubmit('ok', 'OK');
$form->onSubmit[] = '_submit';
function _submit(Form $form)
{
var_dump($form->getValues(), $_POST);
}
$form->isSubmitted();
echo $form;
V tomto případě se ani _submit()
nezavolá. Pokud jde o
AppForm
, tak tam se zpracovávací funkce zavolá (protože se
obsluhuje pomocí signálů?), ale všechna další přidaná pole po
setDefaults()
jsou ignorována.
Revize 476, PHP 5.2.10, Arch Linux, Apache/2.2.11
Editoval jakubkulhan (8. 8. 2009 13:46)
- vlki
- Člen | 218
Vzhledem k tomu, že výchozí hodnoty by se do formuláře měly zapsat
jedině v případě, že není formulář odeslaný, tak se to musí zjistit.
Dojde tedy k zpracování HttpRequest
u. A ten se musí zpracovat
jen jedinkrát.
Při volání setDefaults
se tedy HttpRequest
zpracuje a zbytek definice formuláře je při tomto zpracování
ignorován.
Tím pádem se musí setDefaults
nastavovat až po kompletní
definici formuláře.
Nechápu, jak to ale může fungovat u AppForm
…?
- jakubkulhan
- Člen | 55
vlki napsal(a):
Vzhledem k tomu, že výchozí hodnoty by se do formuláře měly zapsat jedině v případě, že není formulář odeslaný, tak se to musí zjistit.
Mně naopak přijde logické, že – hlavně tedy při použití s MVC s továrničkou v presenteru – si formulář naplním výchozími hodnotami při vytváření (tj. v továrničce) bez toho, abych ověřoval, jestli byl, či nebyl odeslán, protože o zpracování odeslání formuláře se stará presenter ve fázi Interaction.
Dojde tedy k zpracování
HttpRequest
u. A ten se musí zpracovat jen jedinkrát.
Souhlas. Ale jak souvisí zpracování formuláře s jeho naplněním výchozími hodnotami? Když vytvářím SelectBox, říkám, co může obsahovat – práce s hodnotami –, tak proč nemohu rovnou říct, jaká hodnota má být výchozí – taky jako v předchozím případě; práce s hodnotami, nebo ne?
Možný patch:
--- Form.php (revision 476)
+++ Form.php (working copy)
@@ -388,11 +388,12 @@
/**
* Tells if the form was submitted.
+ * @param bool process HTTP request?
* @return ISubmitterControl|FALSE submittor control
*/
- public function isSubmitted()
+ public function isSubmitted($process = TRUE)
{
- if ($this->submittedBy === NULL) {
+ if ($this->submittedBy === NULL && $process) {
$this->processHttpRequest();
}
@@ -491,7 +492,7 @@
*/
public function setDefaults($values, $erase = FALSE)
{
- if (!$this->isSubmitted()) {
+ if (!$this->isSubmitted(FALSE)) {
$this->setValues($values, $erase);
}
}
(Poznámka: Proč jsou ksakru tabulátory převáděny na mezery?)
Pokud člověk před nastavováním výchozích hodnot ověřuje, jestli byl
formulář odeslán pomocí isSubmitted()
, nemělo by ho to nijak
ovlivnit. Jestliže je takový blázen jako já a nedělá to, tak tenhle patch
by mu měl přinést klidné spaní :-) Ale nevím, jak moc věcí závisí na
tom, že vedlejším efektem volání setDefaults()
je zpracování
formuláře.
- Ondřej Mirtes
- Člen | 1536
V továrničce nic kontrolovat nemusíš. Bez problému to tam funguje, stačí, když setDefaults provádíš až po přidání všech prvků formuláře.
protected function createComponentForm() {
$form = new AppForm($this, 'form'); //připojení ke controlu již tady, setDefaults to vyžaduje
$form->addText('text', 'Text');
//... další pole
$form->setDefaults(array(
'text' => 'Defaultní text',
));
$form->addSubmit('okSubmit', 'Odeslat');
$form->onSubmit[] = array($this, 'formSubmit');
//return $form; //již připojeno
}
- jakubkulhan
- Člen | 55
LastHunter napsal(a):
V továrničce nic kontrolovat nemusíš. Bez problému to tam funguje, stačí, když setDefaults provádíš až po přidání všech prvků formuláře.
Ano, já vím. Asi jsem to měl dát jasněji najevo, ale mně tu nejde o to, jak to vyřešit jinak. V podtitulku tohoto fóra je mimo jiné „Chcete nahlásit chybu?“ – a jelikož Issues na GoogleCode nejeví známky života, hlasím tedy věc, co považuji za chybu, tady.
- PetrP
- Člen | 587
Nemyslím si že je chyba že musíš setDefaults volat po přidání všech prvků (má to svojí logiku). Spíš by přidání prvku do formuláře který už má zpracovaný http požadavek mělo vyhodit výjimku.
Asi přidat do FormControl::attached()
něco jako
protected function attached(FormContainer $formContainer)
{
if ($formContainer->getForm() && $formContainer->getForm()->isPopulated()) {
throw new ...Exception...
}
}
- jakubkulhan
- Člen | 55
PetrP napsal(a):
Nemyslím si že je chyba že musíš setDefaults volat po přidání všech prvků (má to svojí logiku).
Stejně tak svoji logiku má volat setDefaults()
třebas
u každého pole – definici jednoho pole (do definice podle mě patří
i výchozí hodnota) nechci mít roztahanou po celé továrničce (nebo ještě
dokonce někde jinde), chci mít všechno u sebe.
A ještě když jsme u těch továrniček, tak pokud mám nějakou základní, která připraví pole, která jsou pro více formulářů společná, tak mi nepřijde zrovna moc dobré, abych je plnil v každé konkrétní továrničce zvlášť – DRY!
Spíš by přidání prvku do formuláře který už má zpracovaný http požadavek mělo vyhodit výjimku.
Ano, to rozhodně.
Ale pořád nevidím důvod, proč by setDefaults()
mělo
vyvolat zpracování požadavku? Až se požadavek zpracuje, výchozí data se
přepíšou těmi z požadavku a přepsat pomocí setDefaults()
už nepůjdou.
- David Grudl
- Nette Core | 8227
Ono to má svoji logiku – ale taky se mi to už dlouhodobě nelíbí. Snažím se s tím (už dlouhodobě) něco udělat ;)