V předchozí části seriálu o Nette Framework jsme nakousli téma fragmentů HTML, označovaných ve frameworku jako snippety. Jde o bloky, které kodér označí v HTML šabloně párovou značkou {snippet}…{/snippet}
a framework se už sám postará o to, aby při AJAXovém požadavku přenášel jen jejich obsah. Je poté na javascriptovém handleru, aby obsah snippetů vložil do aktuální stránky.
Protože snippetů může být ve stránce více, je možné je pojmenovat. Takto například vytvoříme snippet s názvem counter
:
{snippet counter}
Počet hlasů: {$count}
{/snippet}
Pozn.: pokud by to prospělo přehlednosti, je možné název vložit i do koncové značky.
Při běžném, tj. neAJAXovém, požadavku vygeneruje šablona tento HTML kód:
<div id="__counter">Počet hlasů: 23</div>
Jak vidíte, snippety se obalí do elementu div
, jehož id
tvoří název snippetu doplněný o dvě podtržítka. To aby se minimalizovala kolize s jinými id
ve stránce.
Pokud byste chtěli div
nahradit za jiný element, je možné jej specifikovat jako druhý parametr za názvem:
{snippet counter p}
Počet hlasů: {$count}
{/snippet}
Vygeneruje:
<p id="__counter">Počet hlasů: 23</p>
Toliko k běžnému požadavku. Nyní se naopak podívejme, jaká data se přenášejí při AJAXovém požadavku:
{"snippets":{"__counter":"Počet hlasů: 23"}}
Výstupem je datová struktura, označovaná jako payload, serializovaná do JSON řetězce. V tomto případě server vrátil asociativní pole (v řeči JavaScriptu je přesnější termín objekt) s jedním prvkem snippets
obsahujícím pole všech přenášených snippetů uložených jako pár ID a HTML kód.
Aktualizaci HTML stránky lze pak provést například tímto skriptem, který předpokládá přítomnost frameworku jQuery a proměnné payload
:
for (var id in payload.snippets) {
$("#" + id).html(payload.snippets[id]);
}
Které snippety přenášet?
Šablona může obsahovat spoustu snippetů. Jelikož Nette Framework je komponentově orientovaný, mohou se na stránce nacházet komponenty, jejichž šablony také obsahují snippety (přičemž samotný presenter není nic jiného, než speciální komponenta). Aby se při každém požadavku nepřenášely úplně všechny snippety, existuje ve frameworku mechanismus, jak určit, které přenést a které naopak vynechat. V řeči frameworku jde o odlišení neplatných a platných snippetů (neplatné se přenášejí). Ke zneplatnění slouží metoda invalidateControl(), jejíž volitelný parameter je název snippetu. Pokud parametr neuvedeme, znamená to, že se zneplatní celá komponenta a tedy všechny snippety. Obdobně pro validaci existuje metoda validateControl().
Příklad použití:
public function renderDefault()
{
$this->template->count = 23;
$this->invalidateControl('counter'); // snippet 'counter' se přenese
}
Nejen snippety živ je AJAX
Hned z kraje musím zmínit, že snippety představují jen vysokoúrovňový mechanismus, který vůbec nemusíte používat. To znamená, že můžete na výstup poslat jakýkoliv řetězec, ať už je to obyčejný HTML kód nebo serializovaná datová struktura. Přičemž pro datové struktury Nette Framework nabízí speciální podporu. Podívejme se na ni blíže.
Součástí presenteru je datové úložiště $presenter->payload
(pozn. ve starších verzích frameworku bylo dostupné metodou getAjaxDriver()
). Do tohoto úložiště můžete zapisovat jakákoliv data a presenter je nakonec pošle na výstup serializované, standardně jako JSON.
public function renderDefault()
{
$this->payload->count = 23;
$this->payload->show = TRUE;
$this->terminate(); // ukončí presenter
}
Vygeneruje:
{"count":23,"show":true}
Ano, přesně tohle úložiště využívají i snippety, zapisují svůj obsah do $presenter->payload->snippets[$id] = $html
. Samozřejmě lze zároveň používat snippety i zapisování uživatelských dat do $this->payload
. Framework odešle na výstup vše.
Našeptávač
Přikladem samostatného použití $presenter->payload
může být velmi jednoduchý našeptávač:
class AutoCompletePresenter extends Presenter
{
public function handleAutoComplete($text)
{
$this->payload->autoComplete = array();
$text = trim($text);
if ($text !== '') {
// načteme seznam států (pro jednoduchost ze souboru)
$list = file(dirname(__FILE__) . '/items.txt');
// vytvoříme seznam pro našeptávač
foreach ($list as $item) {
$item = trim($item);
if (strncasecmp($item, $text, strlen($text)) === 0) {
$this->payload->autoComplete[] = $item;
}
}
}
// činnost presenteru tímto můžeme ukončit
$this->terminate();
}
....
}
V šabloně bude textové políčko a na něj zavěsíme handler pro událost onkeyup. Ta zavolá výše uvedenou metodu pomocí {link autoComplete!}
a předá ji obsah políčka v parametru text
. Od serveru získá pole payload.autoComplete
, ze kterého seznam.
<p>Název státu: <input type="text" id="text" /></p>
<script type="text/javascript">
<!--
$('#text').focus().keyup(function(event) {
$.getJSON({link autoComplete!}, {'text': $('#text').val()}, function(payload) {
$('ul').remove();
var list = $('<ul></ul>').insertAfter('#text');
for (var i in payload.autoComplete) {
$('<li></li>').text(payload.autoComplete[i]).appendTo(list);
}
});
});
-->
</script>
Pokračování příště
Tím jsme s AJAXem ještě úplně neskončili. Bude mu věnovaný i příští díl.
Autor článku je vývojář na volné noze, specializuje se na návrh a programování moderních webových aplikací. Pravidelně pořádá školení pro tvůrce webových aplikací, vyvíjí open-source knihovny Texy, dibi a Nette Framework.
Přehled komentářů