Nápad na práci s Latte pomocí „vizuálních komponent“

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

Kdybych pracoval více na frontendu – a tedy se šablonami – chtěl bych si vytvářet malinké vizuální komponenty, které bych skládal do velkých celků. Chtěl bych si třeba nadefinovat vzhled submit tlačítek a mít je konzistentní v celé aplikaci. Chtěl bych být odstíněn od jmen *.latte souborů a adresářové struktury, chtěl bych pracovat se jmennými prostory.

<n:base:submitButton caption>
	<p class="foo"><input type="submit" class="bar" value="{$caption}"/></p>
</n:base:submitButton>

{* Párové tagy by komponentu definovaly, pomocí nepárové tagu by se komponenta používala. *}

<n:base:address address>
	<p>Ulice: {$address->street}</p>
	<p>ČP: {$address->houseNumber}</p>
	<p>...</p>
</n:base:address>

{* ------- *}

<n:company:detail company>
	<p>Název společnosti: {$company->name}</p>
	<n:base:address address={$company->address}/>
</n:company:detail>

{* ------- *}

<h1>Detail firmy</h1>
<n:company:detail company={$company}/>

{* Se jmennými prostory potom například takto: *}

<n: namespace="company"/>
<n: use="base:address"/>
<n: use="base:submitButton"/>
{* <n: namespace="company" use="base:address" use="base:submitButton"/> *}

{* a pak tedy jen *}

<n:detail .../> {* company:detail *}
<n:submitButton .../> {* base:submitButton *}

Nechtěl bych tedy řešit, v jakých souborech jsou komponenty definovány, ale v jakých jmenných prostorech jsou definovány. (Mohly by se tedy definovat i pomocí PHP pro širší možnosti.)

Kdybych chtěl vykreslovat formulář, nechtěl bych to řešit přes nějaký defaultní renderer, který bych, pokud by nevykreslil formulář podle mých sofistikovanějších představ, musel vykreslovat ručně (a na polovině z nich zapomenout vypisovat $form->errors). Chtěl bych si nadefinovat komponenty pro nějaké typické výchozí způsoby (inline formuláře, do tabulky, labely vs pouze placeholdery) a mít možnost nějak elegantně řešit drobné rozdíly.

<n:company:form:employee form>
	<p><n:base:input value={$form['firstName']}/> <n:base:input value={$form['lastName']}/></p>
	{* dále už po řádcích *}
	<n:base:form form={$form} exclude={['firstName', 'lastName']}/>
</n:company:form:company>

Co si o tom myslíte?

Michal III
Člen | 83
+
0
-

Není to pouze o formulářích, těch se to týká pouze tím způsobem, že pomocí těchto „vizuálních komponent“ bychom si základní vzhled formulářů definovali v šabloně pomocí Latte a ne takto. Navíc bychom už v šabloně viděli, jakým způsobem je formulář vykreslován, a mohli bychom se až v šabloně rozhodnout, jakým způsobem ho chceme vykreslit (To je trochu ekvivalent toho poděděného, který bych osobně řešil spíše nějakou funkcí, která nám tomu formuláři nastaví požadovaný renderer – $form = new Form; $this->setMyRenderer($form);). Řekne nám trochu víc toto:

<n:base:form form="addEmployee"/>

než toto:

{control addEmployee}

Ale to je opravdu jen okrajová část tohoto návrhu. Když jsem narazil na toto vlákno, nelíbilo se mi z navrhovaných řešení ani jedno. Představoval bych si, že by v aplikaci těchto komponent bylo hodně a neumím si představit, že by pro každý znovupoužitelný odkaz/tlačítko/… vznikala samostatná komponenta (tedy komponenta + interface pro DI + registrace v configu + továrnička např. v presenteru).

A „includování“ nějakého bloku… kde by měl být tento blok definován? Buď někde v nadřazeném @layout, kde podle mě nemá co dělat, nebo v nějakém jiném souboru a v tu chvíli bych se musel starat o to, jakým způsobem ho do šablony „includuju“ (specifikace cesty k souboru).

Třeba mi něco uniká, ale můj návrh se mi zdál docela zajímavý. Když má Latte n:atributy, proč by nemohlo mít n:tagy.

Myiyk
Člen | 321
+
0
-

Chápu co myslíš

Jestli chceš podobným způsobem pracovat s aktuálním nette, můžeš si definovat blok a potom ho používat.

Soubor components.latte

{define button}
	<a class="....." href="{$link}">{$text}</a>
{/define}

V šabloně, kde to chceš použít:

{include 'components.latte'}{* soubor kde jsou definice *}

{include button, link => "...", text => "abc"}

edit: aha, sorry, nevšiml jsem si že tohle nechceš

Editoval Myiyk (4. 9. 2014 20:18)

Myiyk
Člen | 321
+
0
-

Při použití párového tagu by bylo docela nepraktické psát ten název dvakrát (začátek a konec).
Při definici bloku se taky jeho název nepíše dvakrát.

Spíš bych to viděl na něco jako

<n:base:address>
    <p>...</p>
</n:tag>
  ... nebo ..
</n:block>

A nějak nechápu, proč do toho tagu psát proměnné, které se budou používat. (Bloky to taky nepotřebujou)

Tenhle nápad se mi docela zamlouvá, a nebylo by snad tak složité to naprogramovat, když to má úplně stejnou funkčnost jako bloky, ale pouze s jinou syntaxí. Takže by takováhle html syntaxe mohla spolupracovat s běznými bloky.

A v @layout by šlo použít

	<n:content />
Michal III
Člen | 83
+
0
-

ad párové tagy: Zas až tak nepraktické to není (editory umí vygenerovat z názvu celý párový tag – např. Emmet). Usnadňuje to orientaci a odpovídá to xml specifikaci. Nicméně na této drobnosti by asi zas tolik nezáleželo. O tom bych diskutoval, až by byla přijata ta základní myšlenka. Asi bych ani k takové zkratce nic neměl – teoreticky by se to mohlo týkat všech tagů v Latte (např. <div><p></></>), já osobně bych to ale nepoužíval.

ad specifikace atributů: Opět je to už víceméně detail, nicméně díky tomu by bylo od pohledu hned jasné, na čem ten blok závisí. Mohly by se specifikovat povinné a nepovinné atributy (nepovinné by měli např. určenou výchozí hodnotu). Dokonce by si atributy mohly klást podmínky na určité typy proměnné (array, DateTime…).


Ovšem jako hlavní přínos vidím v použití jmenných prostorů a v tom, že bych se nemusel starat o vkládání hledání cesty, kde jsou ty které bloky definovány. Aktuální bloky v Latte fungují velice dobře co se týče dědičnosti (např. určení výchozího obsahu v @layout). Tyto vizuální komponenty by byly zase pro kompozici.