Data z komponenty do šablony presenteru

Kcko
Člen | 465
+
0
-

Ahoj,

dostal jsem se trošku do pasti.

Je Presenter A, komponenta B (nějaký výpis položek se stránkováním).

Presenter A vypisuje (defaultAction) nějaká svoje data plus někde dole na stránce komponentu B.

Nyní vznikla potřeba na místě nadpisu stránky (což je proměnná presenteru A) vypisovat data z komponenty B.

Naivně jsem si myslel, že by to mohlo jít přes událost takto:

Komponenta

<?php
	public function renderDefault(array $config = [])
	{
		$config = $this->getCurrentConfig($config);

		list($limit, $offset) = $this->getPages($config);

		$this->template->advertisements = $this->model->getList(
			$config,
			$limit,
			$offset
		);

		$this->template->config = $config;

		**$this->onRender($this);**

		$this->render($config);

	}
?>

Presenter

<?php

	$this->onRender['B'] = function ($control, $x) {
			$this->template->x = $x;
		};

?>

Ale pak jsem debugovaním zjistil, že komponenta se renderuje až dávno po po presenteru a nemám do jeho šablony jak dostat data.

Napadají mě jen 2 způsoby, oba mi přijdou hrozné ;-)

  1. Sáhnu si na metodu z komponenty, která vrací data pro onu proměnnou (počet výsledků), s tím, že v komponentě bude taky pro správný chod stránkování (akorát si to uvnitř zakešuji, aby se neprováděla zbytečně 2×).
  2. Výpíši si ten počet v komponetně a pak si to přes javascript vlepím na patřičná místa v šablona (správně k nadpisu presenteru).|

Nelze to nějak jinak?

Editoval Kcko (16. 3. 2023 9:06)

Martk
Člen | 652
+
+2
-

3. renderTitle v komponentě
4. Z modelu si vytáhneš data třídu, stejnou třídu predas komponentě B a C (stará se o titulek) a nebo titulek hodíš do template proměnné.

Marek Znojil
Člen | 76
+
+1
-

Také bych se přikláněl k další render metodě v komponentě.

https://doc.nette.org/…n/components#…

Kcko
Člen | 465
+
0
-

Ahoj, diky oboum. 3) je samozřejmě nejlepší a nejčistší řešení.

K te 4). Kdyz si data takhle předám pomocnou „přepravkou“ tak to mít stejny efekt jako ten naivni onRender ne? Data mam k dispozici az v renderu komponenty a to proběhne az po presenteru…

Marek Znojil
Člen | 76
+
0
-

Ahoj,

komponenty jsou lazy, takže si její vytvoření můžeš vynutit třeba v action metodě prezenteru:

public function actionDefault(): void{
    $this['nazevKomponenty'];
}

Pak v nějaké události komponenty nebo *State metodě můžeš předpřipravit data, s kterými komponenta pracuje a geterem si je předat i do prezenteru.

Mohl bys i využít monitorování předků:
https://doc.nette.org/…ponent-model#…

Monitoring bys mohl předpřipravit v konstruktoru komponenty a předek, který by tě zajímal by byl Nette\Application\UI\Presenter.

Kcko
Člen | 465
+
+1
-

Ahoj, diky za myšlenku, tohle znám. Když si sahnu takto na komponentu, tak pořád nedojde k jejímu rendereru. Data mam k dispozici skutecne až v render metode, protože tam mám k dispozici config, který se mění, takže žádný handle ani monitor v constructoru, protože tam není znám ten config viz nahoře, getCurrentConfig. Jinak uz je to na prvni pohled takové vousate a nelogické, nicméně se v tom pro zajimavost/self-learn porypu. 3/ řešení je naprosto logicke, jasne a s minimem prace.

Kcko
Člen | 465
+
0
-

Díky

Marek Znojil
Člen | 76
+
0
-

Ah, moje chyba, špatně jsem si přečetl, že data znáš až v renderu. :)

Martk
Člen | 652
+
+3
-

Ke 4, když už chci sahat na data komponenty, tak už je v hlavě vykřičník, že je něco asi špatně a nakonec přijdu, že ano. Když chci data až v render metodě, tak to už vím 100%, že je něco špatně. Podle kódu $config = $this->getCurrentConfig($config); vidím, že ty data můžeš mít k dispozici kdykoliv. Stačí kód přepsat do $this->getCurrentConfig($this->getParameter('config')); a můžeš je mít v createComponent nebo startup metodě.

Kcko
Člen | 465
+
0
-

Marek Znojil napsal(a):

Ah, moje chyba, špatně jsem si přečetl, že data znáš až v renderu. :)

To nevadí, rád jsem si to zopakoval ;)

Kcko
Člen | 465
+
0
-

Martk napsal(a):

Ke 4, když už chci sahat na data komponenty, tak už je v hlavě vykřičník, že je něco asi špatně a nakonec přijdu, že ano. Když chci data až v render metodě, tak to už vím 100%, že je něco špatně. Podle kódu $config = $this->getCurrentConfig($config); vidím, že ty data můžeš mít k dispozici kdykoliv. Stačí kód přepsat do $this->getCurrentConfig($this->getParameter('config')); a můžeš je mít v createComponent nebo startup metodě.

Jasně, není to ideální, ideální je v tomto případě 3). Jenom tady nechápu, kde a jak a proč si mám posílat GETem config?

Komponenta funguje takto:

  • má defaultní config přímo v sobě
  • můžu komponentu nastavit skrz DB (je takové magické, abych nemusel vytvářet komponenty přes továrnu v presenteru), pak se config v případě potřeby mergne (přepíše nebo to co je jiné než výchozí)
  • mohu pak v presenteru (akcích / renderech ..) komponentu nasetovat a doupravit finálně její config; což dělám dost často (vytáhnu řádek z DB a nějakým způsobem upravím config komponenty na základě získaných dat, to ve startupu nezjistím).

Nechápu tedy tu poznámku o nastavení skrze startup v presenteru ;), pokud jsi to myslel jinak, než jsem pochopil, prosím o demo ukázku, jinak považujme za vyřešené, řešení 3 je fajn a vyhovující a v noci včera mě nenepadlo ;-)

Martk
Člen | 652
+
+4
-

Podle kódu v prvním postu vidím, že na základě parametru config si získáváš aktuální config.

Všechno co se týče db, defaultní hodnoty, nastavování, merge, doupravování configu by nemělo být v komponentě ani presenteru, ale uděláš si na to samostatnou třídu.

Továrny na komponenty jsem taky moc nedělával, byl jsem líný, ale zjistil jsem, že už jsem musel kód tolikrát přepisovat na továrnu, že už to dělám automaticky a nic mě to nestojí.

Pokud ti stačí 3, tak ok. Jenom jsem doplnil odpověď, třeba se bude hodit do budoucna.

Kcko
Člen | 465
+
0
-

Martk napsal(a):

Podle kódu v prvním postu vidím, že na základě parametru config si získáváš aktuální config.

Všechno co se týče db, defaultní hodnoty, nastavování, merge, doupravování configu by nemělo být v komponentě ani presenteru, ale uděláš si na to samostatnou třídu.

Továrny na komponenty jsem taky moc nedělával, byl jsem líný, ale zjistil jsem, že už jsem musel kód tolikrát přepisovat na továrnu, že už to dělám automaticky a nic mě to nestojí.

Pokud ti stačí 3, tak ok. Jenom jsem doplnil odpověď, třeba se bude hodit do budoucna.

Díky, v budoucnu se nad tím ještě zamyslím, kvůli lepší flexibilitě-