Změna šablony komponenty s attached na presenter
- kleinpetr
- Člen | 480
Ahoj,
mám komponentu, která se připojuje na presenter pomocí
attached()
když chci ale v nějakém presenteru změnit šablonu
té komponenty na nějakou konkrétní, tak mi hlásí, že komponenta nebyla
připojena k presenteru.
Jak se dá tedy řešit změna šablony zároveň s
attached()
Díky
Editoval kleinpetr (1. 6. 2015 12:27)
- enumag
- Člen | 2118
Např. tak že v továrně té komponenty zavoláš
$component->setParent($this);
V tu chvílu už bude komponenta připojená. (EDIT: Možná musíš předat
ještě $name
aby to fungovalo správně.)
Osobně jsem si (z jiných důvodů) ke komponentám přidal událost onAttached, což je druhá možnost jak řešit tvůj problém.
Editoval enumag (1. 6. 2015 12:47)
- kleinpetr
- Člen | 480
No mám to zkrátka takhle
V komponentě:
protected function attached($presenter)
{
parent::attached($presenter);
if ($presenter instanceof Presenter) {
$this->translator = $presenter->translator;
}
}
V presenteru:
protected function createComponentMyComponent()
{
$component = $this->someComponent->create();
$component->template->setFile('other.latte');
return $component
}
tohle vrátí chybu:
Component '' is not attached to 'Nette\Application\UI\Presenter'
- kleinpetr
- Člen | 480
Jojo vím.
Vyřešeno takto:
v komponentě:
protected $templateFile = 'componentDefault.latte';
public function setTemplateFile($file)
{
$this->templateFile = $file;
}
public function render()
{
/** @var Nette\Bridges\ApplicationLatte\Template $template */
$template = $this->template;
$template->setFile(__DIR__ . '/templates/'.$this->templateFile);
}
Díky za pomoc.
- newPOPE
- Člen | 648
@kleinpetr
- Presenter nema co menit sablonu komponenty na to mas
render*
v komponente - Ked uz to potrebujes tak to nerob vo factory metode ale v
action*, render*
metode presenteru (zbavis sa attached problemu tym padom aj tohto$this->translator = $presenter->translator;
a vyriesi ti to DI)
- akadlec
- Člen | 1326
To bych si dovolil nesouhlasit. Vytvoříš jednu komponentu, ale budeš ji chtít použít na dvou místech (presenterech) ale pokaždé bude vypadat jinak. Takže přesenter přes setter nastaví jakou šablonu má komponenta použít. Dělat to v render metodě nějakou magii je imho špatně.
A ad translator, jo může si jej předat pomocí constructoru, ale zase třeba když používá kdyby/translator tak si určí prefix který chce mít společný s presenterem tak si jej z presenteru vytáhne ;)
- newPOPE
- Člen | 648
Tak sa skusme zamyslet.
Povedzme, ze 2 miesta su 2 presentery. Tym padom nebudem pisat 2 rozne factory metody ale budem mat jednu niekde v predkovi (napr. BasePresenter daneho modulu ak nejaky mam). No a tu pride na rad tvoja magia ;) nakolko podla coho factory metoda vyhodnoti aky template ma nastavit?.
Ja uprednostujem trocha iny pristup (ked uz to musi byt) a to:
// factory method
public function createComponentMyComponent() {
return $this->myComponentFactory->create();
}
// konkretny presenter A
public function renderFoo() {
$this['myComponent']->setTemplateFile('foo.latte');
}
// konkretny presenter B
public function renderBar() {
$this['myComponent']->setTemplateFile('bar.latte');
}
Co nevybocuje od toho co pises nakolko to nastavuje konkretny presenter.
No a keby velmi chcel tak sa na sablony v Presenteri vykasle lebo tie by mohol ovladat View (za predpokladu, ze pri view uz vynimka nevyleti na co treba mysliet pri pisani) a to takto:
// viewPresenteru.latte (tento example ma problem s Ajaxovanim komponent!)
{control myComponent:foo}
{control myComponent:bar}
Editoval newPOPE (2. 6. 2015 11:50)
- newPOPE
- Člen | 648
Ide o to, ze ked tam uvedies Translator
co je rovno trieda aj
s implementaciou tak si v podstate zatvoris dvere pre zmenu. Napriklad ked to
budes chciet vymenit za MySuperCoolTranslator
a tento translator
nebude potomok Translator
-u tak ti to neprejde type checkom a
budes to musiet prepisat vsade.
Ked pouzijes ITranslator
tak uvedies len rozhranie (interface) a
vtedy len staci aby dany translator implementoval toto rozhranie. Type check je
v poriadku lebo ocakava instanciu ITranslator
-u. Cize vymena je
easy nakolko ked budes menit Translator tak len v novej implementacii
implementujes dany interface.