Formuláře a chybové hlášky při redirectu
- Etch
- Člen | 403
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)
- vlki
- Člen | 218
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
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)
- David Grudl
- Nette Core | 8218
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];
}