Refreshovanie ajaxového obsahu

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
PaBi3
Bronze Partner | 62
+
0
-

Pri písaní AJAX-ových aplikácií sa často stretávam s kódom v štýle:

<?php
...
if ($this->isAjax()) {
	$this->invalidateControl();
} else {
	$this->redirect('somewhere');
}
?>

Nebolo by možné vytvoriť DRY techniku v podobe pridania nasledujúcej metódy do presenteru, resp. controlu? Momentálne v nej nachádzam dosť praktické využitie.

<?php
/**
 * @param string|array snippet names
 * @param string link destination in format "[[module:]presenter:]view" or "signal!"
 * @param array|mixed
 * @return void
 */
public function refresh($snippets = NULL, $destination = 'this', $args = array())
{
	if ($this->getPresenter()->isAjax()) {
		if ($snippets) {
			foreach ((array) $snippets as $snippet) {
				$this->invalidateControl($snippet);
			}
		} else {
			$this->invalidateControl();
		}

	} else if ($destination) {
		$this->redirect($destination, $args);
	}
}
?>

Príklad použitia:

<?php
$self = $this;
$form->onSubmit[] = function (Form $form) use ($self) {
	...
	$self->refresh(); // invalidujte všetky snippety
	$self->refresh('content'); // invalidujte snippet content
	$self->refresh(array('content', 'user')); // invalidujte vybrané snippety
	$self->refresh(NULL, 'default'); // invalidujte všetky snippety a presmeruje na action **default**
}
?>

alebo

<?php
public function handleSomething() {
	...
	$this->refresh(); // rovnaké možnosti ako v predchádzajúcom príklade
}
?>

Ako to riešite vy? Urýchľujete túto činnosť nejakým iným spôsobom?

Editoval PaBi3 (14. 1. 2011 17:09)

bojovyletoun
Člen | 667
+
0
-

jsem pro, jen bych tam dal if ($this->getPresenter()->isAjax()) {

PaBi3
Bronze Partner | 62
+
0
-

Prečo if ($this->getPresenter()->isAjax()) ?

bojovyletoun
Člen | 667
+
0
-

forum
Protože jinak by to nešlo použít v komponentách. Metodu isajax má až presenter a ten dědí od control

PaBi3
Bronze Partner | 62
+
0
-

Máš pravdu, upravil som to.

Filip Procházka
Moderator | 4668
+
0
-

Líbí se mi ten nápad, vypůjčím si ho do Kdyby, jestli nemáš námitek :)

PaBi3
Bronze Partner | 62
+
0
-

Pokojne, veď preto som to sem dal :-).

David Grudl
Nette Core | 8218
+
0
-

invalidateControl a redirect by mělo fungovat dle očekávání i bez testu na AJAX.

PaBi3
Bronze Partner | 62
+
0
-

To som veľmi presne nepochopil.

Sú len 2 možnosti.

  • Ak je request AJAX-ový, tak invalidujem snippety a nepoužívam redirect, pretože by sa mi do payloadu dostalo to, čo v tomto prípade nepotrebujem a bol by som pri použití bežného oblužného javascriptu presmerovaný (cez window.location.href = payload.redirect).
  • Ak nie je request AJAX-ový, tak nepotrebujem (i keď môžem) invalidovať snippety a následne nerobím nič, prípadne použijem redirect.

Aby som sa vyhol dlhšiemu kódu, kde budem overovať „ajaxovosť“ requestu, tak to vyriešim cez jednu metódu – požijem len jeden riadok kódu.

Editoval PaBi3 (2. 2. 2011 21:59)

David Grudl
Nette Core | 8218
+
0
-

Jasně, pravda, ten redirect musí být v podmínce.

joe
Člen | 313
+
0
-

Tím se ale podmínky (nejméně) v komponentách nezbavíš, důvod:

  • AJAX request se chová jako normální požadavek a při něm dojde k projití všech fází životního cyklu presenteru, pokud jej nějak neukončíš
  • komponenta v případě AJAXu by asi neměla být závislá na tom, co se dějě v presenteru → měla by tedy ukončit jeho životní cyklus, nejspíš pomocí $this->sendPayload() aby se výstup poslal přes JSON

Vlastně by to asi šlo doplnit, jen tam chybí renderování šablony komponenty. Takhle je to sice jisté zkrácení, ale v případě AJAX requestů dost neefektivní a bylo by vhodné na to někde upozornit, protože třeba při přidávání komentáře na stránce s profilem chceme přes AJAX přidat jen ten komentář a ne znovu načítat všechna data o uživateli.

Editoval joe (29. 6. 2011 1:50)