Nová verze Nette a dynamické snippety

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

Nevíte někdo jak v nové „bezzavináčové“ verzi udělat dynamický snippet?

{snippet rate$id span}

mi vyhodí LatteException, že název bloku musí být alfanumerický.. tzn. $id to nepřevede na číslo.

jansfabik
Člen | 193
+
0
-

https://forum.nette.org/…ce-nette-2-0

Bohužel to nejde, v nové verzi musí mít všechny snippety statický název. Nešlo by ten snippet pojmenovat rate a pak v presenteru do $this->template->... uložit všechny v něm používané proměnné?

tomees
Člen | 59
+
0
-

V tom případě jsou nové snippety na nic…
Jak mám např. udělat, když mám na stránce hlasovací snippet u 30ti položek…
Je hezké, že zmizeli zavináče, ovšem toto je celkem k ničemu.

Filip Procházka
Moderator | 4668
+
0
-

zkoušel jsi

{snippet "rate$id"}

?

tomees
Člen | 59
+
0
-

HosipLan napsal(a):

zkoušel jsi

{snippet "rate$id"}

?

<?php
{snippet "rate$id" span}
{foreach $stars as $star}
        <img src="{$basePath}/images/site/icons/star_{$star}_red.gif" title="{$id}" />
{/foreach}
{/snippet}
?>

Nette\Templates\LatteException

Block name must be alphanumeric string, ‚_"rate$id"‘ given in …\components\RatingControl.phtml:5

Editoval tomees (14. 11. 2010 16:40)

Filip Procházka
Moderator | 4668
+
0
-

Myslím, že to vubec nejde zkus napsat bug report

jansfabik
Člen | 193
+
0
-

Je to způsobené tím, že v dev verzi je každý snippet reprezentován blokem {block} a bloky jsou překládány do PHP jako funkce, takže nemohou dynamicky měnit svůj název.

jansfabik
Člen | 193
+
0
-

Možná by pomohlo, kdyby někdo implementoval toto:
https://forum.nette.org/…nette-sablon

Ale nevím, jestli by bylo správným krokem jenom kvůli snippetům přepisovat odladěný 45-kilobajtový LatteFilter.

norbe
Backer | 405
+
0
-

Toto chování dle mého názoru cílené a způsobí to mimo jiné i rychlejší odezvu v systému při použití ajaxu.

Člověk si musí uvědomit, jak by se šablony při ajaxu měli chovat. Myslíte si snad, že by se měli zpracovávat kompletně? Já myslím že by se měla zpracovat pouze ta část šablony, které je uvnitř invalidovaného snippetu a to je důvodem toho, že dynamické snippety nemohou fungovat. Na závěr musím říct, že jsem nestudoval jak je to implementovaný, jen uvažuju proč to je tak jak to je a proč si myslím že to tak je správně…

redhead
Člen | 1313
+
0
-

Ono s rychlostí to stejně bude nastejno:

Když budu mít nějaký výpis položek, tak s nynější implementací budu muset posílat celý výpis místo oné jedné položky, která se změnila (tedy projít cyklem všechny položky a vypsat je). S dynamickými snippety by se sice prošli všechny položky, ale odeslala by se jen ta, co se změnila. Čili na straně serveru je to prakticky totožné. Dynamické snippety by ale navíc byly teoreticky menší a rychlejší na transport dat – včetně práce JS na klientu.

Editoval redhead (14. 11. 2010 23:29)

norbe
Backer | 405
+
0
-

S tím bych zase moc nesouhlasil, jelikož dynamický snippet lze nahradit dynamickou komponentou, kterou vykreslim v cyklu. Pokud pak komponenta přijme nějaký signál, invaliduje se a odešle pouze svůj kód.

tomees
Člen | 59
+
0
-

pokud je toto cílené chování, mohl by mi tedy někdo poradit jak docílit požadovaného efektu dynamických snippetů?

tomees
Člen | 59
+
0
-

norbe napsal(a):

S tím bych zase moc nesouhlasil, jelikož dynamický snippet lze nahradit dynamickou komponentou, kterou vykreslim v cyklu. Pokud pak komponenta přijme nějaký signál, invaliduje se a odešle pouze svůj kód.

já to tak teď prakticky mám, mám hlasovací komponentu, která je na stránce 30× a v každé je snippet, který obsahuje hvězdičky

no ale i když bude komponenta dynamická, stále bude muset nějaký snippet vykreslovat ne? A když bude vykreslovat snippet rate, pak na stránce bude 30× blok „rate“.. a potom JS aktualizuje obsahy všech těchto bloků ne?

Editoval tomees (15. 11. 2010 8:24)

norbe
Backer | 405
+
0
-

Myslel jsem to nějak takhle:

// tovarnicka
public function createComponent($name) {
   if (preg_match("/^rateControl/", $name)) {
      $rateControl=new RateControl($this, $name);
      // z nazvu si ziskam predane id a nastavim ho komponente...
      $rateControl->setId($id)
   }
   else {
      return parent::createComponent($name);
   }
// sablona
{foreach $articles as $article}
   {control rateControl.$article->id}
{/foreach}

Edit: Sice budeš mít jednu komponentu, ale s jiným názvem, takže se vždycky invaliduje pouze jedna konkrétní…

Editoval norbe (15. 11. 2010 9:02)

pekelnik
Člen | 462
+
0
-

Doplnil jsem tuhle možnost do testeru… http://jdem.cz/hw3k4

David Grudl
Nette Core | 8107
+
0
-

Implementace zatím není kompletní, info viz https://forum.nette.org/…zi-nette-2-0

jansfabik
Člen | 193
+
0
-

Pokud by byly zavedeny dynamické snippety, tak by se vždycky generovala část stránky zbytečně a pak se zahodila.

Napadá mě řešení: Snippety by zůstaly statické, ale mohly by být vícekrát invalidovány.

{foreach $items as $item}
	...
	{snippet rate $item->id} {* to $item->id se vloží nakonec ID snippetu (a <div>u) *}
		<img src="star.gif" n:for="$i = 0; $i < $item->rating; $i++">
	{/snippet}
	...
{/foreach}

v presenteru:

$items = $model->getRatings(); // načteme jenom to, co je potřeba (rating a id)
foreach ($items as $item) {
	$this->template->item = $item;
	$this->invalidateControl('rate');
}

Vlastně by šlo jen o to, aby se snippety vykreslily už při volání invalidateControl, a aby se drobně upravilo makro {snippet}. Takové řešení by pak bylo velmi efektivní.

edit: Vylepšen kód presenteru.

Editoval jansfabik (15. 11. 2010 17:16)

David Grudl
Nette Core | 8107
+
0
-

Bych to viděl tak, že

  1. zruší se druhý parametr snippetu. Pokud budu chtít snippet z jiného elementu než div, napíšu to takto <tbody n:snippet="name">
  2. dynamické snippety by byly povoleny jen uvnitř statických. Invalidoval by se jen ten statický-obalovací a vykreslil by všechny dynamické uvnitř.
norbe
Backer | 405
+
0
-

Ad 2) Jaký by pak měly ty vnitřní snippety význam? :-)

Filip Procházka
Moderator | 4668
+
0
-

David Grudl: 1) +1


co něco takového?

šablona – prostě se parametry předají

{foreach $items as $item}
        ...
        {snippet rate, 'item' => $item, 'jen_pro_ukazku' => 'ahojky'} {* stejně jsou to teď bloky ... *}
                <img src="star.gif" n:for="$i = 0; $i < $item->rating; $i++"> {$jen_pro_ukazku}
        {/snippet}
        ...
{/foreach}

volání – parametry předám znovu, nemusím lézt do „rodiče“

$id = $this->getParam('id');
$item = $this->model->getRankById($id);

$this->invalidateControl('rate', array('item' => $item, 'jen-pro-uKazku' => NULL));
$this->invalidateControl('rate', array('item' => $item)); // notice, jen_pro_ukazku je undefined, popř dosazení výchozí NULL

takhle nějak by se mohlo generovat ID, ale to už je detail

$hmtlId = 'rank-' . substr(md5(serialize($params)), 0, 8);

vytvořila by se žádost, která by zavolala snippet s těmi hodnotami a tím by byla zaručena dynamičnost,
jenom by to fungovalo trochu jinak :)

//edit: hmmm nápad to byl dobrý než jsem si uvědomil že když změním nějakou hodnotu $item tak mi to pošle jiné ID … :)


a nebo ještě jinak

{foreach $items as $item}
        ...
	{var $jen_pro_ukazku = 'ahojky'}
        {snippet rate, 'itemId' => $item->id} {* v podstatě tagy, ostatní parametry se vezmou od rodiče ... *}
                <img src="star.gif" n:for="$i = 0; $i < $item->rating; $i++"> {$jen_pro_ukazku}
        {/snippet}
        ...
{/foreach}

trochu jiná invalidace

$this->invalidateControl('rate', $tags = array('itemId' => $item->id), $args = array('jen_pro_ukazku' => 'cauky'));
$this->invalidateControl('rate', $tags = array('itemId' => $item->id), $args = array(''));

Popř by se to mohlo zjednodušit na něco podobného původní implementaci a dovolit identifikaci pouze na základě jednoho řetězce ať už int nebo string

{* ted si vymyslim, netuším jaký formát mají htmlId snippetů *}
{snippet rate}
	<div id="snippet-rate"> ... </div>
<td n:snippet="rate">
	<td id="snippet-rate"> ... </td>

{snippet rate, $item->nejakeid}
	<div id="snippet-rate-<?=webalize($item->nejakeId) ?>"> ... </div>
<td n:snippet="rate, $item->nejakeid">
	<td id="snippet-rate-<?=webalize($item->nejakeId) ?>"> ... </td>
$this->invalidateControl('rate', $item->nejakeid, $args = array('item' => $item, 'jen_pro_ukazku' => 'cauky'));
$this->invalidateControl('rate', $item->nejakeid); // notice, nemá proměnné

případně ještě trochu jinak, a zavolat pouze vykreslení bloku s proměnnými templaty

$this->template->item = $item;
$this->template->jen_pro_ukazku = 'čauky'

$this->invalidateControl('rate', $item->nejakeid);

Pochybuju, že někdo bude potřebovat jemnější rozlišení, stejně se to páruje většinou ‚jméno‘ + ‚nejakeid‘ takže by to věc ještě zjednodušilo, id snippetu by se nepředávalo, ale jenom by se použilo na vygenerování tagu


tak jo, nakonec jsem přišel zpátky k tomu že stačí 1 parametr navíc

{snippet rate} nebo <td n:snippet="rate">
{snippet rate, $item->nejakeid} nebo <td n:snippet="rate, $item->nejakeid">

a generovat z něj hmtlId

$this->template->item = $item;
$this->template->jen_pro_ukazku = 'čauky'

$this->invalidateControl('rate');
$this->invalidateControl('rate', $item->nejakeid);

//edit: lol, taková prasárna tady :D

Editoval HosipLan (16. 11. 2010 10:27)

jansfabik
Člen | 193
+
0
-

David Grudl napsal(a):

  1. zruší se druhý parametr snippetu. Pokud budu chtít snippet z jiného elementu než div, napíšu to takto <tbody n:snippet="name">

s tím souhlasím, +1

  1. dynamické snippety by byly povoleny jen uvnitř statických. Invalidoval by se jen ten statický-obalovací a vykreslil by všechny dynamické uvnitř.

To by ale se zase zbytečně generoval kód, který by nebyl potřeba. Nenapadá mě důvod, proč by měly snippety být dynamické, když stačí statické snippety, které lze invalidovat pokaždé s jinými proměnnými. Existuje nějaký případ, kdy by toto nestačilo?

HosipLan napsal(a):

No, v podstatě jsi došel ke stejnému kódu jako já. ;-)

Pro lepší představu:

{snippet rate, $item->id}
	<img src="star.gif" n:for="$i = 0; $i < $item->rating; $i++">
{/snippet}

by bylo ekvivalentní zhruba s něčím takovým:

{block _rate}
<div id="snippet-{$control->getName()}-rate-{$item->id}">
	<img src="star.gif" n:for="$i = 0; $i < $item->rating; $i++">
</div>
{/block}

Při invalidaci snippetu rate by se pak jen zavolala ta zkompilovaná šabloní funkce s blokem _rate a výstup by se uložil do payloadu.

bojovyletoun
Člen | 667
+
0
-

Ahoj,

To by ale se zase zbytečně generoval kód, který by nebyl potřeba. Nenapadá mě důvod, proč by měly snippety být dynamické, když stačí statické snippety, které lze invalidovat pokaždé s jinými proměnnými. Existuje nějaký případ, kdy by toto nestačilo?

Jak se to používá?: statické snippety, které lze invalidovat pokaždé s jinými proměnnými.

jannemec
Člen | 78
+
0
-

jansfabik napsal(a):

David Grudl napsal(a):

  1. zruší se druhý parametr snippetu. Pokud budu chtít snippet z jiného elementu než div, napíšu to takto <tbody n:snippet="name">

s tím souhlasím, +1

ano, to vypadá dobře +1
>

  1. dynamické snippety by byly povoleny jen uvnitř statických. Invalidoval by se jen ten statický-obalovací a vykreslil by všechny dynamické uvnitř.

To by ale se zase zbytečně generoval kód, který by nebyl potřeba. Nenapadá mě důvod, proč by měly snippety být dynamické, když stačí statické snippety, které lze invalidovat pokaždé s jinými proměnnými. Existuje nějaký případ, kdy by toto nestačilo?

HosipLan napsal(a):

No, v podstatě jsi došel ke stejnému kódu jako já. ;-)

Pro lepší představu:

{snippet rate, $item->id}
	<img src="star.gif" n:for="$i = 0; $i < $item->rating; $i++">
{/snippet}

by bylo ekvivalentní zhruba s něčím takovým:

{block _rate}
<div id="snippet-{$control->getName()}-rate-{$item->id}">
	<img src="star.gif" n:for="$i = 0; $i < $item->rating; $i++">
</div>
{/block}

Při invalidaci snippetu rate by se pak jen zavolala ta zkompilovaná šabloní funkce s blokem _rate a výstup by se uložil do payloadu.

Takhle to vypadá zajímavě a myslím, že dynamické snippety jsou užitečná věc – od více hlasování, přes nějaké AJAX kusy textu … přijde mi toto řešení lepší než tvorba více controlů
JN

_Martin_
Generous Backer | 679
+
0
-

David Grudl napsal(a):

  1. zruší se druhý parametr snippetu. Pokud budu chtít snippet z jiného elementu než div, napíšu to takto <tbody n:snippet="name">

Bude se to realizovat?

David Grudl
Nette Core | 8107
+
0
-

Ano, bude.