Propagování CSS a JS souborů z komponent do šablon presenterů
- Ondřej Mirtes
- Člen | 1536
Ahoj,
začal jsem řešit problém, se kterým se dřív nebo později setká každý
Nettista – pokud použiju nějakou komponentu, která vyžaduje vlastní CSS
a Javascriptové soubory, je potřeba tyto soubory explicitně uvádět
u každého vykreslení této komponenty v šabloně presenteru. Což svádí
k chybám. Přirozené řešení by ale bylo, pokud by si tyto informace nesla
komponenta u sebe a ty soubory měla vedle zdrojového kódu třídy namísto
adresáře public nebo někde pohromadě v app/templates.
CSS/JS soubory mohu dát kamkoli mimo public díky WebLoaderu, to je v pohodě. Problém nastává se samotnou logikou zaregistrování těchto souborů. Zvolil jsem „probublání“, kdy potomek Control definuje metody addStyle a addScript, které uvnitř sebe volají rodiče a v Presenteru se ty soubory přidají do WebLoaderu.
addStyle/Script se v komponentě volají v metodě attached()
,
což je první moment, kdy je dostupný rodič komponenty. A kvůli systému
továrniček zde nastává jeden, zdá se, neprůchodný problém: Pokud
danou komponentu nijak nedonastavuji v presenteru mimo továrničku, tak se
vytváří a inicializuje až v době vykreslování šablony, což je
pozdě. Nevím, jak přesně uvnitř funguje systém bloků
v šablonách v Nette, ale zdá se, že layout se kreslí dříve, než
konkrétní šablona presenteru. Což je vzhledem k principu opačného
vykreslování divné, ale asi to tak bude. Zkrátka je WebLoader v momentě,
kdy se kreslí vnitřek tagu <head> v layoutu prázdný. Dokázal bych se
s tím smířit, pokud bych nějaký {widget}
měl přímo
v layoutu a tento případ řešil extra, ale pokud se jedná o konkrétní
šablonu nějaké akce, myslel jsem, že to fungovat bude.
Nemá někdo nějaký nápad, jak dosáhnout toho, co chci?
Co napadlo mě:
- V nějaké afterRender() metodě presenteru udělat cyklus nad všemi továrničkami a zinicializovat komponenty, o které se starají. Zkusil jsem to na jednom příkladě a začalo to fungovat, ale tohle řešení se mi nelíbí. Popírá to samotný princip továrniček (lazy inicializace) a je to overkill.
- Nějaký hack šablon, aby dělaly to, co chci já. Např. tento konstrukt do každé šablony pod {block #content}…{/block}, resp. do nějakého layoutu mezi konkrétními šablonami a velkým globálním layoutem:
{block #css}{include #parent}{/block}
{block #js}{include #parent}{/block}
Teoreticky by to mohlo inicializovat tyto bloky v rodičovském layoutu ještě před jeho samotným vykreslením a tudíž by se mohlo provést to, o co se snažím. Sice tento konkrétní příklad nefunguje, ale nějakým podobným způsobem by se toho docílit mohlo.
Díky.
- Panda
- Člen | 569
K těm šablonám – ona se skutečně nejdřív renderuje šablona view a
pak až šablona layoutu. Jenže to vypadá právě naopak kvůli blokům –
šablona view se projede a to, co je uzavřené do bloků, se nadefinuje jako
funkce. Až po vykonání této šablony se přejde k šabloně layoutu a
teprve v něm se nadefinované bloky vykreslí (tzn. například blok
content
se bude vykreslovat při
@{include #content}
).
Já osobně jsem to řešil ošklivě takto:
{title "Titulek"}
{touch myControl}
@{block #content}
{control myControl}
Makro touch
způsobilo inicializaci komponenty. Ale opět je tu
ten problém, že na to člověk musí myslet a není to „lazy“.
- Dr.Diesel
- Člen | 53
Panda napsal(a):
K těm šablonám – ona se skutečně nejdřív renderuje šablona view a pak až šablona layoutu. Jenže to vypadá právě naopak kvůli blokům – šablona view se projede a to, co je uzavřené do bloků, se nadefinuje jako funkce. Až po vykonání této šablony se přejde k šabloně layoutu a teprve v něm se nadefinované bloky vykreslí (tzn. například blok
content
se bude vykreslovat při@{include #content}
).Já osobně jsem to řešil ošklivě takto:
{title "Titulek"} {touch myControl} @{block #content} {control myControl}
Makro
touch
způsobilo inicializaci komponenty. Ale opět je tu ten problém, že na to člověk musí myslet a není to „lazy“.
Pro tenhle konkretni simple priklad co uvadis se mi render (capture)
konkretnich komponent vyresit podarilo, ale nelze zajistit fungovani
v podminkach / ridicich cyklech ({if},{for},{while},…) – Nevis totiz
predem jestli se renderovat bude, pripadne kolikrat.
https://forum.nette.org/…blanie-bloku?…
Cele to zavisi na pristupu k renderu samotne sablony, jak tu uz bylo popisovano (zhora dolu, nebo zevnitr ven – osobne jsem vyuzival zevnitr ven a vypis najednou, Nette renderuje zhora (zevnitr definuje jen funkce) ).
Editoval Dr.Diesel (16. 8. 2010 0:38)