Ukladání stavu komponenty při generování odkazu
- romansklenar
- Člen | 655
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
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žmorender
/action
) a pak uvádět jen hodnoty.
- romansklenar
- Člen | 655
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
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.