Block, který se poprvé neprovede, chceteli šablona blocku
- mcmatak
- Člen | 504
Určitě znáte ten případ, kdy se třeba definice nějakého řádku v tabulce neustále opakuje, třeba 20× na stránce, nebo jen určitá část kódu, pochopitelně se bavíme o šablonách.
V takovém případě to budete řešit přesunutím kódu do externího souboru a budete volat include. Nebo si při prvním použití toho vytvoříte block a ten includujete obdobně. Už jen proto, aby když potřebujete něco na dvou řádcích změnit, aby jste to nemuseli dělat 20×. Např. přidat class nebo něco takového.
Jenomže dost často se stane, že block potřebujete použít dříve než ho definujete, protože prostě ve formuláři přibyde prvek který má být první atd. Dále je to taky docela nepřehledné, protože bloky jsou někdě uvnitř kódu.
Nebylo by lepší si ho definovat na začátku souboru? Na začátku šablony? A pak už jen používat. Je tedy potřeba zajistit, aby se poprvé neprovedl.
Jinak funkce zůstává, stačilo by pouze vytvořit syntaxi.
Např.
{templateblock}
{tblock}
{definitionblock}
{dblock}
{preparedblock}
{pblock}
- Ondřej Mirtes
- Člen | 1536
Zkus se líp vyjádřit a uvést nějaký příklad – mám za to, že současný systém bloků umí všechno :)
- Petr Motejlek
- Člen | 293
Já se přidávám, mě taky není úplně jasné, o čem tu mluvíš ;). Skoro mi ale přijde, že by ti spíš pomohla nějaká komponenta, který by ty dva řádky dvacetkrát vyrenderovala ;).
- Jan Tvrdík
- Nette guru | 2595
Jestli jsem to dobře pochopil, tak chce mít možnost vytvořit takový block, který se automaticky nevypíše. V současnosti se totiž {block} přeloží jako definice bloku + include (záleží, zda šablona extenduje jinou). Možnost pouze definice není. S Vítkem na to každou chvíli nadáváme. Akorát jsem si ještě neujasnil, jestli je to chyba mého návrhu nebo nedostatek Nette.
- PetrP
- Člen | 587
JJ taky bych to občas potřeboval, většinou jen pro přehlednost šablony.
Myslím že implementačně to není problém, prostě by existovalo další macro které by přidalo block, ale nezavolalo potom include jako jsou kolem tohodle řádku
- Ondřej Mirtes
- Člen | 1536
K čemu chcete definovat blok, když ho nechcete vypsat v aktuální/nadřazené šabloně?
- JakubJarabica
- Gold Partner | 184
Hurá, toto vlákno mi prišlo presne do rany. Riešim podobný problém, aj
ho rozpíšem:
Mám UzivatelPresenter, v ktorom mám renderStream, renderInfo,
renderAlbumy(hrám sa s takým customised FB návrhom). V každej z týchto
šablón by som rád mal dva stĺpce(div id lavy, div id pravy). Ľavý stĺpec
by mal obsahovať rovnaké údaje pre všetky tieto rendery(napr. fotku, karmu,
mesto). Je mi však trošku proti vôli a DRY, aby som do každého z týchto
templatov kopíroval ten istý blok s divom lavy, najmä, keď tých renderov
bude ešte viac a budem potrebovať zmeniť jeden link. Riešenie by bolo
použiť vlastný @layout pre celý UzivatelPresenter, ale tým by sa mi
zase zduplikovalo všetko z layoutu(čo sa mi tiež 2× nepáči). Ideálny
spôsob, akým by som si to predstavoval je mať nejaký block(ktorý by
obsahoval div id lavy), ktorý by som vždy len do templatu vložil miesto
daného divu a tým pádom by som to mal dostupné všade, kde mi to
treba(volaním toho bloku) a bolo by to editovateľné z jedneho miesta(kde by
som to ale napchal?). V takomto prípade by sa mi ani neduplikoval
@layout ani nerobil veľa kópií div id lavy. Vie ma niekto naviesť?
Ideálne s čo najkonkrétnejším príkladom, už asi mesiac mám
v záložkách prednášku o šablónach, no čas zatiaľ nie je.
Vďaka :)
- Jan Tvrdík
- Nette guru | 2595
Ondřej Mirtes napsal(a):
K čemu chcete definovat blok, když ho nechcete vypsat v aktuální/nadřazené šabloně?
Představ si soubor blocks.phtml, který obsahují hromadu užitečných
bloků = funkcí (např. na flash messages).
V jakékoliv šabloně pak stačí zavolat
{include 'blocks.phtml'}
a svoje oblíbené bloky = funkce = kusy
kódu máš hned po ruce.
I v jedné šabloně ale občas narážím na potřebu (= bylo by to hezčí, čitelnější, možná čistší) definovat blok bez nutnosti jeho vypsání.
Představ si, že by v PHP každá definice funkce byla přeložena jako definice + volání. Proč bys přece definoval funkci, když ji nechceš použít, že? :)
- mcmatak
- Člen | 504
jan tvrdík, petrp … myslím, že tak jak to popsali to je ono
<?php
{block #rowControl}
<?php if (!isset($rowControl)) return; ?>
<div class="row {if $rowControl->getOption('required')}required{/if}">
<table>
<tr>
<th>{$rowControl->label}:</th>
<td>
{$rowControl->control}
<p class="small" n:ifset="$rowControl->options['description']">{$rowControl->options['description']}</p>
</td>
</tr>
</table>
</div>
{/block}
{include #rowControl, rowControl => $form['user']}
{include #rowControl, rowControl => $form['password']}
{include #rowControl, rowControl => $form['retypePassword']}
ano prostě chci block jen definovat a ne provést a jestli vůbec se někdy provede to děj se vůle boží, třeba ho zahodím, ale kolikrát k blocku potřebuji nějaký comment a chci si ho prostě uklidit nakonec sablony apod.
?>
- Jan Tvrdík
- Nette guru | 2595
JAM3SoN napsal(a): Vie ma niekto naviesť?
Nečetl jsem to celé, je to moc dlouhé :)
Zkus vytvořit Users.@layout.phtml
, který bude extendovat
hlavní layout (makro extends). Všechny pohledy pak budou dědit z
Users.@layout.phtml
místo z @layout
. Více násobná
dědičnost je mocnou zbraní.
Editoval Jan Tvrdík (21. 1. 2010 13:34)
- Ondřej Mirtes
- Člen | 1536
Pokud chci definovat blok bez jeho vypsání v místě definice, tak ho nepíšu dovnitř {block #content}, ale nad něj :)
Pokud chci mít po ruce kusy šablon, můžu si vytvořit X souborů .phtml.
- Jan Tvrdík
- Nette guru | 2595
PetrP napsal: Myslím že implementačně to není problém.
Vím. Dokonce i o tom konkrétním řádku, který to include volá. Chtěli jsme to s Vítkem řešit na pražské Poslední sobotě, ale z té jaksi nic nebylo. A vlastní makro jsem si ještě nenapsal, protože mě v ten okamžik nenapadlo dobré jméno, jak by se to makro mohlo jmenovat :)
- Jan Tvrdík
- Nette guru | 2595
Ondřej Mirtes napsal(a):
Pokud chci definovat blok bez jeho vypsání v místě definice, tak ho nepíšu dovnitř {block #content}, ale nad něj
To, zda se automaticky vypíše nebo ne závisí na tom zda šabloně od někoho dědí, čehož lze v určitých případech skutečně „zneužít“ k definici makra, které nechci automaticky vypsat. Bohužel zdaleka ne vždy.
Pokud chci mít po ruce kusy šablon, můžu si vytvořit X souborů .phtml.
Což, jak určitě víš, bude pomalejší než mít jeden soubor s nadefinovanými 20 bloky.
U implementace je (pokud vím) jediný problém, že includnutím souboru neincluduji definice bloků v něm obsažených. To by se muselo nějak pořešit.
Editoval Jan Tvrdík (21. 1. 2010 13:40)
- JakubJarabica
- Gold Partner | 184
Jan Tvrdík napsal(a):
JAM3SoN napsal(a): Vie ma niekto naviesť?
Nečetl jsem to celé, je to moc dlouhé :)
Zkus vytvořit
Users.@layout.phtml
, který bude extendovat hlavní layout (makro extends). Všechny pohledy pak budou dědit zUsers.@layout.phtml
místo z@layout
. Více násobná dědičnost je mocnou zbraní.
Trafil si klinec po hlavicke. Vdaka ;)
- Oggy
- Člen | 306
Přikláním se také k nějakému makru blocku bez výpisu…
Pro příklad..flashmessage chci mít na všech stránkách. ale pro každý
„typ“ stránky (pro každý presenter) umístěné jinde.
= vytvořím v layoutu nevypisovatelný block flash ..
a v jednotlivých šablonách presenterů jej includuji..
Nyní to dělám tak, že základní layout .. je ještě rozšiřován např. classic.layout, 2row.layout atd.. a jednotlivé šablony actionů rozšiřují určitý typ layoutu. tzn. pokud v classic a 2row layoutech jsou flash umístěné jinde..definuji je dvakrát.
Editoval Oggy (21. 1. 2010 17:39)
- Honza Kuchař
- Člen | 1662
A určitě by ten block měl umět přijímat parametry. (je to fce, takže to nebude žádný problém)
- Vyki
- Člen | 388
Oggy napsal(a):
Přikláním se také k nějakému makru blocku bez výpisu…
Pro příklad..flashmessage chci mít na všech stránkách. ale pro každý „typ“ stránky (pro každý presenter) umístěné jinde.
Tak v tomto rozhodně souhlasím. Taky to teď řeším dost oklikou, což není zrovna moc „cool“.
Editoval Vyki (21. 1. 2010 22:04)
- Petr Motejlek
- Člen | 293
Já jsem asi mimo. Mě pořád přijde, že chování, které všichni požadujete, už dneska můžete řešit přes komponenty. A k tomu snad i existují, nebo ne? Když chci na všech stránkách vypisovat flash zprávy, ale pokaždé jinde, udělám si BasePresenter, do kterého přidám továrničku createComponentFlashMessagesRenderer(), tak si zajistím, že se k té komponentě vždycky dostanu ze všech presenterů. Vytvořím si control FlashMessagesRenderer, který bude mít za úkol vyrenderovat ten stejný výpis flash zpráv. Potom si do všech šablon presenterů, ve kterých chci ty flash zprávy vypisovat, vložím {control flashMessagesRenderer} tam, kde chci ten výpis mít, a mám to, co tu popisujete ;).
Přiznávám, že to může být zdlouhavější, ale zdá se mi to daleko čistší, než přístup jedenVelkýSouborProVšechnyBlokyKteréKdyBuduPotřebovat.phtml ;). Komponenty jsou objektové, ten ohromný soubor, je spíš procedurální. Jářku, začíná mi to připomínat samotné PHP, kde se obojí taky velmi ohyzdně míchá ;).
P. S.: Kdyby někdo opravdu toužil po ohyzdném ohromném souboru, může udělat tu komponentu tak, že do ní naháže víc renderNěco metod, a pak je volat přes {control myControl:něco}, to by hodně připomínalo to, co se pokoušíte udělat ;).
- Ondřej Mirtes
- Člen | 1536
Mně to taky přijde jako blbost. Co když najednou budete chtít ten blok, který máte v nějakém odkládacím souboru, chtít vložit, ale pod jiným názvem? Např. v souboru pro inkludování máte {block news}, ale šablony máte navržené tak, že to potřebujete vložit namísto {block currentNews}. Nebo to potřebujete vložit do bloků, co se různě jmenují. A jste nahraní.
Vytvořte si na ty obvyklé věci komponenty. K tomu slouží.
- Panda
- Člen | 569
Myslím, že jste se trochu odklonili od původního úmyslu a možná proto vám to připadá jako blbost. Pokud jsem to správně pochopil, tak mcmatakovi původně šlo o definici a znovupoužití bloku v rámci jedné komponenty a vadilo mu, že když ten blok nadefinuje, tak se rovnou vypíše. S tím samozřejmě žít jde, ale kamenem úrazu je fakt, že tomu bloku, který je jako první nadefinovaný, nelze předat parametry, takže se tam s těmi hodnotami musí pracovat trochu jiným způsobem (tzn. tahat z globálního kontextu šablony). Jako bonus vzniká fakt, že vykreslení 4× v podstatě stejné věci se dělá dvěma různými způsoby: poprvé definicí a pak 3× include.
A řešení přes komponenty by v některých případech nebylo moc elegantní. Kupříkladu k vykreslení takového diff-datagridu (2 stejné tabulky vedle sebe) o 2×100 řádcích by se muselo vytvořit 200 subkomponent (což je mírný overhead). A nebo includovat 200× jeden soubor…
Editoval Panda (22. 1. 2010 14:19)
- Jan Tvrdík
- Nette guru | 2595
Petr Motejlek napsal(a): Mě pořád přijde, že chování, které všichni požadujete, už dneska můžete řešit přes komponenty.
Ty na výkon aplikace moc nehledíš, že? (viz např. Panda a příklad s DataGridem)
Ondřej Mirtes napsal(a): Co když najednou budete chtít ten blok, který máte v nějakém odkládacím souboru, chtít vložit, ale pod jiným názvem?
Máš ve zvyku si vytvářet funkce, které chceš volat jiným názvem, než který jsi jim dal?
Editoval Jan Tvrdík (22. 1. 2010 18:13)
- mcmatak
- Člen | 504
- komponenta a mnoho renderů, to ale přece znamená pro každý render vytvořit šablonu a to si přece mohu rovnou vytvořit šablonu a tu naincludovat, co s tím mají společného komponenty (přece mi nic neulehčí od ničeho nepomůžou)
- 100× include té samé šablony by prý nemělo na výkon mít vliv, šablona se do paměti načte pouze jednou (resp. soubor)
- pominemeli zbytečné vatváření a includování dalšího souboru (což na výkon asi nebude mít příliš vliv i při deseti zbytečně vytvořených šablonách), tak oproti blokům má toto nevýhodu hlavně v předání proměnných, které se jinak musí získávat z kontextu šablony, což není košér, protože se mohou změnit a nikdo nikdy nezjistí kdo se na ně spoléhal, přijde mi to hodně nečisté z tohoto hlediska
pokud vám přijde že tohle není reálná potřeba tak myslím, že i blocky nejsou potřeba a dá se jejich funkčnost celkem úspěšně simulovat opět includováním souborů
pokud se to pojmenuje jinak nijak vás nemusí ani trápit wtf faktor
- David Grudl
- Nette Core | 8218
Několik poznámek:
- v podstatě něco takového jsem chtěl do frameworku přidat už dříve
pod makrem
{makro ...}
, s tím, že i řada výchozích maker by se definovala v .phtml souboru; tímto by šlo definovat „blok“, který by se nemusel volat přes{include #row}
, ale v podstatě přímo přes{row ...}
. Zatím to není realizované, protože zvažuju, jak přijímat parametry. - používání více souborů nemusí mít negativní vliv na rychlost, makro
{include 'part.pthml'}
může jednodušší šablony rovnou vkládat do obsahu volající šablony - naopak hromadění bloků v jednom souboru může mít docela negativní
vliv na přehlednost. Kolikrát si říkám, jestli by nebylo elegantnější
implementovat přepisování tak, že místo
Homepage.default.phtml
s definicí tří bloků na top úrovni, které vlastně nemají nic společného, by se dohledávaly a načítaly např.Homepage.default.content.phtml
,Homepage.default.style.phtml
,Homepage.default.sidebar.phtml
vždy s jedním top-level blokem, čímž by v těchto souborech nebylo ani třeba použít obalovací makra{block} {/block}
. Jen třeba vHomepage.default.content.phtml
by byl kolem nadpisu{block title}
. {include 'bloky.pthml'}
nenačte seznam bloků, protože by vznikl bordel, tahle je každý soubor svým jmenným prostorem.
- Petr Motejlek
- Člen | 293
Jan Tvrdík napsal(a):
Petr Motejlek napsal(a): Mě pořád přijde, že chování, které všichni požadujete, už dneska můžete řešit přes komponenty.
Ty na výkon aplikace moc nehledíš, že? (viz např. Panda a příklad s DataGridem)
Já nemusím, navrhuju si to tak, aby to bylo rychlé, a bylo s tím nejméně práce… ;)
Nakonec po dlouhém přemýšlení vidím ty bloky ve smyslu funkcí jako použitelné přesně pro to, co popisujete. To, co bych dneska řešil komponentou, která má jednu šablonu a neprovádí žádné výpočty, prostě jen do té šablony pošle data a vykreslí jí, by takové funkční bloky hezky vyřešily. Jen si myslím, že je škoda, že musíme hledat takový řešení… :(
Editoval Petr Motejlek (22. 1. 2010 21:27)
- Jan Tvrdík
- Nette guru | 2595
David Grudl napsal(a):
v podstatě něco takového jsem chtěl do frameworku přidat už dříve pod makrem
{makro ...}
To by část problémů určitě řešilo.
používání více souborů nemusí mít negativní vliv na rychlost, makro
{include 'part.pthml'}
může jednodušší šablony rovnou vkládat do obsahu volající šablony
Tak to ale nyní nefunguje, ne?
Kolikrát si říkám, jestli by nebylo elegantnější implementovat přepisování tak, že (…) by se dohledávaly a načítaly (…)
Už docela dávno mě napadlo, že by mohl existovat nějaký „BlockAutoLoading“, který by se spouštěl v případě, že se nepodaří blok najít.
- redhead
- Člen | 1313
nyní mě zaskočila jedna věc. U svého jednoduchého datagridu bych rád použil filtery pro nějaké sloupce (myslím že to má i ‚oficiální‘ DataGrid ne?), zatím to píšu natvrdo v továrničce, tak že přiřazuju callbacky k metodám presenteru (nameFilter, timeFilter, linkFilter, …), ale to se mi nelíbí, hlavně kvůli nepřehlednosti a prasení v php místo v šablonách. Pokud bych měl tyhle „callable“ bloky mohl bych je vytvářet v šabloně a volat jako {include $filterName}. Jak byste to řešili teď? Nic jednoduchýho mě nenapadá..