Obsah
Nette\Application\Control
Control je vykreslitelná komponenta.
Ta si umí navíc, kromě toho že se umí vykreslit, 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(), což je
základem AJAXu v Nette.
Nette však nabízí ještě jemnější rozlišení, než na úrovni Controlů, a to tzv. snippetů neboli ústřižků.
Poznámka: pro jednoduchost k pochopení budu v následujících odstavcích brát Control jako komponentu. To, že je vykreslitelná, vyplývá z překreslovací vlastnosti snippetů.
Lze tedy invalidovat/validovat na úrovni těchto snippetů (každá komponenta může mít libovolné množství snippetů). Pokud se invaliduje celou komponentu, tak je i každý snippet považován za invalidní. Komponenta je invalidní i tehdy, pokud je invalidní některá její subkomponenta. 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.
Komponenta (tedy přesněji vykreslitelná komponenta Control) nepředstavuje pravoúhlou oblast ve stránce, ale logickou komponentu, která se může renderovat i do více podob. Každá komponenta může být navíc na stránce vykreslena vícekrát, nebo podmíněně, nebo pokaždé s jinou šablonou atd.
Komponenta Control ač má mnoho společných rysů s Presenterem nemá svůj
životní cyklus v pravém slova smyslu. Jen metody attached() a
detached() umožňují detekovat, kdy byl Control
připojen k nebo odpojen od rodiče (presenteru či jiné komponenty).
O zachycení signálu se stará presenter, ten ho odevzdá komponentě, která je jeho příjemcem. Protože presenter je sám o sobě komponentou, tak ho klidně odevzdá i sám sobě.
Šablony
Třída Control obsahuje továrničku
createTemplate() na svou šablonu. Ta standardně vytvoří
šablonu, předá ji některé základní proměnné a zaregistruje standardní
helpery:
{**
* Template's description.
*
* @param Presenter $presenter
* @param Control $control
* @param Template $template
* @param array $flashes
* @param string $baseUri Environment::getVariable('baseUri');
*
* You can use these helpers:
* escape, escapeJs, escapeCss, cache,
* snippet, lower, upper, capitalize, stripTags,
* strip, date, nl2br, truncate, bytes
*}
Pro pohodlnější práci v šablonách (hlavně v při vaší další práci v budoucnu) by každá šablona měla obsahovat hlavičku popisující proměnné, které v ní lze využívat.
Strom komponent
Každá komponenta děděná z třídy Control má jako první
parametr konstruktoru rodiče (IComponentContainer) v hierarchii
stromu komponent. Rodičem může být Presenter, nějaká
komponenta nebo jakýkoliv jiný objekt implementující rozhraní
IComponentContainer. Hierarchie pak může vypadat
i nějak takto:
Presenter
|
--Control { implementuje IComponentContainer => může být rodičem }
|
--Component
|
--Component { neimplementuje IComponentContainer => nemůže být rodičem }
|
--Control
|
--Component
Protože Control samotný neumí generovat odkazy, ale jen
signály, potřebujeme jej svázat s Presenterem. Podle struktury a zanoření
hierarchie se můžeme k presenteru dovolat i z podkomponent a používat
jeho veřejné metody.
$presenter = $control->getPresenter();
Hierarchie vzniká připojováním komponent do stromu komponent. Při vytváření komponenty uvedeme v parametru konstruktoru instanci jejího rodiče a řetězec se jménem komponenty. Uvedením stejné komponenty pod různými jmény se dá dosáhnout například zobrazení jedné komponenty na stránce vícekrát.
Komponentový model Nette umožňuje velmi dynamickou práci se stromem (komponenty můžeme vyjímat, přesouvat, přidávat), proto by byla chyba se spoléhat na to, že po vytvoření komponenty je hned znám rodič, rodič rodiče atd. Nemusí být.
$control = new NewsControl;
// ...
$parent->addComponent($control, 'shortNews');
// nebo alternativně starším (statickým) způsobem
$control = new NewsControl($parent, 'shortNews');
Flash zprávy
Vizuální komponenta Control má své vlastní úložiště
flash zpráv nezávislé na presenteru (metoda flashMessage patří
třídě Control).
Jde o zprávy, které např. informují o výsledku operace a uživateli se
zobrazí až po přesměrování. Zasílání obstarává metoda
flashMessage() třídy Control (tj. je možno
zasílat zprávy i na úrovni komponent).
Kód presenteru nebo komponenty:
public function deleteFormSubmitted(AppForm $form)
{
Model::delete(); // něco smažeme
$this->flashMessage('Položka byla smazána.');
// nebo pokud chceme uložit zprávu přímo do presenteru
$this->getPresenter()->flashMessage('Položka byla smazána.');
$this->redirect('default');
}
Metoda flashMessage() zprávu vkládá přímo do šablony do
parametru flashes (jako pole objektů stdClass).
Šablona pro vypsání zpráv pak může vypadat třeba takto:
{foreach $flashes as $flash}
<div class="flash">{$flash->message}</div>
{/foreach}
Jako druhý parametr metody lze uvést typ zprávy (výchozí hodnota je „info“) nebo její kód.
$this->flashMessage('Položka nebyla smazána!', 'warning');
Typ zprávy pak lze použít například jako CSS třídu:
{foreach $flashes as $flash}
<div class="flash {$flash->type}">{$flash->message}</div>
{/foreach}
Také je možné do zprávy přidat extra informace:
$message = $this->flashMessage('Obrázek byl uložen.');
$message->image = $image;
$message->width = 123;
Nejdůležitejší samozřejmě je, že pokud po uložení zprávy
flashMessage() následuje přesměrování, bude i v dalším
požadavku v šabloně existovat stejný parametr flashes. Zprávy
zůstanou poté živé další 3 sekundy – například pro případ, že by
z důvodu chybného přenosu uživatel stránku dal obnovit. Pokud někdo
dvakrát za sebou obnoví stránku (F5), tak mu zpráva tedy nezmizí, pokud
klikne jinam, tak ji už neuvidí.
Příklad zpracování událostí komponenty s flashovými zprávami
Tento způsob vede k lepší znovupoužitelnosti komponenty, na událost si její vlastník reaguje zcela po svém.
class Komponenta extends Control
{
/** @var array handlery události Xyz */
public $onXyz;
public function handleLogin()
{
...
$this->onXyz(); // volej handlery
}
}
class HomepagePresenter extends Presenter
{
public function startup()
{
$komponenta = new Komponenta($this, 'k');
$komponenta->onXyz[] = array($this, 'xyzHandler'); // registruje handler
}
public function xyzHandler()
{
$this->flashMessage('Uživatel byl přihlášen.');
}
}
Viz také:
- Control API reference
- IPartiallyRenderable API reference
- Ajax & Snippety



