Nette Framework
  • Úvodní stránka
  • Download
  • Dokumentace
  • Fórum
  • Blog
  • Přispějte
  • Quick Start
    • Začínáme
    • Adresářová struktura
    • Vytvoření presenteru
    • Připojení šablony
    • Tvorba odkazů
    • Hezčí šablony
    • Zobrazení tabulky
    • Stránkování a řazení
    • Tvoříme komponentu
  • Nette
    • Základní třídy
    • Nette\Annotations
    • Nette\Component
    • Nette\Debug
      • Základy
      • Logování chyb
      • Firebug
    • Nette\Environment
    • Nette\Image
    • Nette\Object
    • Nette\String
  • Nette\Application
    • Application
    • AppForm
    • Control
    • Presenter
    • PresenterCompo­nent
    • PresenterRequest
    • Routování
    • MultiRouter
    • Route
    • SimpleRouter
  • Nette\Caching
  • Nette\Forms
  • Nette\IO\SafeS­tream
  • Nette\Loaders
  • Nette\Security
    • Bezpečnost aplikací
    • Identity
    • SimpleAuthenti­cator
    • Permission
    • Dynamická správa rolí a zdrojů
  • Nette\Templates
    • Template
    • Template Filters
    • Template Helpers
  • Nette\Web
    • Web
    • Ftp
    • Html
    • HttpRequest
    • HttpResponse
    • Session
    • User
Naposledy změněno 12. 12. 2008 Edituj Historie Poslední změny

Ajax & snippety

AJAXový požadavek lze detekovat metodou třídy (resp. služby) zapouzdřující HTTP požadavek: Environment::getHttpRequest()->isAjax() (detekuje podle HTTP hlavičky X-Requested-With). Uvnitř presenteru je k dispozici „zkratka“ v podobě metody $presenter->isAjax().

AJAXový požadavek se nijak neliší od klasického požadavku – je zavolán presenter s určitým view a parametry. Je také věcí presenteru, jak bude na něj reagovat: může použít vlastní rutinu, která vrátí nějaký fragment HTML kódu (HTML snippet), XML dokument, JSON objekt nebo kód v JavaScriptu. K tomu lze využít i předpřipravený objekt šablony – například tak, že při detekci AJAXu zvolí speciální šablonu:

public function handleClick($param)
{
    if ($this->isAjax()) {
        $this->template->setFile('...ajax.phtml');
    }
    ...
}

Nicméně daleko silnější nástroj představuje vestavěná podpora AJAXu. Díky ní lze udělat z obyčejné aplikace AJAXovou prakticky několika řádky kódu.

Myšlenka vychází z toho, že při prvotním (tedy neAJAXovém) požadavku se přenese celá stránka a poté se při každém již AJAXovém subrequestu (= požadavku na stejný presenter a view) přenášet pouze kód změněných částí. K tomu slouží dva mechanismy: invalidace a renderování snippetů.

Invalidace

Každý objekt třídy Control (což je i samotný Presenter) si umí zapamatovat, jestli při subrequestu došlo ke změnám, které si vyžadují jej překreslit. K tomu slouží triptych metod invalidateControl(), validateControl() a isControlInvalid(). Příklad:

public function handleLogin($user)
{
    // po přihlášení uživatele se musí objekt překreslit
    $this->invalidateControl();
    ...
}

Nette však nabízí ještě jemnější rozlišení, než na úrovni komponent. Uvedené metody mohou totiž jako parametr nabývat název tzv. „snippetu“, nebo-li ústřižku. Lze tedy invalidovat/va­lidovat na úrovni těchto snippetů (každý objekt může mít libovolné množství snippetů). Pokud se invaliduje celá komponenta, tak je i každý snippet považován za invalidní. Komponenta je invalidní i tehdy, pokud je invalidní některá její subkomponenta.

echo $this->isControlInvalid(); // -> FALSE

$this->invalidateControl('header'); // invaliduje snippet 'header'
echo $this->isControlInvalid('header'); // -> TRUE
echo $this->isControlInvalid('footer'); // -> FALSE
echo $this->isControlInvalid(); // -> TRUE, alespoň jeden snippet je invalid

$this->invalidateControl(); // invaliduje celou komponentu, každý snippet
echo $this->isControlInvalid('footer'); // -> TRUE

Komponenta, která přijímá signál, je automaticky označena za invalidní.

Díky invalidaci snippetů přesně víme, které části kterých prvků bude potřeba překreslit.

Renderování snippetů

Nette je založeno na myšlence logických, nikoliv grafických prvků, tj. objekt třídy Control nepředstavuje pravoúhlou oblast ve stránce, ale logickou komponentu, která se může renderovat i do více podob (např. DataGrid může mít jednu metodu pro vykreslení mřížky a druhou pro vykreslení „stránkovadla“ apod). Každý prvek může být navíc na stránce vykreslen vícekrát, nebo podmíněně, nebo pokaždé s jinou šablonou atd.

Není tedy možné jednoduše zavolat metodu render na každém invalidním objektu, vlastně ani žádný interface metodu render nedefinuje. K vykreslování je nutné přistupovat tak, jako když se kreslí celá stránka. (Přesněji řečeno, je možné jít touto cestou a vykreslit pouze invalidní snippety invalidních objektů, ale vaše aplikace musí být k tomu účelu vhodně navržena, kdežto vestavěná podpora AJAXu musí fungovat obecně).

Vykreslování stránky probíhá velmi podobně, jako u neAJAXového požadavku, načtou se tytéž šablony atd. Klíčovým úkolem však je vypustit ty části, které se na výstup vůbec dostat nemají, a ty, které se vykreslit mají, přidružit s identifikátorem a poslat klientovi ve formátu, kterému bude obslužný JavaScript rozumět.

Pokud se uvnitř šablony nachází control nebo snippet, musíme jej obalit párovou značkou {snippet} ... {/snippet} – ty totiž zajistí, že se vykreslený snippet vystřihne a předá AJAXovému ovladači. Také jej obalí pomocnou značkou <div> (lze použít i jinou značku). V uvedeném příkladě je snippet pojmenován jako header:

<html>
  <body>
  ...
  {snippet header}
  <h1>Hello .... </h1>
  {/snippet}

  </body>
</html>

Při využití této techniky je nutné si dát pozor na vkládané šablony pomocí {include $template}, které obsahují nějaké snippety, aby nebyly přeskočeny. Tomu lze zabránit přidáním zavináče před složené závorky, tedy použitím @{include $template}.

Komunikace s prohlížečem

Jednotlivé snippets společně s dalšími (i uživatelskými daty) se předají AJAXovému ovladači, který je dostupný přes $presenter->ajaxDriver. Pokud vám vestavěny driver nevyhovuje, můžete použít svůj (pohledem do zdrojového kódu zjistíte, že jde o velmi jednoduchou třídu). Výchozí driver předává data ve formátu JSON, předělat jej na XML je celkem triviální.

Jak to celé funguje pohromadě demostruje příklad Fifteen, jehož kód najdete v distribuci.

Nette Framework powered | dibi powered | Texy! powered | Institut Školení PHP