Řešení formulářů v administrační komponentě
- Odo
- Člen | 48
Ahoj všem,
potřeboval bych poradit, jak nejlépe vyřešit „administrační“ komponentu. Komponenta zobrazuje seznam položek + tlačítka pro různé akce, které posílají signály (přes AJAX). Stránkování, řazení, apod., je jednoduché, protože se pouze na základě parametrů překreslí snippety. Narážím ale na problém s editačními formuláři, u kterých bych potřeboval něco jako action v presenterech.
Komponenta vypadá (zjednodušeně) takto:
abstract class AdminControl extends Nette\Application\UI\Control
{
protected $model;
/** @persistent */
public $page = 1;
/** @persistent */
public $size = 10;
/** @persistent */
public $sort = null;
/** @persistent */
public $id = null;
function __construct(Model\AdminManager $model)
{
parent::__construct();
$this->model = $model;
}
function render()
{
$this->template->data = $this->model->getAll($this->page, $this->size, $this->sort);
// naplnění dalších parametrů šablony
$this->template->render(__DIR__.'/templates/AdminControl.latte');
}
protected function redrawSnippets()
{
$this->redrawControl('flash');
$this->redrawControl('grid');
$this->redrawControl('form');
}
function handlePaginate($page)
{
$this->redrawSnippets();
}
function handleResize($size)
{
$this->redrawSnippets();
}
function handleSort($sort)
{
$this->redrawSnippets();
}
function handleDelete($id)
{
$this->model->deleteItem($id);
$this->flashMessage('Záznam byl smazán.', 'info');
$this->redrawSnippets();
}
function handleEdit($id) // standardní editační formulář
{
$this->redrawControl('flash');
$this->redrawControl('form');
$this->template->action = 'edit';
}
function handleManage($id) // další editační formulář
{
$this->redrawControl('flash');
$this->redrawControl('form');
$this->template->action = 'manage';
}
protected function createComponentAdminForm()
{
$item = $this->model->getItem($this->id);
$form = new \App\BaseForm;
$form->getElementPrototype()->class('ajax');
// přidání prvků do formuláře
$form->setDefaults($this->item);
$form->onSuccess[] = [$this, 'adminFormSucceeded'];
$form->addProtection();
return $form;
}
function adminFormSucceeded($form, $values)
{
try {
$this->model->setItem($this->id, $values);
$this->flashMessage('Změny byly uloženy.', 'success');
$this->redrawSnippets();
return;
}
catch (Nette\Database\UniqueConstraintViolationException $e) {
$form->addError('Chyba! Záznam již v databázi existuje. Zkuste změnit duplicitní údaje.');
}
catch (Nette\Database\DriverException $e) {
$form->addError('Chyba! Záznam se nepodařilo uložit. Zkuste to znovu.');
bdump($e);
}
$this->template->action = 'edit'; // při chybě se formulář znovu zobrazí
$this->redrawControl('form');
}
}
{import @layout.latte}
{import $presenter->getTemplate()->getFile()}
<h1>
{include #"$name-title"}
<a class="ajax btn btn-success" n:href="edit!,0"><span class="glyphicon glyphicon-plus"></span> Přidat</a>
</h1>
{snippet flash}
{foreach $flashes as $flash}
{include #alert, type => $flash->type, message => $flash->message}
{/foreach}
{/snippet}
{snippet form}
{default $action = ''}
{if $action == 'edit'}
{control adminForm}
{/if}
{if $action == 'crop'}
<img id="crop" src="{$image}{date('?YmdHis')}" alt>
{control cropForm}
{/if}
{if $action == 'manage'}
{include #"$name-manager"}
{/if}
{/snippet}
{snippet grid}
<div class="table-responsive">
<table class="data-grid table table-condensed table-striped table-hover">
<thead>
<tr>
{* hlavička *}
</tr>
</thead>
<tbody>
<tr n:foreach="$data as $item">
{include #"$name-item", item => $item}
<td>
<a class="ajax btn btn-primary"
n:href="edit!,$item->id"><span class="glyphicon glyphicon-pencil"></span></a>
<a class="datagrid-delete btn btn-danger"
n:href="delete!,$item->id"><span class="glyphicon glyphicon-trash"></span></a>
</td>
</tr>
</tbody>
<tfoot>
<tr>
{* patička - stránkovač *}
</tr>
</tfoot>
</table>
</div>
{/snippet}
Komponenty pro konkrétní věci (soubory, videa, uživatelé, apod.) jsou pak od ní odvozené a řeší si pouze zobrazení položek a zpracování formulářů.
U některých komponent potřebuju po zpracování editačního formuláře ještě zpracovat další formulář (třeba ořez náhledu):
function adminFormSucceeded($form, $values)
{
// zpracování formuláře...
$this->template->action = 'crop';
$this->redrawControl('form'); // zobrazení nový formulář (cropForm)
}
Přijde mi, že jsem tím vlastně simuluju metody actionXXX z presenteru,
ale v komponentě.
Existuje nějaký správný postup, jak toto řešit?
[Nette 2.4]
Editoval Odo (19. 4. 2020 18:35)