Dokumentace dynamických snippetů

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

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

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)