Špatná invalidace snippetu

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

Zdravím,

s ajaxem pod nette teprve začínám a hned jsem narazil na problém. Mám následující strukturu.

Presenter: message
Metody v presenteru: default, tweet.

V metode (a sablone) renderDefault mam prehled vsech message. Chci nyni udelat to, ze kdyz kliknu na nejakou message, zobrazi se na strance default (nekde bokem) obsah metody (sablony) tweet (renderTweet).

V default.latte mam:

Tedy neco jako zavolej na presenteru Message metodu renderTweet s id a vrat obsah do snippetu tweet.

{foreach $messages as $tweet}
<a class="ajax" n:href="Message:tweet $tweet->tid">tst</a>
{/foreach}
{snippet tweet}
    SNIPPET
{/snippet}

v tweet.latte mam treba jenom hodnotu „TEST“

v presenteru Message to vypada nasledovne:

Takze mel vyrenderovat hodnotu 123 atd. + obsah tweet.latte

public function renderTweet($id)
    {
        if (!$this->presenter->isAjax()) {
            print 456;
            //$this->presenter->redirect('this');
        } else {
            print 123 . " * " . $id;
            $this->invalidateControl("tweet");
        }
}

jquery, jquery.nette a podobne mam nalinkovane. Asynchrone pozadavek probehne a vraci 123 * hodnotaId {„state“:[]}. Pokud vytvorim tweet.latte jako:

{snippet tweet}
TEST
{/snippet}

Pak je hodnota odezvy

123 * hodnotaId {"state":[],"snippets":{"snippet--tweet":"TEST\n"}

a invalidace snippetu v default.latte stejne neprobehne.

Delam neco spatne? Diky moc za veskere rady.

Vojtěch Dobeš
Gold Partner | 1316
+
0
-

Ten návrh je špatně. V akci default se vždy použije default.latte a v akci tweet šablona tweet.latte. Ajax v Nette je chytře navržen ve stylu Progressive Enhancement, tudíž aplikace by měla fungovat i bez něj. Zkus se nad tím tak nejprve zamyslet, třeba to celé sám přemyslíš jinak.

Každopádně tvůj problém vyřeší zavolání $this->template->setFile( ...cesta k šabloně default.latte... ) v akci tweet. tweet.latte pak můžeš smazat. Invalidace snippetu se pak provede v té první šabloně a bude fungovat správně.

Lepším řešením ale bude napsat si na to nějakou komponentu, nebo prostě alespoň funkcionalitu toho zobrazení detailu přenést do akce default.

zis
Člen | 16
+
0
-

Diky za rady,

zkousim nad tim premyslet. Komponentovy navrh by se mi zamlouval, ale poradne nevim jak to uchopit.

Idea je takova, ze mam proste seznam zprav(message). Ten chci aby byl vzdy zobrazen. Pokud navic klikne na nejakou zpravu, tak aby se mu nekde na strance asynchrone objevil obsah zpravy (tweet). Celkem bezna vec, jde to udelat jednoduse mimo nette, ale jednalo by se o spatny navrh.

Premyslel sem, ze bych udelal komponentu Tweet. V sablone presenteru Message by se vypisovaly vsechny zpravy a nekde mimo obsah komponenty Tweet. Po kliknuti na message by se by se invalidoval obsah komponenty.

Moc si ale nedokazu predstavit, jak volat z sablony Message signal komponenty tweet, coz me vede k tomu, ze se jedna opet o spatny navrh :).

V pripade ze bych z toho udelal jednu velkou komponentu (seznam message + detail), bych se zase dostal do stejne situace, kdy bych chtel mit na jedne strance vypsan obsah dvou sablon. Musi existovat nejake elegantni reseni.

zis
Člen | 16
+
0
-

Ještě mě trápí jedna věc a to ta, že si nejsem jist, zda přesně vím, jak funguje invalidace snippetu a vůbec ajax pod nette. Lze mít prázdny snippet na stránce (třeba jen s textem TEST) a jeho obsah změnit jednoduše podle příkladu níže?

sablona:

{foreach $messages as $tweet}
<a class="ajax" n:href="Message:tweet! $tweet->tid">tst</a>
{/foreach}
{snippet}
TEST
{/snippet}

Presenter:

public function handleTweet($id)
    {
        if (!$this->presenter->isAjax()) {
            print "NONAJAX";
            //$this->presenter->redirect('this');
        } else {
            print "AJAX * " . $id;
            $this->invalidateControl();
        }
    }

Firebug mi oznámí, že byl signál vyvolán a návratová hodnota je:

AJAX * 3{"state":[],"snippets":{"snippet--":""}}

A já bych chtěl ten výsledek zapsat do toho snippetu. Konkrétně pak do toho snippetu budu potřebovat dostat nějaký html kód nejlépe z nějaké šablony.

Případně pokud dám do metody handleTweet do bloku else hodnotu

$this->template->test = 1;

která je defaultně nastavena na 0 a v šabloně pak:

{snippet}
TEST - {$test}
{/snippet}

Zprvu je 0 a i po zavolání signálu tweet je 0. Je něco špatně?

Aearsis
Člen | 57
+
0
-

Předně nesmíš do AJAX odpovědi cokoli vypisovat (print, echo, dump, …), protože to pak není validní JSON a klient to nezparsuje.

Invalidace funguje asi tak, že za každým makrem {snippet} je schovaný div s určitým id. Když se generuje odpověd na AJAX požadavek, latte vybere jen ty snippety, které má označené jako nevalidní, a jejich obsah vrátí v JSON poli. Pokud snippet není na původní stránce, není tam div – není kam to vykreslit. Pokud není na té druhé, dotazované, stránce, nemá se jak vykreslit, tudíž se nezmění.

zis
Člen | 16
+
0
-

Kdyz bych se zeptal jednoduse jinak. Lze vytvorit neco jako detail fotky na stejne strance? Priklad fotky z facebooku. Seznam fotek, na nejakou kliknu a ukaze se mi nahled, modalni okno s komentarema, fotkou, popiskem,… Mohl by nekdo alespon hodit nastrel? Podle toho co sem cetl vyse, mi prijde, ze v nette se to ciste udelat neda. Diky za napady.