Jak nastavit setLayout() u komponent?

Šaman
Člen | 2659
+
0
-

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
+
0
-

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.

Šaman
Člen | 2659
+
0
-

Aha. Takže ten presenter to dělá taky přes ten provider? Interní jsem myslel, že moc netuším co a jak dělá ten coreParentFinder, co je přesně referenceType atd.
Nicméně si to klidně copypastnu, potřeboval jsem vědět že jsem nic nepřehlédl a nedělám úplné blbosti. Díky.

David Grudl
Nette Core | 8218
+
0
-

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
+
-4
-

@Š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
+
0
-

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
+
0
-

Š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
+
0
-

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.