Ajax, snippety a formuláře
Vložit na stránky formulář tak, aby se odesílal Ajaxově, není nic těžkého. Na Nette je to dobře popsané, takže jen krátké shrnutí:
Ajaxový formulář
Jakýkoliv formulář stačí opatřit třídou "ajax". Buď dáš tuto třídu přímo k formuláři, nebo stačí k submit tlačítku. Například takto:
<form n:name="form" class="ajax">
<textarea name="comment"></textarea>
<input n:name="submit">
</form>
nebo
<form n:name="form">
<textarea name="comment"></textarea>
<input n:name="submit" class="ajax">
</form>
No jo - Naja
V dokumentaci Nette se píše, že je potřeba vložit na stránky knihovnu Naja. Stačí ji buď stáhnout a používat ji lokálně, nebo vložit odkazem:
<script src="https://unpkg.com/naja@2/dist/Naja.min.js"></script>
Tady jsem narazil na první zádrhel, když ani po vložení knihovny se mi aplikace Ajaxově nechovala. Na Nette přímo není zmínka o tom, že by se měla inicializovat. To jsem našel až přím na stránkách knihovny Naja. Takže pod načtení knihovny ještě proveď tu inicializaci:
<script>
document.addEventListener('DOMContentLoaded', function() {
naja.initialize();
});
</script>
Snippet s komentáři
K článkům v blogu je možné vkládat komentáře. Já to například dělám tak, že na formuláři odchytávám událost onSuccess:
$form->onSuccess[] = function (Form $form) {
$values = $form->getValues();
$item = new Comment();
$item->hydrate($values);
$this->commentInsertFacade->insert($item);
if ($this->getPresenter()->isAjax()) {
$this->redrawControl('commentList');
$form->reset();
} else {
$this->getPresenter()->redirect('this');
}
};
Ta metoda ->hydrate jen naplní entitu hodnotami z odeslaného formuláře. Zajímavé pro tebe je to, co se děje na řádku 7. Tam se zjistí, zda je formulář odeslán Ajaxem. Pokud ano, překreslí se snipper s názvem commentList. Je tedy potřeba tokový snippet mít a v něm nechat zobrazovat všechny komentáře. Do šablony tedy vlož třeba takovýto kód:
<div n:snippet="commentList">
<div class="comments">
<h3>Komentáře</h3>
<div n:foreach="$comments as $comment" class="comment-box">
<div class="name">{$comment->name}</div>
<div class="text">{$comment->text}</div>
</div>
</div>
</div>
Prostě v cyklu vypíšeme všechny komentáře. Důležité je, že jsou v DIVu, který je označen jako snippet s názvem "commentList". A právě tento kus stránky se po odeslání formuláře překreslí. Nejprve se tedy vloží komentář do databáze. Nesmíme ale zapomenut na to, že po odeslání formuláře ještě musíme z databáze znovu získat všechny komentáře včetně toho nového. Já si všechny formuláře důsledně vyrábím jako komponenty. Takže mi stačí v metodě render() zavolat nějaký dotaz. Může to vypadat takto:
public function render(): void
{
$this->getTemplate()->setFile($this->templateFile);
$this->template->comments = $this->commentSelectFacade->getAllForBlog($this->id);
$this->getTemplate()->render();
}
A teď to vymazání formuláře
Takhle to vcelku dobře jede - nové komentáře lze přidávat a rovnou se zobrazují pod článkem. Jen ten formulář prostě zůstává vyplněný a dost to otravuje, když chceš napsat nějaký další komentář. Takže trik je zapřáhnout knihovnu Naja. Ta umí odchytit událost 'success', což je chvíle, kdy se podařilo odeslat nějaký formulář Ajaxově. A to je také okamžik, kdy chceme resetovat formulář.
Do snippetu "commentList" tedy přidáme obslužný javascript, který to udělá:
<script>
document.addEventListener('DOMContentLoaded', function() {
naja.addEventListener('success', function(event) {
document.getElementById('frm-commentForm').reset();
});
});
</script>
Předpokladem je, že tvůj formulář má ID="frm-commentForm".
A to je vše přátelé.
Komentáře