Kategorie: PHP

Smazání formuláře po odeslání Ajaxem

Pokud se nemusí stránka načítat celá znovu, je to vždy lepší. Ajax umí spousty zajímavých věcí, jako třeba odeslat formulář s komentářem k příspěvku v blogu a rovnou ho vykreslit na stránce, aniž by uživatel musel čekat na načtení celé stránky a pak znovu scrolovat dolů. Ale narazil jsem na malou nepříjemnost - formulář po odeslání zůstal vyplněný. Co s tím?

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

Přidat komentář

O mně

Jmenuji se Rudolf Svátek - lektor výpočetní techniky, trochu PHP programátor a SEO konzultant na volné noze.

Adresa

Příčná 326/3
736 01 Havířov

Kontakty

Email: office@rudolfsvatek.cz
Telefon: +420 777 828 353
Skype: svatekr