Aplikování AJAXU do projektu

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

Chtěl jsem si zkusit zakomponovat do své aplikace AJAX, ale trochu se v tom ztrácím. Chtěl bych proto požádat o radu, co mám špatně?

latte:

{block #content}
{snippet form}

{form menuForm class => ajax}
    <table bordercolor="white">
       <tr>
            <td>{label datum/}</td>
            <td> {input datum}</td>
        </tr>
        <tr>
            <td>{label polevka/}</td>
            <td>{input polevka}</td>
            </tr>
        <tr>
            <td>{label jidlo1/}</td>
            <td>{input jidlo1}</td>
        </tr>

        <tr>
            <td>{label jidlo2/}</td>
            <td> {input jidlo2}</td>
        </tr>


        <tr>
            <td>{input create}</td><td> {input cancel}</td>
        </tr>
    </table>
{/form}
{/snippet}


<div>
    <table cellspacing="0">

        {foreach $menu as $menu}
            <tr>
                <td class="bold">Datum: </td>
                <td class="volna_bunka"></td>
                <td>{$menu->datum|date:'j. n. Y'}</td>
                <td><a class="edit" n:href="edit, $menu->id"><img src="{$basePath}/images/edit.png" alt="Editovat" /></a></td>
                <td><a class="delete" n:href="delete, $menu->id"><img src="{$basePath}/images/delete.png" alt="Vymazat" /></a></td>
            </tr>
            <tr>
                <td class="bold">Polévka: </td>
                <td class="volna_bunka"></td>
                <td>{$menu->polevka}</td>

            </tr>
            <tr>
                <td class="bold">1. jídlo: </td>
                <td class="volna_bunka"></td>
                <td>{$menu->jidlo1}</td>

            </tr>
            <tr>
                <td class="bold">2. jídlo: </td>
                <td class="volna_bunka"></td>
                <td>{$menu->jidlo2}</td>

            </tr>
            <tr>
                <td> <br /> </td>
            </tr>



        {/foreach}
    </table>
</div>



{/block}

potvrzení formu v presenteru:

public function menuFormSubmitted(Form $form) {

       $this->menu->createMenu()->insert(array(
          'datum' => $form->values->datum,
          'polevka' => $form->values->plevka,
          'datum' => $form->values->datum,
          'jidlo1' => $form->values->jidlo1,
          'jidlo2' => $form->values->jidlo2,
       ));

       $this->flashMessage('Jídlo přidáno.', 'success');
       if (!$this->isAjax()) {
           $this->redirect('this');
       } else {
           $form->setValues(array(), TRUE);
           $this->invalidateControl('form');
       }
   }

Po kliknutí na tlačítko Přidat se ale nic nestane. Zkouším to podle quickstartu…

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

Máš přilinkovaný nějaký obslužný skript pro AJAX?

.:M@rt!n:.
Člen | 201
+
0
-

Ano, podle quickstartu. Kod je tento:

jQuery.ajaxSetup({
    cache: false,
    dataType: 'json',
    success: function (payload) {
        if (payload.snippets) {
            for (var i in payload.snippets) {
                $('#' + i).html(payload.snippets[i]);
            }
        }
    }
});

// odesílání odkazů
$('a.ajax').live('click', function (event) {
    event.preventDefault();
    $.get(this.href);
});

// odesílání formulářů
$('form.ajax').live('submit', function (event) {
    event.preventDefault();
    $.post(this.action, $(this).serialize());
});
Vojtěch Dobeš
Gold Partner | 1316
+
0
-

Viz žlutý rámeček hned pod odkázaným nadpisem. Je třeba si stáhnout nějaký solidní skript z doplňků, který řeší, kterým tlačítkem byl formulář odeslán.

.:M@rt!n:.
Člen | 201
+
0
-

Už to odesílá. Ale nepozoruji žádnou změnu, oproti tomu, když to bylo klasicky bez AJAXu… Co by se mělo změnit??

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

Vůbec nechápu otázku.

Skripty z doplňků by měly například odesílat informaci o odeslaném tlačítku.

Editoval vojtech.dobes (7. 5. 2012 12:33)

.:M@rt!n:.
Člen | 201
+
0
-

No jak poznám, že daný form je odeslán AJAXem a ne klasicky??

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

Tak že se odešle AJAXový požadavek :) Lze sledovat kupříkladu ve Firebugu, stránka zůstane still a na formulář se odešle napozadí. Na serveru pak lze odeslání AJAXem detekovat metodou presenteru $this->isAjax().

.:M@rt!n:.
Člen | 201
+
0
-

Takže jestli to dobře chápu, data co uložím přes AJAX form by se mě měli na stránce ukázat bez kompletního reloadnutí stránky??

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

O tom je AJAX: první A ve zkratce znamená Asynchronní. Stránku na začátku načteš klasickým požadavkem, ale formulář odešleš asynchronně (AJAXem), „na pozadí“. Obslužný JS skript pak vrácenou odpověď (která je JSON) nějak zpracuje – typicky nahrazením vrácených snippetů v DOMu na správné místo.

Stačí jeden otazník ;)

Editoval vojtech.dobes (7. 5. 2012 13:29)

.:M@rt!n:.
Člen | 201
+
0
-

No a právě, že mě se stejně reloadne celá stránka a data se načtou až potom. Proto se ptám co mám špatně?

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

Ahá… nu, a předtím s tím krátkým skriptem ti to fungovalo? Máš na formuláři třídu ajax?

Promiň, máš, to už jsi psal. Máš tam stále ty poslední řádky, kde se pomocí live to ajaxové zpracování navazuje?

Editoval vojtech.dobes (7. 5. 2012 13:37)

.:M@rt!n:.
Člen | 201
+
0
-

Předtím to nefungovalo vůbec. V prezenteru u potvrzení formu mám toto:

public function menuFormSubmitted(Form $form) {

        $this->context->createMenu()->insert(array(
           'datum' => $form->values->datum,
           'polevka' => $form->values->polevka,
           'datum' => $form->values->datum,
           'jidlo1' => $form->values->jidlo1,
           'jidlo2' => $form->values->jidlo2,
        ));

        $this->flashMessage('Jídlo přidáno.', 'success');
        if (!$this->isAjax()) {
            $this->redirect('this');
        } else {
            $form->setValues(array(), TRUE);
            $this->invalidateControl('form');
        }
    }

čili jestli dobře chápu podmínku, tak ten kód si myslí, že tam AJAX není a přesměruje mě normálně bez něj(reload celé stránky)…
form vypadá takto:

{snippet form}

{form menuForm class => ajax}
    <table bordercolor="white">
       <tr>
            <td>{label datum/}</td>
            <td> {input datum}</td>
        </tr>
        <tr>
            <td>{label polevka/}</td>
            <td>{input polevka}</td>
            </tr>
        <tr>
            <td>{label jidlo1/}</td>
            <td>{input jidlo1}</td>
        </tr>

        <tr>
            <td>{label jidlo2/}</td>
            <td> {input jidlo2}</td>
        </tr>


        <tr>
            <td>{input create}</td><td> {input cancel}</td>
        </tr>
    </table>
{/form}
{/snippet}
Vojtěch Dobeš
Gold Partner | 1316
+
0
-

První otázka je, jestli se ti ten formulář vůbec ajaxově odesílá. To poznáš tak, že to budeš třeba ve Firebugové konzoli sledovat.

.:M@rt!n:.
Člen | 201
+
0
-

To by mělo být v pořádku – u statusu je OK po odeslání formu.

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

A co je v odpovědi? V payloadu?

.:M@rt!n:.
Člen | 201
+
0
-

To najdu kde?

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

Ve Firebugové konzoli se vypisují všechny požadavky, když si ho rozklikneš, tak tam jsou jednotlivé záložky (mrkni na záložku JSON, myslím).

Editoval vojtech.dobes (7. 5. 2012 15:14)

.:M@rt!n:.
Člen | 201
+
0
-

JSON tam nikde nemám :(

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

Nerozpakuj se informovat mě víc :) Co tam máš?

.:M@rt!n:.
Člen | 201
+
0
-

:) při rozkliknutí záložky síť mám: Vše, HTML, CSS, JS, XHR, Obrázky, Falsh a Média. Když kliknu na JS tak mě to vypíše všechny js které mám přilinkovaný a u všech je status „200 OK“

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

Já ty AJAXové požadavky sleduju v panelu Konzole. Tam pak po rozkliknutí jsou ty podrobné informace (nicméně jak se dívám, tak v té Síť je to taky). Pak mě zajímá, jaké informace máš v těch podrobnostech onoho requestu.

.:M@rt!n:.
Člen | 201
+
0
-

Snad je to to, co potřebuješ :)
Hlavičky:

Cache-Control	no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection	Keep-Alive
Content-Type	text/html; charset=utf-8
Date	Mon, 07 May 2012 13:48:38 GMT
Expires	Thu, 19 Nov 1981 08:52:00 GMT
Keep-Alive	timeout=5, max=100
Location	http://127.0.0.1:8888/TNPW2/admin/menu/?_fid=gnlq
Pragma	no-cache
Server	Apache/2.2.17 (Win32) PHP/5.3.4
Set-Cookie	PHPSESSID=fcdbmj319h5fmg5peu3gj5gui3; path=/; httponly nette-browser=v2z6fbrnwo; path=/; httponly
Transfer-Encoding	chunked
X-Frame-Options	DENY
X-Powered-By	Nette Framework
Hlavičky požadavkuzobrazit zdroj
Accept	text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding	gzip, deflate
Accept-Language	cs,en-us;q=0.7,en;q=0.3
Connection	keep-alive
Cookie	PHPSESSID=fcdbmj319h5fmg5peu3gj5gui3; nette-browser=v2z6fbrnwo
Host	127.0.0.1:8888
Referer	http://127.0.0.1:8888/TNPW2/admin/menu/?_fid=7mjg
User-Agent	Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20100101 Firefox/12.0
Request Headers From Upload Stream
Content-Length	102
Content-Type	application/x-www-form-urlencoded

Post:

_token_	7mh0ulwltt
create	Přidat
datum	07.05.2012
jidlo1	sfgtxdtg
jidlo2	xdghzxdtz
polevka	xghdtr
Zdroj
datum=07.05.2012&polevka=xghdtr&jidlo1=sfgtxdtg&jidlo2=xdghzxdtz&create=P%C5%99idat&_token_=7mh0ulwltt

Odezva:

Reload the page to get source for: http://127.0.0.1:8888/TNPW2/admin/menu/?do=menuForm-submit
Vojtěch Dobeš
Gold Partner | 1316
+
0
-

Nechápu to úplně poslední :)

Reload the page to get source for: http://127.0.0.1:8888/TNPW2/admin/menu/?do=menuForm-submit

To mě přesně zajímá :) Jinak další způsob debugování (ta kapitola v dokumentaci vážně chybí, že?) je firelogování. Do Firebugu je třeba si doinstalovat doplněk Firelogger. A pak lze v PHP volat Nette\Diagnostics\Debugger::fireLog($whatever); a v záložce Firelogger si tyhle dumpy prohlížet (je to jak barDump(), ale pro AJAX).

Tobě se to nakonec vždycky přesměruje? Pokud jo, zakomentuj si ten redirect (pro jistotu, pokud tam někde nemáš zapnuté persistování konzole, tak se ti po redirectu resetne).

Editoval vojtech.dobes (7. 5. 2012 16:01)

.:M@rt!n:.
Člen | 201
+
0
-

Redirect zakomentován, ale stejně se mě reloadne celá stránka a akorát form zůstane vyplněnej. Asi tam toho bude víc co je špatně tak to večír zkusim udělat znovu podle tohoto tutoriálu

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

Máš tam pořád někde tento kód?

// odesílání odkazů
$('a.ajax').live('click', function (event) {
    event.preventDefault();
    $.get(this.href);
});

// odesílání formulářů
$('form.ajax').live('submit', function (event) {
    event.preventDefault();
    $.post(this.action, $(this).serialize());
});
.:M@rt!n:.
Člen | 201
+
0
-

Jo tak ten mě tam chyběl :) ale teď se form po potvrzení vymaže a data se neukáží. Stránka už se nereloaduje.

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

Co znamená, že se form vymaže? Vyprázdní se políčka, nebo formulář úplně zmizí?

.:M@rt!n:.
Člen | 201
+
0
-

Vyprázdní se políčka

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

Tak to je přesně to, co chceš, ne? Voláš setValues, kterým vyresetuješ všechna pole a invaliduješ snippet.

Jinak schválně se teď mrkni do toho panelu Konzole, rozklikni si ten AJAXový požadavek (POST) – bude tam podzáložka JSON, kde si můžeš prohlédnout, jak se ty snippety posílají.

.:M@rt!n:.
Člen | 201
+
0
-

Jo to sice potřebuji, ale jak vypsat ještě ty uložený data, bez reloadu stránky?

Jo jinak už v konzoli JSON je.

Editoval .:M@rt!n:. (7. 5. 2012 16:36)

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

Já nechápu, na co se mě ptáš. Snaž se prosím víc specifikovat, čeho chceš přesně dosáhnout.

.:M@rt!n:.
Člen | 201
+
0
-

No po potvrzení formuláře by se mě měly vypsat data, které jsem pomocí formuláře uložil do db, bez reloadu stránek. Jenže data se po odeslání formuláře uloží do db ale už se nevypíší(musím sám reloadnout stránku aby se vypsaly). Čili jak k tomu ještě dodělat, aby se data vypsaly po potvrzení formuláře?

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

Už chápu. No, pokud chceš nějak ovlivnit výpis těch dat, co tam máš, tak ten musí být taky ve snippetu. Takže obalit do snippetu a invalidovat.

.:M@rt!n:.
Člen | 201
+
0
-

Jo, děkuji za rady, funguje tak jak má.