Jednoduchy ajax formular – zacatecnicka otazka

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

Ahoj vsem. Chtel bych se zeptat na jednu zacatecnickou drobnost u ajaxu.

Koukal jsem se na dva priklady na planette a oba se lisi v tom, jestli se neco nastavuje v js nebo ne.
https://doc.nette.org/…ication/ajax – zde se nastavi jen zaklad – nette.init (to mam) a nic vice
https://pla.nette.org/…ivajici-ajax#… – zde se nastavuje preventdefault u odeslani formulare a nejake dalsi veci

V kterych pripadech je tedy nutne nastavovat to rucne a v kterych to resi samo nette?

Mam jednoduchou komponentu, ktera obsahuje metody:

public function render()
{
$template = $this->template;
$template->setFile(__DIR__ . '/Login.latte');

	$form = new \Nette\Application\UI\Form();
	$form->addText('name', 'Emailová adresa');
	$form->addPassword('password', 'Heslo');
$form->addSubmit('send', 'Přihlásit se');
$form->onSuccess[] = $this->processForm;
	$template->form = $form;

	$template->render();
}

	public function processForm($form)
{
		if ($this->isAjax()) {
		$template->error = "test";
    $this->redrawControl('login_result');
		}
}

A k ni lattecko:

{snippet login_result}{ifset $error}<div class="alert alert-danger alert-dismissable login-error">{$error}</div>{/ifset}{/snippet}
{snippet login_control}{$form}{/snippet}

Problem je v tom, ze po odeslani formulare se normalne nacte stranka, tedy nejedna se o ajax (v konzoli neni zadna chyba). V koznoli se po odeslani objevi akorat toto:

XHR Loaded (nazev - 200 OK - 230.56699999142438ms - 16.747KB)
VM4967:3 http://url.cz/xxx?name=a&password=&send=P%C5%99ihl%C3%A1sit+se
VM4968:3 Object {startedDateTime: "2015-05-31T15:07:03.800Z", time: 230.56699999142438, request: Object, response: Object, cache: Object…}

Kazdopadne promenna $error je vzdy prazdna. I kdyz to upravim takto:

	public function processForm($form)
{
		if ($this->isAjax()) {
		$template->error = "test";
    $this->redrawControl('login_result');
		}
		$template->error = "test";
    $this->redrawControl('login_result');
}

Kde jsem mohl udelat chybu? Je v tomto pripade rucne upravit JS tak, aby tam byl preventdefault a dalsi veci pro znovuvykresleni snippetu? Hlavne nechapu, proc je promenna $error prazdna, i kdyz se formular odeslal.

Predem diky za radu, pekny zbytek vikendu vsem.

Editoval hotline (31. 5. 2015 17:16)

Lukeluha
Člen | 130
+
+2
-
  1. Potřebuješ celému formuláři nastavit class=ajax – jinak by knihovna nevěděla, že se má formulář odesílat AJAXem – o nic jiného by ses neměl starat.
  2. Formulář vytvářej v továrničce createComponentForm a v šabloně poté formulář vykreslíš {control form}.
  3. Druhý tutoriál je 5 let starý, ještě neexistovala knihovna od Honzy Dobeše – máš ji správně includnutou?
  4. Pokud se odešle formulář klasicky a zavoláš redrawControl, nevím, jestli to nezpůosíb nějakou neplechu (v processForm by mělo být if ($this->isAjax()) ... else pouze nastav proměnnou
  5. Používej flash message :)

Editoval Lukeluha (1. 6. 2015 9:11)

hotline
Člen | 41
+
0
-

Perfektni, diky moc za odpoved, nastavil jsem to jak pises (krome flashek, v tomto pripade to resim trosku jinak) a formular se odesila ajaxove. Jeste tam ale nekde bude nejaka chybka v metode processForm($form), protoze po odeslani dostavam 500 error.

500 Internal Server Error
		609ms
jquery.min.js (řádek 6)

exception 'Nette\MemberAccessException' with message 'Call to undefined method LoginControl::isAjax(
).' in /site/vendor/nette/utils/src/Utils/ObjectMixin
.php:96
Stack trace:
#0 /site/vendor/nette/utils/src/Utils/Object
.php(77): Nette\Utils\ObjectMixin::call(Object(LoginControl), 'isAjax', Array)
#1 /site/app/components/Login.php(85): Nette
\Object->__call('isAjax', Array)
#2 /site/app/components/Login.php(85): LoginControl-
>isAjax()
#3 [internal function]: LoginControl->processForm(Object(Nette\Application\UI\Form), NULL)
#4 /site/vendor/nette/utils/src/Utils/Callback
.php(67): call_user_func_array(Object(Closure), Array)
#5 /site/vendor/nette/forms/src/Forms/Form
.php(420): Nette\Utils\Callback::invoke(Object(Closure), Object(Nette\Application\UI\Form), NULL)
#6 /site/vendor/nette/application/src/Application
/UI/Form.php(137): Nette\Forms\Form->fireEvents()
#7 /site/vendor/nette/application/src/Application
/UI/Presenter.php(326): Nette\Application\UI\Form->signalReceived('submit')
#8 /site/vendor/nette/application/src/Application
/UI/Presenter.php(207): Nette\Application\UI\Presenter->processSignal()
#9 /site/vendor/nette/application/src/Application
/Application.php(148): Nette\Application\UI\Presenter->run(Object(Nette\Application\Request))
#10 /site/vendor/nette/application/src/Application
/Application.php(88): Nette\Application\Application->processRequest(Object(Nette\Application\Request
))
#11 /site/www/index.php(11): Nette\Application
\Application->run()
#12 {main}
(stored in /site/app/../log/exception-2015-06-01-10-23-28-b456a513f9c150292508bbdc53f88995
.html)

Kdyz odeberu podminku na $this-isAjax(), dostavam:

500 Internal Server Error
		234ms
jquery.min.js (řádek 6)

exception 'ErrorException' with message 'Creating default object from empty value' in site/app/components/Login.php:86
Stack trace:
#0 /site/app/components/Login.php(86): Tracy
\Debugger::errorHandler(2, 'Creating defaul...', '/site/...', 86, Array)
#1 [internal function]: LoginControl->processForm(Object(Nette\Application\UI\Form), NULL)
#2 /site/vendor/nette/utils/src/Utils/Callback
.php(67): call_user_func_array(Object(Closure), Array)
#3 /site/vendor/nette/forms/src/Forms/Form
.php(420): Nette\Utils\Callback::invoke(Object(Closure), Object(Nette\Application\UI\Form), NULL)
#4 /site/vendor/nette/application/src/Application
/UI/Form.php(137): Nette\Forms\Form->fireEvents()
#5 /site/vendor/nette/application/src/Application
/UI/Presenter.php(326): Nette\Application\UI\Form->signalReceived('submit')
#6 /site/vendor/nette/application/src/Application
/UI/Presenter.php(207): Nette\Application\UI\Presenter->processSignal()
#7 /site/vendor/nette/application/src/Application
/Application.php(148): Nette\Application\UI\Presenter->run(Object(Nette\Application\Request))
#8 /site/vendor/nette/application/src/Application
/Application.php(88): Nette\Application\Application->processRequest(Object(Nette\Application\Request
))
#9 /site/www/index.php(11): Nette\Application
\Application->run()
#10 {main}
(stored in /site/app/../log/exception-2015-06-01-10-30-05-ad5e74bfe66298d61444b69e303bfd4b
.html)

Login.php:86 je $template->error = "test"; Pokousim se najit pricinu, ale kdybyste ji tam rychlym pohledem do kodu videli, reknete prosim. Postupoval jsem podle tohoto tutorialu.

David Matějka
Moderator | 6445
+
+2
-

$this->isAjax()$this->presenter->isAjax()
$template->error$this->template->error

hotline
Člen | 41
+
0
-

Skvele, diky. Posledni otazka: kdyz jsem resil ajax rucne bez frameworku a potreboval jsem zjistovat, jake tlacitko uzivatel stisknul pri odeslani formulare (v jednom formualari jich mam vice), defaultne se hodnota tlacitka vubec neodesilala a musel jsem to resit nejak takhle:

var values = $(this).closest('form').serialize() + '&' + this.name;
Viz. treba Ajax post serialize() does not include button name and value

Nesetkali jste se s tim nekdo v Nette? Vse mi funguje v poradku, data si vytahnu pres $values = $form->getValues(TRUE);, ale $values['send'] neexistuje. Ostatni pole ano.

Editoval hotline (1. 6. 2015 13:22)

David Matějka
Moderator | 6445
+
+2
-
if ($form['send']->isSubmittedBy()) {
	...
}