Dynamické snippety v „dynamických“ snippetech ve verzi 2.0

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

Ahoj, úspěšně jsme s naším startupem přešli na nette 2.0, kde jsem konečně zprovoznil dynamické snippety, mám však problém. Abych byl konkrétní, dejme tomu že zobrazuju nějaké příspěvky a u každého je bodové hodnocení a komentáře. Když však udělám dynamické snippety, jak jsem našel zde na fóru v jednom příspěvku od Davida, tedy:

{snippet dynamic_wall}
   {foreach $dops as $dop}
    {snippet dynamic_wall-$dop[uniId]}
	// vypsání počtu hlasů
	//vypsání příspěvku
	// vypsání komentářů
    {/snippet}
   {/foreach}
{/snippet}

, přičemž při invaidaci do pole $dops posílám jen jeden řádek, který je třeba překreslit (k mému údivu, jak to může fungovat) tak vše opravdu funguje – a řádově rychleji. Pořád to však přináší potřebu načítání nějakých dat, která se nemění, ale hlavně reload tohoto neměnného obsahu (ačkoliv oproti nutnosti načítání VŠECH příspěvků je to pokrok). Potřeboval bych docílit chování, kdy když odešlu hlas, tak se refreshne opravdu jen div s hlasama, protože pak nejen, že nemusím načítat obsah celého příspěvku znovu, hlavně se mi potom nevymaže např rozepsaný comment, který je ve stejném snippetu nebo nevypne přehrávané video v příspěvku. Napadlo mě udělat to takto:

{snippet dynamic_wall}
   {foreach $dops as $dop}
    {snippet dynamic_wall-$dop[uniIdLikes]}
	// vypsání počtu hlasů
    {/snippet}
	//vypsání příspěvku
    {snippet dynamic_wall-$dop[uniIdComments]}
	// vypsání komentářů
    {/snippet}
   {/foreach}
{/snippet}

přičemž po invalidaci posílám potřebné pole, ve kterém je vždy !empty buď ono $dop[uniIdLikes], nebo $dop[uniIdComments] – a čekal jsem, že se tedy refreshne jen "pod"snippet s tímto id v názvu, ale evidentně to funguje jinak než jsem si představoval a refreshne to všechny snippety v dané iteraci foreache, nikoliv jeden.

Rozumíte někdo už plně těm novým snippetům, abyste mě mohli nakopnout, jak docílit požadovaného chování?

Díky moc za každou radu, T.

Editoval Why?! (21. 9. 2011 0:27)

hAssassin
Člen | 293
+
0
-

mam pocit ze jsem nekde (ale fakt netusim kde) cetl, ze se pri invalidaci subsnippetu invaliduji vsechny nadrazene snippety. Ale ruku do ohne bych za to nedal :-)

EDIT: jo uz vim, kde, tady, ale nejsem si jisty jestli tomu uplne dobre rozumim: Komponenta je „invalidní“ i tehdy, pokud je invalidní některá její subkomponenta.

Editoval hAssassin (21. 9. 2011 0:47)

Why?!
Člen | 15
+
0
-

No, možná jsem trochu natvrdlý, ale vůbec nemám ponětí, jakým způsobem to řeší můj poblém, krom pocitu, že „to takhle nejde“, nette nepodporuje nebo to bude složitý :-) V tom manuálu na snippety není ani zmínka o těch dynamických ani o tom, jak „zabránit“ invalidaci dyn. sn., nebo lépe, jak vynutit invalidaci jen jednoho z více dyn. snippetů (s rozdílným dyn. id) vyskytujících se v jedné iteraci foreache. :(

EDIT: ještě mě napadlo udělat to snippetem ve snippetu a v těchto dvou dát dyn. snippety ale pokaždé s jiným názvem, jenže to mi v latte hodí error :(

{snippet dynamic_likes}
{snippet dynamic_comments}
   {foreach $dops as $dop}
    {snippet dynamic_likes-$dop[uniId]}
        // vypsání počtu hlasů
    {/snippet}
        //vypsání příspěvku
    {snippet dynamic_comments-$dop[uniId]}
        // vypsání komentářů
    {/snippet}
   {/foreach}
{/snippet}
{/snippet}

Editoval Why?! (21. 9. 2011 1:57)

nanuqcz
Člen | 822
+
0
-

Podle mě bude řešení někde v přepsání jquery.nette.js, aby přepisoval jen obsah snippetů v nejnižší úrovni. Není to univerzální řešení, ale tvůj problém by to asi vyřešilo.

Aurielle
Člen | 1281
+
0
-

Potřebuješ k něčemu „vnější“ snippety dynamic_wall a dynamic_comments? Jestli ne tak pryč s nimi, a funguje ti to tak, jak potřebuješ… Akorát musíš invalidovat přímo konkrétní snippet tak, jak sis ho pojmenoval.

studna
Člen | 181
+
0
-

Dynamické snippety musí být obalené do statického snippetu, nebo ne?

nanuqcz
Člen | 822
+
0
-

Taky jsem tu někde od Davida četl, že dynamické snippety musí být obalené ve statickém. Ale pokud to už není pravda, bylo by to super :-)

Aurielle
Člen | 1281
+
0
-

No já dynamické snippety prozatím nepotřeboval, takže moje rada je jen střelená od boku. Pokud ale definice snippetu projde normálním PHP parserem a vyleze z toho čistý string tak bych v tom neviděl problém :)

Ot@s
Backer | 476
+
0
-

xxxObiWan napsal(a):

Taky jsem tu někde od Davida četl, že dynamické snippety musí být obalené ve statickém. Ale pokud to už není pravda, bylo by to super :-)

Ne, dynam. snippety musí být obalene statickým snippetem (2beta z 24.8.). Jinak laděnka hodí hlášku, že statický obal chybí.

Why?!
Člen | 15
+
0
-

gmvasek napsal(a):

Potřebuješ k něčemu „vnější“ snippety dynamic_wall a dynamic_comments? Jestli ne tak pryč s nimi, a funguje ti to tak, jak potřebuješ… Akorát musíš invalidovat přímo konkrétní snippet tak, jak sis ho pojmenoval.

Ot@s napsal(a):

Ne, dynam. snippety musí být obalene statickým snippetem (2beta z 24.8.). Jinak laděnka hodí hlášku, že statický obal chybí.

Právě proto tato varianta také nefunguje :( Mám to nahlásit jako chybu, nebo někdo ví způsob, jak na to?

Editoval Why?! (26. 9. 2011 13:06)

Ot@s
Backer | 476
+
0
-

Why?! napsal(a):
Právě proto tato varianta také nefunguje :( Mám to nahlásit jako chybu, nebo někdo ví způsob, jak na to?

Chyba to asi není. Viz ukázka jako pokus o odpoved – jedno kliknuti vynutí změny 2 částí (snippetů) v šabloně (předpokladem je mít v layoutu všechny JS knihovny pro podporu AJAXu v Nette).

Obsah presenteru:

	// ukazka prace s odkazy
	public function renderUkazka3()
	{
		$param = $this->getParam();
		$this->template->cislo = (isset($param['cislo'])?$param['cislo']:false);
		$this->template->odkazu = range(1,20);
		if (isset($param['cislo']) && $this->isAjax()) {
			$this->template->odkazu = array($param['cislo']); // tady posilam jen to, co se ma ve foreach zmenit
			$this->invalidateControl('vrstva');
			$this->invalidateControl('odkaz');
		}
	}

Šablona ukazka3.latte:

<h2>Ukázka práce s odkazy</h2>
{snippet odkaz}
	<h3 n:if="$cislo">Kliknuto na odkaz c.{$cislo}</h3>
	<p n:if="$cislo"><a n:href="this">Reset</a></p>
{/snippet}
<p>
	{foreach $odkazu as $i}
		<a class="ajax" n:href="this, cislo=>$i">Odkaz č.{$i}</a>{sep} | {/sep}
	{/foreach}
</p>
<p>
	{snippet vrstva}
	{foreach $odkazu as $i}
		{snippet vrstva-$i, span}
			{$i}: {=($i==$cislo?date('H:i:s'):'----------')}
		{/snippet}{sep} | {/sep}
	{/foreach}
	{/snippet}
</p>
Why?!
Člen | 15
+
0
-

No, ale to není tak úplně to, co potřebuji. Tvůj příklad ukazuje funkčnost dynmických snippetů zároveň s refreshem dalšího statickýho – s tím také problém nemám. K tomu, aby to fungovalo, jak potřebuji, by to muselo v šabloně vypadat nějak takto:

<p>
        {snippet vrstva}
        {foreach $odkazu as $i}
                {snippet vrstva-koment-$i, span}
                        koment-{$i} // příklad vypsání například jen ID
                {/snippet}

		{snippet vrstva-like-$i, span}
                        like-{$i} // příklad vypsání například jen ID
                {/snippet}{sep} | {/sep}
        {/foreach}
        {/snippet}
</p>

Zkrátka potřebuji ještě dynamičtější než dynamické snippety jak jsou teď, protože potřebuji ještě jeměji – přímo v každé iteraci foreach určit, jaké „podsnippety“ se mají refreshnout, nemám tam jeden, jak je uvedeno v každém příkladu z těch málo co jsem našel, ale více…

Editoval Why?! (26. 9. 2011 14:49)

Filip Procházka
Moderator | 4668
+
0
-

Můžeš si v šabloně volat

<div id="{$control->getSnippetId('like-' . $id)}">
    ...
</div>

A pak si v handle sestavovat odpověď ručně. Není to krásné a voňavé, ale bude to fungovat než vymyslíš něco lepšího.

zbytovsky
Člen | 18
+
0
-

Nevím jestli je to ještě nyní aktuální, ale předpokládám, že se pořád ještě najde hodně lidí na nette2.0beta. Píšu to se pro další hledající, protože tohle vlákno mi pro dynamické snippety fakt pomohlo (Ot@sův příspěvek)

Především stačí si uvědomit jak ty dynamické snippety(DS) fungují, tj. podívat se na zkompilovanou šablonu. Statický snippet se vytvoří ve funkci a následně se DS prostě přidávají do pole. Pokud tedy budeme vědět, které zrovna chceme vykreslit, stačí příslušnou definci DS podmínit a ona se do pole nepřidá, tedy i nepřenese. Ta část za pomlčkou je pouze pro js identifikátor, tedy v pohodě můžeme použít alfanumerický. Netestováno, ale funguje mi v mém projektu.

<p>
{snippet vrstva}
        {foreach $odkazu as $i}
		{if $invalidni[koment$i]}
        	        {snippet vrstva-koment$i, span}
	                        koment-{$i} // příklad vypsání například jen ID
	                {/snippet}
		{/if}

		{if $invalidni[like$i]}
                	{snippet vrstva-like$i, span}
                       		like-{$i} // příklad vypsání například jen ID
	                {/snippet}
		{/if}
        {/foreach}
{/snippet}
</p>

Editoval zbytovsky (23. 1. 2012 2:46)