Block, který se poprvé neprovede, chceteli šablona blocku

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
mcmatak
Člen | 504
+
0
-

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

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

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

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

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

K čemu chcete definovat blok, když ho nechcete vypsat v aktuální/nadřazené šabloně?

JakubJarabica
Gold Partner | 184
+
0
-

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

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

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

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

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

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

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

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 z Users.@layout.phtml místo z @layout. Více násobná dědičnost je mocnou zbraní.

Trafil si klinec po hlavicke. Vdaka ;)

Honza Marek
Člen | 1664
+
0
-

Občas by se mi taky takovej šablonovitej blok hodil.

Oggy
Člen | 306
+
0
-

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)

redhead
Člen | 1313
+
0
-

mě už to napadlo kdysi dávno, když jsem ještě s nette začínal. Určitě by se mi to taky hodilo!

Honza Kuchař
Člen | 1662
+
0
-

A určitě by ten block měl umět přijímat parametry. (je to fce, takže to nebude žádný problém)

Jan Tvrdík
Nette guru | 2595
+
0
-

To umí snad už nyní, ne? {include #myBlock, a => 127, b => 'xyz'}

Vyki
Člen | 388
+
0
-

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)

jasir
Člen | 746
+
0
-

+1 Taky jsem se musel trošku nepohodlně drbat ;-)

Petr Motejlek
Člen | 293
+
0
-

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

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

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

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
+
0
-
  1. 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)
  2. 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)
  3. 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 | 8170
+
0
-

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 v Homepage.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
+
0
-

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

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

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á..