Dokumentace dynamických snippetů
- llook
- Člen | 407
Dneska jsem se pokoušel dohledat a pochopit, jak se pracuje s dynamickými snippety a pak jsem to zkusil sepsat. Zvláštní poděkování si zaslouží vojtech.dobes.
Nejsem si jistý, jestli se v tom neplánují nějaké změny a taky příklad by se asi dal vymyslet lepší. Krom toho nedokážu naplnit požadavek zkrácení na čtvrtinu bez ztráty informační hodnoty. Mohla by se vypustit část o přidávání nových položek, ale já osobně jsem se právě na tom na chvíli zasekl, takže mi to pochopitelně připadá důležité.
Celá stránka o AJAXu by si podle mě zasloužila předělat, takže můj popis dynamických snippetů na ni ani moc nenavazuje, ale sám se na to teď nechystám. Předpokládám, že uživatel zná mimo jiné obvyklý postup pro zajaxování odkazů.
No nic, tady je můj návrh, připomínky vítány:
Dynamické snippety
Nette také umožňuje používání snippetů, jejichž název se vytvoří až za běhu – tj. dynamicky. Hodí se to pro různé seznamy, kde při změně jednoho řádku nechceme přenášet AJAXem celý seznam, ale stačí onen samotný řádek. Příklad:
<ul n:snippet="itemsContainer">
{foreach $list as $id => $item}
<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
{/foreach}
</ul>
Zde máme statický snippet itemsContainer
, obsahující
několik dynamických snippetů item-0
,
item-1
atd.
Dynamické snippety nelze invalidovat přímo (invalidace item-1
neudělá vůbec nic), musíte invalidovat jim nadřazený statický snippet
(zde snippet itemsContainer
). Potom dojde k tomu, že se provede
celý kód toho kontejneru, ale prohlížeči se pošlou jenom jeho
sub-snippety. Pokud chcete, aby prohlížeč dostal pouze jediný z nich,
musíte upravit vstup toho kontejneru tak, aby ostatní negeneroval.
V příkladu výše zkrátka musíte zajistit, aby při ajaxovém požadavku
byla v proměnné $list
byla pouze jedna položka a tedy aby ten
cyklus foreach
naplnil pouze jeden dynamický snippet:
class HomepagePresenter extends \Nette\Application\UI\Presenter
{
/**
* Zde je nějaká logika pro získání celého seznamu. Správně to patří do
* modelu, ale pro příklad to nebudu komplikovat.
* @return array
*/
private function getTheWholeList()
{
return array(
'První',
'Druhý',
'Třetí'
);
}
public function renderDefault()
{
if (!isset($this->template->list)) {
$this->template->list = $this->getTheWholeList();
}
}
public function handleUpdate($id)
{
$this->template->list = $this->isAjax()
? array()
: $this->getTheWholeList();
$this->template->list[$id] = 'Updated item';
$this->invalidateControl('itemsContainer');
}
}
Přidávání a mazání
Pokud přidáte novou položku a invalidujete itemsContainer
,
pak vám AJAXový požadavek sice vrátí i nový snippet, ale obslužný
javascript ho neumí nikam přiřadit. Na stránce totiž zatím není žádný
HTML prvek s takovým ID.
V takovém případě je nejjednodušší celý ten seznam obalit ještě jedním snippetem a invalidovat to celé:
{snippet wholeList}
<ul n:snippet="itemsContainer">
{foreach $list as $id => $item}
<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">update</a></li>
{/foreach}
</ul>
{/snippet}
<a class="ajax" n:href="add!">Add</a>
public function handleAdd()
{
$this->template->list = $this->getTheWholeList();
$this->template->list[] = 'New one';
$this->invalidateControl('wholeList');
}
Totéž platí i pro mazání. Sice by se dal nějak poslat prázdný snippet, jenže v praxi jsou většinou seznamy stránkované a řešit úsporněji smazání jednoho plus případné načtení jiného (který se předtím nevešel) by bylo příliš složité.
- Filip Procházka
- Moderator | 4668
Přesunuto na dev.
https://doc.nette.org/…ication/ajax,
tam se s tím bude lépe pracovat, než na fóru :)
Je to napsáno velice dobře. Pokud k tomu nebude nikdo nic mít, mohlo by se to zařadit do odpovídající sekce v dokumentaci.
Editoval HosipLan (17. 3. 2012 13:35)