[Bug] InvalidStateException při nastavování defaultních hodnot

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

Myslím, že poslední verze Nette (rev 285) obsahuje bug. Resp. co fungovalo, nefunguje :). Využívám vylepšené metody createComponent popsané zde: create<ComponentName>(). Následující kód vyhodí výjimku:

protected function createForm($name) {
	$form = new AppForm();
	//...

	$form->setDefaults($defaults); // vyhazuje vyjimku!
}
InvalidStateException
Component is not attached to 'Presenter'.

Problém je, že výchzí hodnoty nelze pro dosud nepřidanou komponentu do hiearchie nastavit. Přidáním řádku $this->addComponent($form, $name); před nastavování výchozích hodnot je řešení, ale nabourává to přístup supertovárničky. Navíc pro to není důvod, alespoň myslím.

Chyba se v revizi 254 (poslední má záloha) neobjevovala.

Editoval mancze (30. 4. 2009 13:21)

Jod
Člen | 701
+
0
-

Ako kukám bude to asi tým, že ponovom musí byť komponenta priradená k presenteru a potom až môžu byť nastavené defaultné hodnoty?

Možno to má nejaký význam.

kravčo
Člen | 721
+
0
-

Je to zrejme spôsobené zmenou v metóde Form::setDefaults, BC break to ale nie je, keďže pred touto zmenou bolo treba volať setDefaults() len na neodoslanom formulári:

if (!$form->isSubmitted()) {
	$form->setDefaults(array(
		// ...
	));
}

Čo je rovnaká logika ako v aktuálnej verzii, len sa táto podmienka presunula do volania setDefaults().

Na tento problém som narazil i ja, keď som sa snažil odseparovať formuláre od prezenterov a nechať ich čisto v modeli – presne kvôli tomuto mi to celkom nešlo… Dá sa to riešiť nejako inak?

jasir
Člen | 746
+
0
-

kravco napsal(a):

Na tento problém som narazil i ja, keď som sa snažil odseparovať formuláre od prezenterov a nechať ich čisto v modeli – presne kvôli tomuto mi to celkom nešlo… Dá sa to riešiť nejako inak?

Napadá mě (a možná je to blbost) podědit si Form na MyForm – stejně něco podobného asi většina z nás dělá (?) – a v něm si přepsat setDefaults nějak takhle

<?php
private $_defaults
public function setDefaults($defaults)
{
	$this->_defaults = $defaults;
}
public function attached($presenter)
{
	parent::attached($presenter);
	if($presenter instanceOf Presenter) {
		$this->setDefaults($this->_defaults)
        }
}
?>

Takto by se mělo setDefaults volat až při připojení k prezenteru. Nezkoušel jsem…
Podobně jako to děla AppForm

Editoval jasir (30. 4. 2009 15:17)

mancze
Člen | 58
+
0
-

jasir napsal(a):

Takto by se mělo setDefaults volat až při připojení k prezenteru. Nezkoušel jsem…

Zřejmě funkční, ale fuj řešení. Co mají výchozí hodnoty co dělat s tím, jesti je form připojený k Presenteru či nikoliv?

Na druhou stranu souhlasím s tím, jak setDefaults funguje – přednastavuje jen v případě neodeslaného formuláře.

jasir
Člen | 746
+
0
-

mancze napsal(a):

jasir napsal(a):

Takto by se mělo setDefaults volat až při připojení k prezenteru. Nezkoušel jsem…

Zřejmě funkční, ale fuj řešení. Co mají výchozí hodnoty co dělat s tím, jesti je form připojený k Presenteru či nikoliv?

Presenter poskytne informace o zaslání/nezaslání formuláře? Podobně, jako to dělá AppForm, pouze jsme ho rozšířili? No dobře, zavání to :)

Honza Marek
Člen | 1664
+
0
-
protected function createForm($name) {
	$form = new AppForm();
}

Nejjednodušší (i když lehce otravné) bude připojení formuláře k presenteru už v konstruktoru takhle:

$form = new AppForm($this, $name);

Na druhou stranu to ani nebude potřeba na konci vracet returnem.

jasir
Člen | 746
+
0
-

Honza M. napsal(a):

Nejjednodušší (i když lehce otravné) bude připojení formuláře k presenteru už v konstruktoru takhle:

$form = new AppForm($this, $name);

Na druhou stranu to ani nebude potřeba na konci vracet returnem.

Jo, v super továrničče to je tak asi nejsnazší, na druhé straně jak psal kravco, možná by se přístup přes attached() dal použít pro tvorbu formulářů v rámci modelů.

Editoval jasir (30. 4. 2009 16:10)

Patrik Votoček
Člen | 2221
+
0
-

Jak psal Honza M. tak bych to vyděl jako správné řešení. I když vytváření formuláře máš v modelu. Nevím jestly by to tam mělo být ale asi ano. Tak stejně když ten formulář vytváříš tak ho na 99% budeš chtít i vykreslit (vlastně asi na 100% – nenapadá mě důvod vytvářet formulář který se později nevykreslí.

A co ti brání pokud máš tvorbu formuláře v modelu řekněme:

<?php
class MyModel extends Model
{
	public function createForm(...)
	{
		...
	}
}
?>

Nevím proč nemít v parametrech $parent a $name, stejně by se dle mého názoru ‚bestpractice‘ formulář pojmenovat nějákým IDčkem. A když už víme že se bude vykreslovat tak mu předat i $parent (presenter nebo vykreslitelnou komponentu).

Taky nechápu proč by to mělo popírat smysl supertovárničky? Přece když volás createComponent($name) tak už máš dostupný presenter/vykreslitelnou komponentu. Tak proč jí v továrničce to $this nenapsat. Navíc jméno je u createComponent($name) v parametru name jako poviné tak proč to taky nepředat?

Nebo sem snad něco nepochopil?

Editoval vrtak-cz (30. 4. 2009 17:40)

mancze
Člen | 58
+
0
-

Osobně cítím vytvoření komponenty (ať již AppForm nebo cokoliv jiného) a její zařazení do hierarchie komponent jako dva oddělené kroky. Nelíbí se mi proto to mít v společně v jedné metodě.

Každopádně se přiznám, že jednoduché $form = new AppForm($this, $name); mne nenapadlo. Používám obdobné řešení: $form = $this->spawnForm($name);, které vytvoří a vrátí samotnou instanci Formu už zařazeného do hierarchie.

kravčo
Člen | 721
+
0
-

vrtak-cz napsal(a):

Taky nechápu proč by to mělo popírat smysl supertovárničky? Přece když volás createComponent($name) tak už máš dostupný presenter/vykreslitelnou komponentu. Tak proč jí v továrničce to $this nenapsat. Navíc jméno je u createComponent($name) v parametru name jako poviné tak proč to taky nepředat?

Iste, máš pravdu. Vyriešil som to tak ako popisuješ. Akurát sa mi to veľmi nepáči a nie je podľa mojich predstáv. To čo písal jasir vyzerá rozumne, bude to chcieť asi trochu doladiť (napr. dediť od AppFormu, keďže Form nemusí súvisieť s prezenterom). Vyskúšam to a podelím sa…