Komponenta v komponentě a překreslení snipetu
- David Matějka
- Moderator | 6445
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;
}
}
- LeonardoCA
- Člen | 296
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)
- LeonardoCA
- Člen | 296
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
@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
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
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
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)