Good news everyone :) Successfull AJAX and Snippets Test

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

Ahoj,

podle nejnovějších commitů se zdá být AJAX (i snippety) v Nette plně funkční na Presenter– i na Control– úrovni.

Vytvořil jsem testovací Sandbox – je to normální Sandbox z Nette – pouze s předvyrobenýma pár komponentama na testování.

Funguje perfektně :)

Demo http://ajax.estateportal.eu/
Source https://github.com/…test-sandbox
Download https://github.com/…pball/master

Jediné co nefunguje jsou „dynamické snippety“ (bugreport, diskuse)

Nefunguje to ani takhle:

{foreach array('a', 'b', 'c') as $item}
	{snippet $item}
		<p class="snippet">
			{$item}
		</p>
	{snippet}
{/foreach}

natožpak takhle

{foreach array(1, 2, 3) as $id}
	{snippet "item-$id"}
		...

Výraz v makru {snippet} se vůbec nevyhodnocuje – a tedy vznikne snippet-$id (resp. $item v prvním případě), což vyhodí vyjímku: Block name must be alphanumeric string, ‚snippet-$id‘ given…


Závěrem bych chtěl pochválit komunitu za zdařilý vývoj a Davidovi vynadat za nefunkční dynamické snippety ;)

Update: k dispozici je zdroják na githubu…

Editoval pekelnik (15. 11. 2010 14:07)

Bernard Williams
Člen | 207
+
0
-

Nazdárek,

zkoušel jsi chování control snippetu v presenter snippetu? Tzn. ne oddělené, ale vnořené. Právě s tím dost bojuji v jedné starší 2.0dev verzi.

Bernard

pekelnik
Člen | 462
+
0
-

Doplnil jsem příklad i zip… vnořená komponenta ve snippetu funguje bez problémů…

Update: Doplnil jsem

  • dynamické snippety (via dynamické komponenty)
  • skutečně pořádně zanořenou komponentu ;)

Enjoy :) http://jdem.cz/hw3k4

Editoval pekelnik (15. 11. 2010 12:20)

arron
Člen | 464
+
0
-

Mozna je to bug v testovaci aplikaci, ale kdyz kliknu na „Refresh all snippets“ (nebo pouziju patricny odkaz), tak ze neobnovi snippet v „Control: b“.

pekelnik
Člen | 462
+
0
-

@arron: refreshuje snippety na úrovni presenteru, dále je tam tlačítko, které refreshuje všechny komponenty tedy i B, samozřejmě bych mohl invalidovat i snippet v komponentě B ale to není účelem tohoto testu…

arron
Člen | 464
+
0
-

Tak to se omlouvam, moje hlava skopova si to vylozila jinak :-)

mbskot
Člen | 42
+
0
-

Cafte, nefunguje mi to akosi v presentery

public function handleReset()
{
  $this->invalidateControl('aaa');
}
{block #content}
  <a n:class="ajax" n:href="reset"><b>Refresh all snippets</b></a>
  {snippet aaa}
    <?php echo time();?>
  {/snippet}
{/block}

Tentokrat firebug hlasi: 404 Not Found.

Editoval mbskot (25. 4. 2011 14:20)

Patrik Votoček
Člen | 2221
+
0
-

mbskot napsal(a):

Dokonca mi to nefunguje ani v presentery…

n:href="reset"n:href="reset!"

mbskot
Člen | 42
+
0
-

nj dik, v presentery to uz zije, ale v komponente ani nahodou.
Skusal som ‚s‘ aj ‚bez‘ vykricnika, ziadna chyba ale nefunguje. V komponente mi vyhadzuje e500 ak napisem

$this->invalidateControl('aaa');

preto som tam dal

$this->presenter->invalidateControl('aaa');

ale teraz zase nic nerobi.

arron
Člen | 464
+
0
-

v oné ‚e500‘ bude nejspis i popsano, v cem je problem…

Nox
Člen | 378
+
0
-

@původní příspěvek:

ještě nefunguje respektování kontextu renderování při ajaxu (renderSmall, parametry…).

Čím víc nad tím přemýšlím, tím víc neproveditelný se zdá renderování jen invalidovaných komponent… pokud bych měl render komponenty ve foreach a využívala iterátor, musí se to asi holt přerenderovat komplet, plus makra var a takové problémy

Pokud by stačil kontext na začátku šablony a nebyly dynamické snippety, stačilo by https://gist.github.com/896127 (pojmenované solution, až pak sem přišel na spoustu mezer)
(možná by to šlo řešit i podobně a vyřešit co jsem uvedl, zatim ale úplně nevim)

VelmiPozdníEdit: ony vlastně snippety mají vlastní scope, tak to by mělo být řešitelné

Editoval Nox (1. 6. 2011 7:25)

David Grudl
Nette Core | 8218
+
0
-

Dynamické snippety by měly fungovat, stačí je obalit do společného (nedynamického) snippetu.

mach2roman
Člen | 22
+
0
-

Jak se to invaliduje. Při načtení stránky dojde ke zpracování a vykreslení dynamických snippetů, vše proběhne korektně, ale po zpracování AJAXu a invalidaci dynamického snippetu se žádná data v poli snippets nevrátí a tudíž se nepřekreslí. Pokud dám invalidovat ten statický obalovací tak to funguje, ale je to nepoužitelné, jelikož v něm mám dalších asi 100 dynamických a vlastně to musí poslat zpět skoro celou stránku. Jak tedy invalidovat pouze ten jeden konkrétní dynamický?

David Grudl
Nette Core | 8218
+
0
-

Invaliduje se jen ten statický a ten už si může vykreslit tolik dynamických, kolik potřebuje.

mach2roman
Člen | 22
+
0
-

David Grudl napsal(a):

Invaliduje se jen ten statický a ten už si může vykreslit tolik dynamických, kolik potřebuje.

Pak nějak nechápu k čemu je to dobré? Jaký je rozdíl mezi statickým snippetem který obsahuje nebo neobsahuje dynamické snippety? Když se musí invalidovat ten statický tak tam ty dynamické mít nemusím a výsledek je stejný ..... jen na rozdíl od starých snippetů se přenáší v případě 100 dynamickách snippetů uvnitř 100× větší objem dat a celková doba zpracování je pak násobně delší než u starých. Možná se sníží zátěž serveru, ale doba zpracování na serveru je pár ms, kdežto přenos všech snippetů trvá neporovnatelně déle. Na verzi 0.9.6 to lítá jak vítr, kdež to po úpravě na verzi 2 je nepoužitelné.

Filip Procházka
Moderator | 4668
+
0
-

Řekl bych, že potom je use case takovýto:

$template->letters = array('a', 'b', 'c');
{snippet item}
	{foreach $letters as $l}
	        {snippet item->$l} {$l} {=microtime(TRUE)} {snippet}
	{/foreach}
{snippet item}

invalidace 1 záznamu a jestli jsem to dobře pochopil, odešle se pouze vnitřní snippet?

$template->letters = array('a');
$this->invalidateControl('item');
{snippet item}
	{foreach $letters as $l}
	        {snippet item-$l} {$l} {=microtime(TRUE)} {snippet}
	{/foreach}
{snippet item}

invalidace více záznamu

$template->letters = array('a', 'b');
$this->invalidateControl('item');
{snippet item}
	{foreach $letters as $l}
	        {snippet item-$l} {$l} {=microtime(TRUE)} {snippet}
	{/foreach}
{snippet item}

pak je tu ale problém s iterátory atd… Jsem z toho zmaten :)

Editoval HosipLan (1. 6. 2011 15:36)

David Grudl
Nette Core | 8218
+
0
-

mach2roman napsal(a):

Pak nějak nechápu k čemu je to dobré?

Pokud to nepotřebuješ, tak k ničemu ;-)

HosipLan napsal(a):

invalidace 1 záznamu a jestli jsem to dobře pochopil, odešle se pouze vnitřní snippet?

Ano

pak je tu ale problém s iterátory atd… Jsem z toho zmaten :)

Jaký?

ViliamKopecky
Nette hipster | 230
+
0
-

David Grudl napsal(a):

pak je tu ale problém s iterátory atd… Jsem z toho zmaten :)

Jaký?

třeba sep, first, last, even/odd.

David Grudl
Nette Core | 8218
+
0
-

Proč to nejde? Nějaký příklad?

hrach
Člen | 1838
+
0
-

No jasny, ony fungují, ale ne tak, jak kdybych do daneho foreache selectnul vse, zeano.. :)

David Grudl:
neuvažujte nad tím jako: vykreslím 100 komentářů, všechny zahodím a jen dvojku pošlu ven, to je přece prasárna
(https://forum.nette.org/…ych-snippetu#…)

Souhlasím s tím, že je to prasárna, nicméně pokud chcu opravdu zachovat staré chování, musím selectovat vždy všechna data a ještě nějakým ifem kontrolovat, jestli daný blok vypsat.
({if ($isAjax && $invalidate[$id]) || (!$isAjax)}).

Tvé řešení je uplně stejně funkčně „nedokonalé“ jako to moje, jen má jinou syntaxi.

jazby
Člen | 44
+
0
-

Mě by zajímalo jak by se správně řešilo toto:
Mám komponentu, co mi vypisuje seznam (čehokoli, třeba stránek).
Každá položka má na sobě on/off a delete + změnu pořadí pomocí sortable.
Jak toto správně zajaxovatět? Nyní posílám při každém on/off (deletu) znove celý tree, což není moc dobře. Dynamické snippety by toto vyřešit mohli, jenže jak nevím jak to správně implementovat?

Implementace u mě (prosím prasárny odpustit, jsou to jen testy)
presentr:actionEdit:template

{widget layout:list, $presenter->getParam("id")}

Control:Layout:template

{snippet layout}
<script type="text/javascript" src="{$basePath}/js/live.js"></script>
<ul n:inner-foreach="$list as $item" class="layout sortable">
	<li id="layout_{$item->page_layout_id}">
		{snippet $item->page_layout_id}
			<span>#</span>
			{if $item->status_id == $ACTION["Active"]}
				<a class="ajax" href="{link changeStatus! $item->page_layout_id, $ACTION['inActive']}"><img src="/admin/images/on.png" alt="on_status" title="vypnout layout" /></a>
			{else}
				<a class="ajax" href="{link changeStatus! $item->page_layout_id, $ACTION['Active']}"><img src="/admin/images/off.png" alt="off_status" title="zapnout layout" /></a>
			{/if}
			{$item->name} - <img src="/admin/images/{$item->phpname}.gif" alt="{$item->phpname}" title="{$item->phpname}"/>
			<a class="edit" href="{plink $item->phpname.":edit", 'id' => $item->page_layout_id}"><img src="/admin/images/edit.gif" alt="edit" /></a>
		{/snippet}
		</li>

</ul>
{/snippet}

Control:Layout

	/*pri ajaxu se vola toto namisto "list", chyba nette ?*/
	public function render()
	{
		$template = parent::createTemplate(); //Vytvoříme šablonu
	$template->setFile(__DIR__ . '/layout.latte'); //Soubor se šablonou
		$template->ACTION = LayoutModel::getAllAction();
		$template->list = LayoutModel::getLayoutList($this->presenter->getParam("id"));
		$template->render();
	}

	/*vola se normalne*/
	public function renderList($pages_id)
	{
		$template = parent::createTemplate(); //Vytvoříme šablonu
	$template->setFile(__DIR__ . '/layout.latte'); //Soubor se šablonou
		$template->modules = LayoutModel::getModulModel()->getPublicModules();
		$template->ACTION = LayoutModel::getAllAction();
		$template->list = LayoutModel::getLayoutList($pages_id);
		$template->render();
	}

	public function handleChangeStatus($page_layout_id, $actions)
	{
		LayoutModel::editLayout(array("status_id"=>$actions), array("page_layout_id"=>$page_layout_id));
		$this->template->id = $page_layout_id;
		$this->invalidateControl("layout");
	}

	/**tuto prasarnu predelat, ukladat se bude pouze pořadí co se změnilo ->zdenek*/
	public function handleChangeTree()
	{
		$data = $this->presenter->getRequest()->getPost();
		$rank = 0;
		foreach( $data["layout"] as $layout_id=>$value )
		{
			LayoutModel::editLayout(array("rank"=>$rank), array("page_layout_id"=>$layout_id));
			$rank = $rank + 10;
		}
		$this->invalidateControl("layout");
	}

Snad je jasné na co se ptám.