Formuláře a chybové hlášky při redirectu

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

Omlouvám se za triviální dotaz, ale nette zkouším teprve druhý den takže se ještě moc nechytám.

Pokud budu mít formulář udělaný pomocí AppForm a potřebuji zamezit jeho opětovnému odeslání pomocí refreshe stránky takže udělám redirect jenže bych potřeboval po redirectu zobrazit zprávu o úspěchu či selhání operace. Teď to řeším ve zkratce následujícím způsobem pomocí signálu :

<?php
class TestPresenter extends Presenter{

	public function prepareDefault(){
		$form = new AppForm($this, 'delete');
		$form->addText('id', 'ID : ')
			 ->addRule(Form::NUMERIC, 'Zadané ID musí být číslo');
		$form->addSubmit('deletebutton', 'Smazat');
		$form->onSubmit[] = array($this, "deleteSubmit");
		$this->template->form = $form;
	}

	// Zpracování požadavku

	public function deleteSubmit($sender){
		$data = $sender->getValues();
		if($data['id'] == 1){
			$this->redirect('DeleteOk!');
		}else{
			$this->redirect('DeleteError!');
		}
	}

	// Nastavení Infa při úspěchu

	public function handleDeleteOk(){
		$this->template->info = 'Smazáno';
	}

	// Nastavení Infa při selháni

	public function handleDeleteError(){
		$this->template->info = 'Mazání selhalo';
	}
}
?>

Ale přesto by mě zajímalo jestli to nejde řešit nějakým jednodušším způsobem. Předem děkuji.

Editoval Etch (24. 9. 2008 20:27)

Honza Marek
Člen | 1664
+
0
-

Zkusit sessions?

vlki
Člen | 218
+
0
-

Osobne jsem se inspiroval resenim v CakePHP, kde se da vyhodit flash zprava. Idealni pro vyhazovani hlasek po uspesne uprave/pridani/vymazu. Postaveno je to na sessions. Prikladam jednoduchou komponentu, ktera to zajistuje.

U setu se take nastavuje, jestli chci vyhodit error, varovani nebo potvrzeni. Podle toho se mi to obarvi cervene, zlute respektive zelene:)

<?php
class FlashControl extends Control
{

  protected $identifier = 'FlashControl';

  protected $types = array(
    'error',
    'warning',
    'success',
  );


  public function __construct(IComponentContainer $parent = NULL, $name = NULL)
  {

    parent::__construct($parent, $name);

    $namespace = Environment::getSession($this->identifier);

    foreach($this->types as $type) {
      if (!isset($namespace->$type)) {
        $namespace->$type = array();
      }
    }

  }


  public function set($message, $type = 'success')
  {

    if (!in_array($type, $this->types))
      $type = 'success';

    $namespace = Environment::getSession($this->identifier);
    if (!in_array($message, $namespace->$type)) {
      $namespace->{$type}[] = $message;
    }

  }


  public function render()
  {

    $template = $this->createTemplate();
    $template->setFile(Environment::getVariable('templatesDir') . '/components/FlashControl.phtml');

    $namespace = Environment::getSession($this->identifier);
    foreach($this->types as $type) {
      $template->$type = $namespace->$type;
      $namespace->$type = array();
    }
    $template->render();

  }

}
?>

Ale zajimalo by mne take, jestli to nekdo resi jeste lepe.

Editoval vlki (25. 9. 2008 10:41)

Etch
Člen | 403
+
0
-
if (!in_array($message, $namespace->$type)) {
  $namespace->$type[] = $message;
}

tohle musí být zapsáno myslím takto

if (!in_array($message, $namespace->$type)) {
  $namespace->{$type}[] = $message;
}

Jinak hezké. Mě hlavně zajímalo jestli už samo nette nemá v sobě zabudováno něco na posílání hlášek.

Editoval Etch (25. 9. 2008 4:06)

vlki
Člen | 218
+
0
-

To mas uplnou pravdu, ve svem prispevku opravim.

Pokud vim, tak tam nic takoveho neni.

LM
Člen | 206
+
0
-

U tohoto ale může dojít že se ta zpráva zobrazí v úplně jiném okně/panelu prohlížeče? lepší předávat v URL.

vlki
Člen | 218
+
0
-

To je pravda, ale kdyz si kontroluju, kam presmerovavam, tak jsem se jeste nesetkal s problemem…

phx
Člen | 651
+
0
-

Sance jsou male, ale pokud nekdo obnovi cilovou stranku ve dvou oknech ztak zprava bude v tom drivejsim.

Nebyla by ukazka te flash zpravy?

David Grudl
Nette Core | 8218
+
0
-

Flash messaging je věc, kde se raději neinspirujte frameworky, protože jsem ještě neviděl žádný, kde by to řešili dobře.

Fakta:

  • je běžná věc, že se pod jedním session ve dvou oknech provádí dvě operace
  • není neobvyklé odeslat oba formuláře téměř naráz
  • hláška se musí objevit ve správném okně, nezávisle na jiných oknech
  • a to i po refreshi (třeba kvůli nenačtenému obrázku, netrpělivému uživateli, …)

Pokud chápeme, že

  • okno prohlížeče představuje nejnižší rozlišovací jednotku
  • v rámci jedné session může operovat (a často operuje) naráz více oken
  • jednotlivá okna nelze na straně serveru odlišit

tak existuje jen jedno možné řešení – přenášet výsledek operace přes URL. Buď v cestě (redirect na example.com/success) nebo v parametru URL (example.com/sent.php?message=Odesláno+v+pořádku) a to nejlépe jen pomocí identifikátoru (example.com/sent.php?message=1). Identifikátor zprávy pak může být napevno propojen s textem ($messages[1] = 'Odesláno v pořádku') nebo může být proměnný:

$namespace = Environment::getSession('flash');
$id = uniqid();
$namespace[$id] = $message;
$namespace->setExpiration(1000, $id);

... redirect na example.com/sent.php?message=$id ...

if (isset($namespace[$id])) {
    echo $namespace[$id];
}
David Grudl
Nette Core | 8218
+
0
-

Flash messaging je nyní implementován přímo ve frameworku.