Ukladání stavu komponenty při generování odkazu

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

Toto bude asi individuálnější dotaz na Davida, ale pokud poradí někdo jiný budu jen rád.

Dokázal by mi někdo objasnit, proč se při generování odkazu komponentou ukládá stav komponenty, je-li název parametru v metodě handle<Signal> stejný jako nějakého existujícího persistentního parametru?

Například mám-li takovouto komponentu:

class SimpleControl extends Control
{
	/** @persistent int */
	public $param = 1;

	// ...

	public function handleParam($param)
	{
	}


	public function render()
	{
		$this->link('param', 123);
	}


	public function saveState(array & $params)
	{
		parent::saveState($params);
		Debug::dump($params['param']); // 123
	}
}

Pokud v takovéto komponentě generuji signál jako tady v metodě render, pak se při jeho generování v presenteru uloží i stav komponenty (saveState) a do persistentního parametru se dostane hodnota 123.

Dá se to obejít tak, že se změní v deklaraci handleParam($param) název parametru na jiný než je název persistentního parametru, ale zajímalo by mě, jaký je důvod ukládání stavů v takovémto případě, případně je-li to chtěné/nutné.

Mimo to se komponenta ukládá ještě 2× (zde v metodě getGlobalState – jednou voláno odtud a podruhé odtud) a pokaždé je pak $params['param'] == NULL.

Jsem teda trošku zmatený a snažím se pochopit proč má pak při ukládání stavu parametru poprvé jinou hodnotu než v dalších voláních.

A proč se vůbec ptám – krom toho že chci lépe porozumět Nette? :) Pokud chci při prvním uložení stavu komponenty „zazálohovat“ hodnoty persistentních parametrů do session a při dalším vytvoření komponenty v loadState vzít parametry odtud, tak to dělá neplechu a v parametrech mám jiné hodnoty než bych očekával.

David Grudl
Nette Core | 8228
+
0
-

Zkus se na to podívat takto:

  • Každý komponenta má jeden balík parametrů.
  • Některé z nich je možné označit jako persistentní.
  • Aby nebylo potřeba jejich názvy vyjmenovávat při každém {link...}, lze výčet specifikovat v metodě handle (potažmo render/action) a pak uvádět jen hodnoty.
romansklenar
Člen | 655
+
0
-

To vím, dokonce to tady už bylo na fóru řečeno. Zajímalo mě jen to ukládání stavů jsou-li si názvy persistentního parametru a parametru v handle stejně pojmenovány.

Vzpomínám si, že v quick startu v datagridu bylo něco takového:

class DataGrid extends Control
{
	/** @persistent int */
	public $page = 1;

	...


	public function handlePage($page)
	{
		// $this->page = $page; - is done automatically
	}
}

Pokud je tedy název persistentu stejný jako název parametru v metodě handle tak se automaticky změní i hodnota persistentu a pak se musí uložit i stav komponenty – to ale musím nejříve kliknout na odkaz se signálem. A to je ono o co mi jde – já na odkaz neklikám. Proto mě to zaráží, že pouhé vygenerování linku už volá saveState a cpe mu hodnotu z tohoto odkazu. Pokud teda v render generuju více linků, volá se saveState na každém z nich a zajímá mě, jestli je to požadované chování jestli tam třeba není nějaká skrytá souvislost třeba s životním cyklem, protože pomalu začínám zjišťovat, že je o dost složitější než jsem myslel a daleko přesahuje zdokumentovanou oblast v dokumentaci a zdaleka mu nerozumím tak jak bych chtěl protože nevidím ty skryté závislosti, které z kódu nejdou vyčíst.

class SimpleControl extends Control
{
	/** @persistent int */
	public $param = 1;

	// ...

	public function handleParam($param)
	{
	}


	public function render()
	{
		$this->link('param', 123);
		$this->link('param', 456);
		$this->link('param', 789);
	}


	public function saveState(array & $params)
	{
		parent::saveState($params);
		Debug::dump($params['param']); // při vykreslování komponenty postupně vydumpuje: 123, 456, 789
	}
}
David Grudl
Nette Core | 8228
+
0
-

Zkus vnímat saveState spíš jako serializeState nebo takeSnapshot. Prostě to uloží aktuální stav komponenty do parametrů tvořících URL. Samozřejmě by bylo skvělé, kdyby se saveState volalo až když na link klikneš, ale to prostě nejde, to už je HTML stránka odeslána ze serveru.