Komponenta v komponentě a překreslení snipetu

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

Zdravím,

mám komponentu v komponentě a potřebuju z vnořené komponenty zavolat překreslení snippetu vnější komponenty.

Je vůbec možné něco takového udělat? Když volám překreslení snippetu v šabloně přímo v template tak je to bez problémů.

Děkuju za odpověď

Etch
Člen | 403
+
0
-
$this->parent->redrawControl(... )

???

David Matějka
Moderator | 6445
+
+4
-

j, jak pise @Etch, ale zvaz, jestli je nutne ty komponenty takhle uzce provazat. Casto je dobrym resenim vytvoreni udalosti v zanorene komponente a rodicovska komponenta se na tu udalosti navaze a udela, co potrebuje. Kratce:

class SubComponent extends BaseControl
{
	public $onUpdate = [];

	public function handleDoSth()
	{
		...
		$this->onUpdate(....);
	}
}

class Component extends BaseControl
{
	public function createComponentSub()
	{
		$control = new SubComponent();
		$control->onUpdate[] = function () {
			$this->redrawControl(...);
		};

		return $control;
	}
}
Jan Mikeš
Člen | 771
+
0
-

To co pise @matej21 pouzivam take u formularu obalenych komponentami a mohu vrele doporucit, toto reseni je ciste a zustava ti vzajemna nezavislost komponent na sobe.

LeonardoCA
Člen | 296
+
0
-

Tady mi trosku unika pointa. v Nette komponent modelu je prece vazba na parent vzdy vytvorena a kdyz zavolam $this->parent->redrawControl(); pro preklesleni parent componenty (pozor → ne nejake jine komponenty) tak zadnou novou vazbu nevytvarim, jen vyuzivam jiz existujici.

Resit tohle pres event mi prijde zbytecne, az kontraproduktivni, nebo se pletu?

Editoval LeonardoCA (10. 1. 2015 0:25)

Jan Endel
Člen | 1016
+
+1
-

Komponenta jako taková je samostatná jednotka a je jí v podstatě jedno kdo je její rodič (to je mi ale povedené dítko) a ani by správně neměla nic vědět o jeho implementaci, pro znovupoužitelnost je rozhodně lepší eventa jak navrhl @matej21

LeonardoCA
Člen | 296
+
0
-

S tim v tomto konkretnim pripade nesouhlasim, predpokladam-li, ze vsechny komponenty dedi od Nette\UI\Control tak maji preci vsechny zakladni implementaci stejnou a strom komponent je zaklad pro praci s komponentami v nette, neni jen pro srandu kralikum … (a nebo nechapu o cem je rec, presvedcte me :)

Editoval LeonardoCA (10. 1. 2015 0:37)

Marek Šneberger
Člen | 130
+
0
-

@LeonardoCA Jinými slovy, je lepší se osamostatnit a nebýt závislý na rodičích :)
Vem si třeba když potřebuješ v komponentě udělat redirect. Jasně, Nette je celkem chytré a tak můžeš jednoduše zapsat v komponentě $this->presenter->redirect(), ale potom je ta komponenta závislá (to slovo se mi začíná líbit :D) na Presenteru. Lepší a čistější cesta je si vytvořit event $onRedirectRequired = [] a ten volat z presenteru. Ještě jinak řečeno – komponentě jako takové (malá skládačka webu) má být uplně ukradené, jestli proběhne redirect nebo ne, protože to si řeší ten Presenter

Jan Endel
Člen | 1016
+
+3
-

Tam nejde o to, kdo od koho dědí nedědí, ale kdo je rodič a potomek ve stromu komponent, správná komponenta by měla být taková, kterou vemeš a bez závislosti na umístění ve stromu použiješ někde úplně jinde bez toho, aniž by byla jakkoliv závislá na implementaci rodiče. Tuto závislost tam právě natvrdo napsaným $this->parent->redrawControl() zavádíš.

Etch
Člen | 403
+
0
-

Ono stejně vždy záleží na situaci. Například občas se mi stane, že vytvářím komponentu „jen“ z důvodu, abych odstranil složitou logiku z šablony předka a ta komponenta je opravdu striktně jednoúčelová. Není tedy vytvářena kvůli znovu použitelnosti, ale kvůli tomu, aby kodér neměl v šabloně složitou logiku, ve které by se mohl ztratit. V takové komponentě klidně použiji $this->parent->, protože mi tam ta „závislost“ absolutně nevadí.

Ve většině případů ovšem také volím cestu eventu. Při překreslování snippetů to dělám hlavně (kromě již zde zmíněných důvodů) i z toho důvodu, že chci překreslení snippetů v šabloně vždy řídit z komponenty (presenteru), která k dané šabloně náleží, i za cenu, že by to mělo být napsáno třeba takhle triviálně:

	protected function createComponentFoo(){
		$control                 = $this->fooFactory->create();
		$control->onNeedRedraw[] = $this->redrawControlClosure('flashMessages');
		$control->onNeedRedraw[] = $this->redrawControlClosure('foo');
		$control->onNeedRedraw[] = $this->redrawControlClosure('bar');

		return $control;
	}

	private function redrawControlClosure($name){
		$me = $this;
		$closure = function () use ($name, $me){
			$me->redrawControl($name);
		};

		return $closure;
	}

Pro mě má to řešení na úrovni eventů tu výhodu, že pokud bych například i jen chtěl nějaký snippet z nějakého důvodu přejmenovat, tak nemusím myslet na to, že v nějaké zanořené komponentě (nedejbože komponentách) může být hardcoded invalidace daného snippetu, ale stačí se mi kouknout do kódu komponenty (presenteru), který k dané šabloně náleží.

Stejně tak v případě, že se najednou vyskytne potřeba invalidovat nějaký nově přidaný snippet rodiče, je daleko přímočařejší přidat $control->onNeedRedraw[] = $this->redrawControlClosure('baz'); než lézt do implementace té „zanořené“ komponenty (komponent) a přidávat to tam.

Editoval Etch (10. 1. 2015 4:47)

LeonardoCA
Člen | 296
+
0
-

Ok, vcera jsem si spatne precetl puvodni otazku – ze slo o prekresleni konkretniho snippetu v parent komponente – v tomto pripade je urcite lepsi vyuzit event.

Ja mel na mysli pripad, ze bych chtel prekreslit celou parent komponentu, pak by mi prijde zbytecne to delat pres event a definovat v kazde komponente obsluhu eventu, kdyz to muzu udelat jednoduse bez kodu navic.

(Hmm, nevim, budu si ted trochu vic hrat s ruznymi komponentami, tak si to jeste promyslim)