Jak nastavit setLayout() u komponent?
- Šaman
- Člen | 2659
Ahoj, kde přesně se do šablony nastavuje layout z php kódu?
Když prohledávám přímo Nette, tak v presenteru setLayout()
nastaví členskou proměnnou, ale nenašel jsem kde přesně se dostane do
šablony.
Resp. jak mohu nastavit soubor s layoutem v komponentě? Tam žadný
setLayout()
není a objekt Template
také žádný
nemá.
Přitom pokud v latte použiju {extends …}
tak to funguje
správně.
Call to undefined method Nette\Bridges\ApplicationLatte\DefaultTemplate::setLayout()
.
Tak jsem dohledal tohle: Automatické dohledávání layoutu, ale moc moudrý z toho nejsem. To opravdu musím obyčejné nastavení cesty k souboru řešit nějakou interní funkcí Latte enginu, nebo jsem někde přehlédl běžné řešení?
Editoval Šaman (16. 5. 17:16)
- David Grudl
- Nette Core | 8218
Interní funkce to není, když je dokumentovaná a uvedená takto na webu. Ano, dělá se to tak, nicméně pokud najdeš snadnější řešení, klidně to do Nette dám.
- David Grudl
- Nette Core | 8218
coreParentFinder
je název právě funkce, co umí dohledat
šablonu.
A referenceType… myslím že jsem zvažoval, že by to umělo dohledávat i layout layoutu, což nejspíš nikdo nepotřebuje, tak to asi časem zjednoduším, aby by funkce mohla vracet ten soubor přímo
- m.brecher
- Generous Backer | 864
@Šaman
Resp. jak mohu nastavit soubor s layoutem v komponentě?
Layout se standardně nastavuje v presenteru, protože z layoutu dědí šablony akcí. Ve speciálních případech jako je Tvůj je možné, aby komponenta definovala layout, ale zatímco v presenteru je nastavení layoutu snadné, v komponentě narazíme na tento problém:
Komponenty se v Nette standardně vytvářejí rozšířením UI\Control. Do presenteru se vkládají metodu createComponent<*>() která komponentu vytvoří v „lazy create“ režimu. Pokud komponenta nezpracovává signál, tak se vytvoří až když se vykresluje latte šablona akce, kde je komponenta vložena {control ‚myComponent‘}. To už je pozdě nastavovat layout.
Řešení:
Komponentu vložíme pomocí addComponent() rovnou v action<*>() a zavoláme nějakou metodu v komponentě která analogicky k presenteru se může jmenovat startup() a zde uděláme co je potřeba udělat před vykreslením:
public function actionUpdate(): void
{
$this->addComponent($this->myComponentFactory->create(), 'myComponent');
$this->getComponent('myComponent')->startup();
}
komponenta:
class MyComponent extends UI\Control
{
public function startup(): void
{
$this->getPresenter()->setLayout('.....');
}
}
Editoval m.brecher (17. 5. 1:36)
- Šaman
- Člen | 2659
Ale já nenastavuji layout presenteru, ale přímo té komponenty. Prostě
mám rodinu komponent, které mají všechny společný layout/wrapper a měním
jen jejich obsah. A ten soubor s layoutem nastavuji ve společném předkovi,
aktuálně jako proměnnou, kterou pak v komponentě použiju v rámci makra
{extends $layout}
.
Nakonec jsem se ale rozhodl toto ponechat a nenastavovat layout přímo
v kódu předka, protože když edituji samotnou šablonu, vidím ihned že
tahle patří do layoutu ({extends $layout}
) a budu používat
bloky. Zatímco jiné komponenty, které nepatří do této rodiny, si
zpracovávají celou šablonu samy.
- Kamil Valenta
- Člen | 815
Šaman napsal(a):
Prostě mám rodinu komponent, které mají všechny společný layout/wrapper a měním jen jejich obsah.
Úplně jsem ten use-case nezachytil, ale nechceš to řešit komponentou v komponentě? Pak nemusíš žádný „layout“ řešit, protože rozdílný vnitřek vykreslí vnitřní komponenta a společný „layout“ vykreslí vnější komponenta…
- Šaman
- Člen | 2659
Use case je stejný, jako u presenterů. Třeba chci u interaktivních
komponent vykreslovat flashmessage.
To mohu udělat buď v šabloně každé komponenty (jedna věc na mnoha
místech, špatné upravování), mohu si to vložit pomocí
{include}
(teď z hlavy nevím, jak si to rozumí se snippety,
což je zrovna u flashmessages důležité a navíc pomocí include neobalím
celý kód obsahu), nebo pomocí layoutu, což je i stejné řešení, jak se
podobné siyuace řeší v presenterech.
Pokud mám rodinu komponent, které mají být bootstrap panel, nadpis v hlavičce, pod tím blok pro flashmessages, následuje obsah a případně patička, tak je to myslím ukázkový příklad pro layout. Komponenta v komponentě tu nedává smysl, řekl bych.