Minule jsem ukazoval, jak lze s Nette stavět statické stránky. Ne náhodou jsem začal právě tímto tématem. Statické stránky a technika „dědění“ jsou totiž základním pilířem budování webového sídla. Je na webovém architektovi, aby připravil návrh website, grafik společně s HTML kodérem mohou pilovat vizuální podobu stránek a programátor je oživuje. Nette plně podporuje tuto pokrokovou filozofii skupinového vývoje.

Upozornění: Článek se týká velmi staré alpha verze Nette Framework, současná syntaxe je jiná.

Troška terminologie nikoho nezabije

Začínáme se věnovat oživování stránek, opusťme tedy pojem „statické stránky“. Jen by nás mátl.

Nette podporuje stránky zapsané nejen v jazyce XHTML, ale i HTML a XML (např. RSS kanály). Místo neobratného „HTML-XHTML-XML stránky“ budu dále používat termín dokumenty.

Dokument je tvořen stromem elementů. Program může s touto hierarchií dále pracovat prostřednictvím tzv. DOM.

Základní jednotkou oživování dokumentů je komponenta. Jde o třídu (resp. objekt, podle kontextu), která je potomkem Component. Speciálním druhem komponenty je stránka (třída Presenter). Komponenty tvoří stromovou strukturu a jejím kořenem je vždy nějaký následník třídy Presenter. Tuto strukturu budu označovat jako COM. Nemá to nic společného s technologií COM od Microsoftu.

Všechny třídy v Nette mají prefix N – od PHP 5.3 leží ve jmenném prostoru Nette.

Trojí hierarchie

Pro rekapitulaci, ve hře jsou tři různé hierarchické struktury:

  1. Website, tedy hierarchie dokumentů
  2. strom XML/HTML elementů tvořících dokument
  3. strom komponent oživující dokument

Website je adresář obsahující dokumenty a případně i další podadresáře. Hierarchie, kterou mám v bodě č. 1 na mysli, však není tvořena rozdělením dokumentů do podadresářů, ale oním děděním popsaným v minulém díle!

Jak se oživuje dokument

Je třeba vytvořit nějakou hierarchii komponent a tu propojit s dokumentem. Pro začátek si vystačíme s nejjednodušší hierarchií, tvořenou jedinou komponentou, tedy komponentou stránky. A protože dokumenty jsou základním pilířem Nette, tam právě dokumentu musíme říci, kde je ukryt oživovací kód. K tomu použijeme hlavičku:

<?nette class="MyPage" ?>
<html>
<head>
	<title>Don't know...</title>
</head>

<body>
	<p>Hello World!</p>
</body>
</html>

V atributu class je přípustná i hodnota auto, pak bude název třídy určen automaticky z názvu stránky.

Třída MyPage může vypadat třeba takto:

<?php

class MyPage extends Presenter {

	function render($document)
	{
		$document->head->title = 'Nette example';
	}

}

Uvedený kód přes DOM přistupuje zpátky k dokumentu a změní obsah elementu <title>. Jednoduché, že?

Nyní ve stránce použijeme komponentu, třeba TGrid:

<?nette class="MyPage2" ?>
<html xml:lang="en" lang="en"
	xmlns="http://www.w3.org/1999/xhtml"
	xmlns:com="https://texy.nette.org/nette">
<head>
	<title>Nette demo</title>
</head>

<body>
	<com:TGrid id="grid1" />
</body>
</html>

A opět příklad MyPage2:

<?php

class MyPage2 extends Presenter {

	function render($document)
	{
		$document->getElementById('grid1')->atribut = 'hodnota';
	}

}

Dosud vše jasné? To je dobře. Možná si ale říkáte, proč jsem nepoužil zápis $this->grid1->.... Je to prosté. DOM a COM jsou dočista jiné struktury. Takže nyní prosím zpozorněte.

Vazba DOM ↔ COM

Zatímco COM reflektuje potřeby programátora, DOM tvoří HTML kodér. Dva naprosto neslučitelné zájmy. A Nette jim dopřává maximální volnost. Tedy, pokud totálně překopu vzhled stránky, změním tím k nepoznání DOM. Ale je nutné, aby kvůli tomu programátor musel předělávat aplikaci? Ne! Programátor má své COM a to se mu nezměnilo.

Příklad: tvoříme blog.

Nejprve pohledem programátora: Titulní stránku představuje pět článků a nějaký stránkovací mechanismus pro přístup k dalším článkům. Na to se nám výborně hodí komponenta TDataGrid. Jde o jeden logický celek, který plně zvládne požadovaný úkol. Programátor si ho v COM zpřístupní pod názvem grid1, tedy $this->grid1. V metodě initialize() ho napojí na zdroj dat a nastaví stránkování po pěti záznamech.

A nyní pohledem webdesignera: Komponentu DataGrid tvoří dva grafické celky:

  • zobrazení záznamů, v našem případě jednotlivých článků
  • zobrazení „stránkovátka“

Nette není tak hloupé, aby obojí zobrazovalo napevno za sebou. Naopak – každý z těchto celků si můžeme umístit libovolně na stránce. Ba co víc – webový architekt usoudí, že stránkovátko by mělo být nejen na spodku stránky, ale i nahoře. Ovšem to horní by mělo být méně výrazné, že.

Dejme si to dohromady. Máme komponentu TDataGrid. Ta nabízí dvě renderovací polohy, říkáme jim parts. Jednu z těchto poloh chceme na stránce zobrazit dvakrát. Dále víme, že konkrétní instance této komponenty se jmenuje grid1.

Jak bude vypadat HTML kód?

<?nette class="MyPage3"?>
<html>
<head>
	<title>Blog</title>
</head>

<body>
	<h1>The best blog</h1>
	<div>
	<com:DataGrid.pager name="mygrid" id="horni" />

	<hr />

	<com:DataGrid.items name="mygrid">
		 ...
		 ...
	</com:DataGrid.items>

	<h3>Dále pokračujte:</h3>

	<com:DataGrid.pager name="mygrid" />
	</div>
</body>
</html>

Jedna komponenta v COM, tři zobrazení v dokumentu. Spojuje je atribut name. Tím, že jsem horní „stránkovátko“ opatřil id, mohu s ním dále pracovat prostřednictvím DOM. A třeba nastavit mu menší provedení, jak požadoval grafik.