AJAXově načítané oznámení

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

Zdravím,

chtěl bych, aby se mi všechny zprávy (oznámení, chyby…) načítaly pomocí javascriptu.

Jednou věcí je ošetření vstupu na straně klienta. To jsem vyřešil tak, že jsem upravil v nette.js funkci Nette.addError, takže když je nějaké formulářové políčko required, tak se mi pěkně javascriptem zobrazí chybová zpráva. To funguje skvěle.

Druhou věcí ale je všechno to, co už nevyřeší jen javascript. Například přihlašování – to už musí řešit PHP. Pokud se přihlašování nepovede, napíšu v presenteru $this->error('chyba');, nebo třeba $this->flashMessage('chyba'); a chci, aby se mi opět zobrazila javascriptem přívětivá zpráva o chybě. O tom, jak pracovat s AJAXem (snippety) jsem četl. Nicméně nevím, jak vyřešit tohleto. Můřu třeba dát blok, kde se vypisují flash zprávy do snippetu, ale ta zpráva se má zobrazit nějakým javascriptovým příkazem – jak na to? Jak AJAXem poslat poslat javascriptový příkaz a navíc, jak zařídit, aby to dělal ta vestavěná funkce automaticky?

A další věcí je, že bych třeba někdy chtěl zobrazit chybu (či prostě oznámení) přímo k nějakému políčku formuláře (typycký příklad – kontrola, jestli je možné si zaregistrovat takové uživatelské jméno). V šabloně bych si to představoval tak, že když tohle budu chtít, tak si tam vždy k tomu určitému políčku napíšu nějaký div, do kterého se mají vkládat oznámení ke konkrétnímu inputu, ale jak to pořešit v presenterech? Nejvíc by mi třeba vyhovovalo, kdyby měla funkce flashMessage() nějaký atribut, kterým bych definoval místo, kam se má zpráva napsat, ale jak udělat toto? Měnit kód nette natvrdo určitě není správné.

Díky moc za odpovědi

akadlec
Člen | 1326
+
0
-

Tak prvně by sis měl ujasnit co vše a jak chceš řešit.

  1. Samotné flash message můžeš řešit tak že je nebudeš renderovat jako snippety ale budeš si je posílat přímo jako texty v response pro ajaxové requesty a pro klasické si je budeš předávat jako js proměnné.
  2. A nebo to budeš řešit klasicky jako snippety stránky a budeš je vkládat do DIVů. Tyto DIVy uděláš jako hidden a pomocí JS z ních vyzobeš samotné texty které zobrazíš dle libosti.
  3. Zobrazování chyb atd. pokud se jedná o formuláře je už dávno řešeno a nette tam ty chyby dává samo, pokud používáš nettí renderování formu, pokud vlastní tak si to tam můžeš vložit dle libosti.
Tepster
Člen | 28
+
0
-

1. Samotné flash message můžeš řešit tak že je nebudeš renderovat jako snippety ale budeš si je posílat přímo jako texty v response pro ajaxové requesty a pro klasické si je budeš předávat jako js proměnné.

Jak? Napadlo mě, že bych v BasePresenteru podědil nějakou funkci a dal do ní něco jako

<?php
	if ($this->isAjax())
		$this->payload->messages = $this->flashMessages;
?>

ale do jaké funkce to mám dát, aby se to provedlo těsně před odesláním response zpět klientovi?

3. Zobrazování chyb atd. pokud se jedná o formuláře je už dávno řešeno a nette tam ty chyby dává samo, pokud používáš nettí renderování formu, pokud vlastní tak si to tam můžeš vložit dle libosti.

Co tím myslíš, že je to řešeno ve výchozím rendereru? Potřeboval bych, aby se mi ty errory vracely jako payload. Klidně si napíšu vlastní renderer, který bude dědit z toho výchozího a zmením mu nějakou funkci, ve které by se zjišťovalo, jestli se načítá ajaxem a pokud ano, vypsal bych ty errory do payload. Jak se ale v takové funkci dostanu k tomu, k čemuž se v presenteru dostanu přes $this->payload?

akadlec
Člen | 1326
+
0
-
  1. no přesně takhle, v render metodě.
  2. Pokud to chceš házet do payloadu, tak si musíš u formu upravit zpracování chyb a vytahovat je z něj a pak si je předáš jako flash messages
Tepster
Člen | 28
+
0
-

1. no přesně takhle, v render metodě.

A konkrétně? Podle API dokumentace mohu v presenteru použít metody beforeRender() a afterRender(). Zkoušel jsem je obě:

<?php
abstract class BasePresenter extends Nette\Application\UI\Presenter
{

	protected function beforeRender()
	{
		parent::beforeRender();

		if ($this->isAjax())
			$this->payload->test = "nesmysl";
	}


	protected function afterRender()
	{
		parent::afterRender();

		if ($this->isAjax())
			$this->payload->druhytest = "nesmysl2";
	}

}
?>

ale prostě to nic nevrací. Jde to jen, když ten kód dám do metody startup(). Mě přijde docela logické, že se ty metody vůbec neprovedou, protože při ajaxovém požadavku se vůbec nic nevykresluje (nemám tam ani žádné snippety).

2. Pokud to chceš házet do payloadu, tak si musíš u formu upravit zpracování chyb a vytahovat je z něj a pak si je předáš jako flash messages

Dobře. Ale podobný dotaz, jako předtím – jak se ve zděděné třídě od DefaultFormRenderer dostanu k flashMessages?

Editoval Tepster (30. 10. 2014 10:09)

akadlec
Člen | 1326
+
0
-
  1. V before render ti to musí fungovat, pokud tedy děláš nějaký rendering třeba snippetů což já dělám v každém požadavku. Pokud neděláš tak si můžeš request terminovat sám a pak posílat payload dle potřeby.
  2. Proč se chceš dostávat do DefaultFormRenderer? Stačí využít eventy které ten formulář má. Stačí si pak přidat onSubmit akci nějak takto:
	public function submit(Form $form)
	{
		// Form have some error messages
		if ($form->hasErrors()) {
			// Add form errors to flash messages
			foreach ($form->getErrors() as $error) {
				// ...add flash message to parent control
				$form->getParent()->flashMessage($error, "warning");
			}

			// Add flag that form is not ok
			$form->getPresenter()->payload->formOk = FALSE;

			// Invalidate form snippet
			$form->getParent()->redrawControl('formArea');

		// Form is without errors
		} else {
			// Add flag that form is ok
			$form->getPresenter()->payload->formOk = TRUE;
		}
	}
Tepster
Člen | 28
+
0
-

Díky moc. Funguje.