Nedaří se mi zprovoznit formulář s ajaxem

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

Ahoj všichni.

Nedaří se mi rozchodit ajax ve formuláři. Již déle používám ajax při obsluze signálů a to mi funguje dobře. Dnes se již několik hodin snažím rozchodit formulář a nechápu, proč to nejde. Na stejné stránce je i tlačítko na zajaxovaný signál a to šlape.

Mám to jako Control a pod ním je formulář.

nette.ajax.js mám nahraný a zinicializovaný.

Po kliknutí na odesílací tlačítko ajaxový požadavek normálně proběhne a v odpovědi se vrátí celá stránka(již tam jsou např. vypsané chyby, takže se form odeslal), ale nic se nepřekreslí.

Neajaxově to funguje.

{snippet responseForm}
<h2></h2>
<form class="form-horizontal ajax" n:name="responseForm">

    <div n:foreach="$form->errors as $error" class="alert alert-danger">
        {$error}
    </div>

		... kód formuláře .....

    <div class="form-group">
        <div class="col-md-9 col-md-offset-2">
            <input n:name="submit" class="btn btn-primary" value="Odeslat odpověď" />
        </div>
    </div>

</form>
{/snippet}

Formulář po zpracování refrešnu takto

		if (!$this->isAjax())
		{
			$this->redirect('this');
		}
		else
		{
			$this->redrawControl("responseForm");
			$form->setValues([], TRUE);
		}

Díky moc za pomoc.

Martin

Jan Mikeš
Člen | 771
+
0
-

Kde konkrétně ten redrawControl() voláš? V presenteru? Pošli prosím více kódu.

kejlicz
Člen | 201
+
0
-

Lexi napsal(a):

Kde konkrétně ten redrawControl() voláš? V presenteru? Pošli prosím více kódu.

<?php
namespace Kejzlar\Components;

class Response extends \Nette\Application\UI\Control
{
	/** @var \Kdyby\Doctrine\EntityManager  */
	private $em;
	/** @var \App\Facades\RegionFacade  */
	 ..... inicializace ......

	public function __construct(\Kdyby\Doctrine\EntityManager $em, ...........)
	{
		 ..... přiřazování hodnot ......
	}

	public function render()
	{
       ..... přiřazování hodnot ......
		$this->template->setFile(__DIR__ . "/Response.latte");
		$this->template->render();
	}

	public function createComponentResponseForm()
	{
		$form = new \Nette\Application\UI\Form;
		$form->addText("name");
		$form->addText("email")->setRequired("Je nutné vyplnit Váš email")
			->addRule(\Nette\Application\UI\Form::EMAIL, "Email není ve správném formátu. Prosím překontrolujte zadání.");

		// Nastavení předvyplněného emailu pokud je uživatel přihlášen
		if($this->dbUser instanceof \App\Entities\User)
		{
			$form["name"]->setDefaultValue($this->dbUser->getName());
			$form["email"]->setDefaultValue($this->dbUser->getUsername());
		}

		$form->addTextArea("content")->setRequired("Není vyplněn text odpovědi");
		$form->addUpload("file", "Soubor");

		$form->addCheckbox("success", NULL)->setRequired("Je třeba souhlasit v podmínkami webu zaškrtnutím 'Souhlasím'");

		$form->addSubmit("submit", "Uložit");

		$form->onSuccess[] = array($this, "proccessResponseForm");

		return $form;
	}

	public function proccessResponseForm($form)
	{
		$values = $form->getValues();

		.... ZPRACOVÁNÍ FORMULÁŘE  ........

		$this->flashMessage("Vaše odpověď byla úspěšně odeslána", "success");

		if (!$this->isAjax())
			$this->redirect('this');
		else {
			$this->getPresenter()->redrawControl("responseForm");
			$this->redrawControl("flash");
			$form->setValues([], TRUE);
		}

	}

}
Jan Mikeš
Člen | 771
+
+2
-

Nette\Application\UI\Control nemá metodu isAjax(), přiděláváš si ji tam nějak?
Nemůže být chyba v tom, že mixuješ snippety komponenty a snippety presenteru a neinvaliduješ správný?

kejlicz
Člen | 201
+
0
-

Asi jo. Jsem se v tom nějak zamotal. Jsem to osekal na minimum. Taky jsem upravil ověřování

!$this->isAjax()

na

!$this->getPresenter()->isAjax()

což by mělo podle testování fungovat.

Ale pořád jsem tak nějak na stejném místě. Jen jsem se trochu posunul v tom, že když je formulář v pořádku vyplněný, odešle se ajaxem a zobrazí se flash a obnoví se formulář.
Pokud ale má form nějakou chybu, zůstává stejná situace jako na začátku. Formulář se ajaxově odešle a přijde odpověď, v níž je komplet web stránka. Žádný snippety.

Chápu, že z tohodle popisu se blbě radí. Není někde funkční ukázka takového formu v komponentě? Abych to porovnal.

Díky

Lexi napsal(a):

Nette\Application\UI\Control nemá metodu isAjax(), přiděláváš si ji tam nějak?
Nemůže být chyba v tom, že mixuješ snippety komponenty a snippety presenteru a neinvaliduješ správný?

Editoval kejlicz (7. 10. 2016 1:32)

kejlicz
Člen | 201
+
0
-

Tak jsem se stylem pokus / omyl dostal k funkčnímu řešení. Nebylo mi jasné co se děje při validaci, aby se to odeslalo ajaxem. Tak jsem zkusil přidat

	public function validateResponseForm($form)
	{
		if (!$this->getPresenter()->isAjax())
		{
			$this->redirect('this');
		}
		else {
			$this->redrawControl("responseForm");
			$this->redrawControl("flash2");
		}
	}

a ono všechno funguje jak má. Takhle se to má dělat nebo jsem jen něco obešel?

GEpic
Člen | 566
+
0
-

Příště zkus:

{snippet responseForm}
<h2></h2>
<form class="form-horizontal" n:name="responseForm">

    <div n:foreach="$form->errors as $error" class="alert alert-danger">
        {$error}
    </div>

        ... kód formuláře .....

    <div class="form-group">
        <div class="col-md-9 col-md-offset-2">
            <input n:name="submit" class="ajax btn btn-primary" value="Odeslat odpověď" />
        </div>
    </div>

</form>
{/snippet}

Editoval GEpic (7. 10. 2016 3:18)

CZechBoY
Člen | 3608
+
+2
-

Jo tys totiž měl redraw snippetu v success události a když má formulář chyby tak se do success události samozřejmě nedostane.

Jan Mikeš
Člen | 771
+
+1
-

@GEpic neměl by být rozdíl, jestli ajax class přidá formu nebo submitu.
Je to jak píše @CZechBoY
@kejlicz ještě by jsi mohl zkusit dát ten redrawControl() úplně pryč z formuláře, nechat tam pouze

	if (!$this->getPresenter()->isAjax())
{
    $this->redirect('this');
}

A redrawControl() přesunout do attached() což si myslím, že je i vhodnější způsob ;) Napadlo mě ještě to dát do render() componenty, ale u toho ti nejsem v tuto chvíli schopen říct, že bude fungovat, každopádně to můžeš vyzkoušet.

edit: ještě abych vysvětlit, formuláři by totiž mělo být úplně šumák jak ho zpracováváš a nějaké překreslování snippetů není jeho zodpovědnost, měla by se o to starat komponenta/presenter a tedy je i snaha umístit „na správné místo“ invalidaci snippetů

Editoval Lexi (7. 10. 2016 9:44)

kejlicz
Člen | 201
+
0
-

@GEpic : To je opravdu to samé
@CZechBoY : To mi taky vrtalo hlavou, ale nějak jsem nemohl najít na netu funkční ukázku
@Lexi : Udělal jsem to jak píšeš (redrawControl do attached()) a šlape to. V render() metodě to nešlo.

Díky MOC za pomoc.

Editoval kejlicz (7. 10. 2016 10:41)

GEpic
Člen | 566
+
0
-

kejlicz napsal(a):

@GEpic : To je opravdu to samé
@CZechBoY : To mi taky vrtalo hlavou, ale nějak jsem nemohl najít na netu funkční ukázku
@Lexi : Udělal jsem to jak píšeš (redrawControl do attached()) a šlape to. V render() metodě to nešlo.

Díky MOC za pomoc.

To sice je, ale třídu buttonu můžeš nastavit už jednoduše v PHP, a můžeš tak nastavit zda-li bude formulář ajaxový nebo ne rovnou v PHP, pak můžeš s ledovým klidem klidně vypsat formulář přes control, namísto ručně (pokud k tomu jednou dojdeš).

kejlicz
Člen | 201
+
0
-

GEpic napsal(a):

kejlicz napsal(a):

@GEpic : To je opravdu to samé
@CZechBoY : To mi taky vrtalo hlavou, ale nějak jsem nemohl najít na netu funkční ukázku
@Lexi : Udělal jsem to jak píšeš (redrawControl do attached()) a šlape to. V render() metodě to nešlo.

Díky MOC za pomoc.

To sice je, ale třídu buttonu můžeš nastavit už jednoduše v PHP, a můžeš tak nastavit zda-li bude formulář ajaxový nebo ne rovnou v PHP, pak můžeš s ledovým klidem klidně vypsat formulář přes control, namísto ručně (pokud k tomu jednou dojdeš).

To můžu i u formuláře

$form->getElementPrototype()->class('ajax');

Renderování přes {control xxx} je sice fajn, ale na nějaké složitější formuláře je pro mne určitě lepší renderovat ručně.

Editoval kejlicz (7. 10. 2016 12:19)