Naplnění persistentního parametru komponenty ze session a generování odkazu
- jEhLa
- Člen | 70
Dobrý den,
řeším komponentu na přehled položek, u které je i filtr vyhledávání.
Pomocí persistentních parametrů komponenty přenáším pole filtrovaných
hodnot. Chtěl bych ale umožnit i to, že po opuštění stránky s touto
komponentou, se při návratu na ní, zobrazí poslední nastavený výběr.
Vyřešil jsem to tím, že si pole filtrovaných hodnot ukládám i do
session, pokud se ke komponentě vrátím a má prázdný persistentní
parametr, načtu jej ze session.
To funguje v pořádku.
Problém je v tom, že komponenta je „ajaxová“ a mám zde tedy tlačítko (odkaz) které generuje pouze url na aktuální stránku (aby se mohl odkaz výběru někomu třeba přeposlat). Tlačítko je v šabloně komponenty datagridu.
<a href="{link this}">Aktuální výběr</a>
Jenže při tomto prvním požadavku, kdy je persistentní parametr prázdný a naplním jej tedy obsahem ze session (toto provádím v attached metodě komponenty), se odkaz tlačítka vygeneruje bez persistentních parametrů.
Napadlo mě že k tomu by se dala použít metoda saveState(), ale to se mi nepodařilo nijak rozchodit.
Zjednodušená ukázka kódu.
<?php
class ItemsList extends \Nette\Application\UI\Control
{
/** @persistent */
public $filter = [];
protected function createComponentItemsDatagrid()
{
//...
}
protected function createComponentFilters()
{
//...
}
public function handleFilter( $name, $value )
{
$this->filter[$name] = $value;
//testovací přístup k session
$this->getPresenter()->getSession('test')->filter = $this->filter;
if($this->getPresenter()->isAjax()){
$this->redrawControl('wrapper');
}
else {
$this->redirect('this');
}
}
protected function attached( $presenter )
{
parent::attached($presenter);
if ($presenter instanceof \Nette\Application\UI\Presenter) {
if(isset($presenter->getSession('test')->filter)){
$this->filter = $presenter->getSession('test')->filter;
//tady by asi mělo něco být
}
}
}
}
?>
Za každé nakopnutí děkuji.
Editoval jEhLa (5. 9. 2016 14:31)
- artemevsin
- Člen | 61
tohle chování mi přijde trošku zbytečné – nebylo by jednodušší mít na stránce nějaký box typu Poslední hledání, kde se bude vypisovat posledních 5 vyhledávání? Přece jen když znovu otevřu nějakou stránku,tak neočekávám, že mi tam zůstane aktivní filtr, je to až trošku matoucí, uživatel si toho ani nemusí totiž všimnout…
- artemevsin
- Člen | 61
tak zkus se podívat spíše na metodu loadState()
. Metoda nastavuje persistentní parametry presentrů. saveState() dělá
opak – naplní pole hodnotami persistentních parametrů.
Zdrojak toho řekne víc :)
- jEhLa
- Člen | 70
Ani s loadState() se mi to nepodařilo rozchodit. Stále stejné
chování.
Funguje to pouze pokud tu proměnnou $filter, naplním ze session přímo
v presenteru. Pak to funguje. Pokud se o to snažím v komponentě, tak se
persistentní parametry negenerují.
Takhle to funguje, ale musím to dělat z presenteru :-/
<?php
class ItemsList extends \Nette\Application\UI\Control
{
/** @persistent */
public $filter = [];
public $onFilter;
//...
public function handleFilter( $name, $value )
{
//...
$this->onFilter( $this->filter );
//...
}
}
class DefaultPresenter extends BasePresenter
{
public function renderDefault()
{
$control = $this['itemsList'];
if(!count($control->filter) and isset($this->getSession('test')->filter)){
$control->filter = $this->getSession('test')->filter;
}
}
protected function createComponentItemsList()
{
$control = new ItemsList($this->model);
$control->onFilter[] = function($filter){
$this->getSession('test')->filter = $filter;
};
return $control;
}
}
?>
Editoval jEhLa (7. 9. 2016 19:24)
- artemevsin
- Člen | 61
ale vždyť to můžeš přesunout do komponenty:
<?php
class ItemsList extends \Nette\Application\UI\Control
{
/** @persistent */
public $filter = [];
public $onFilter;
//...
public function __construct(Session $session)
{
$this->session = $session->getSection('itemsListFilter');
if(!$this->filter && $this->session->filter){
$this->filter = $this->session->filter;
}
}
public function handleFilter( $name, $value )
{
//...
$this->session->filter = $this->filter;
//...
}
}
?>
Přinejmenším to má výhodu v tom, že v komponentě přiznáváš závislost na session. Pak už stačí jen vytvořit továrničku, která se o ty závislosti postará.
<?php
interface IItemsListFactory {
/**
* @param \Nette\Http\Session $session
* @return ItemsList
*/
public function create(\Nette\Http\Session $session);
}
?>
Zaregistrovat továrničku jako službu a do presenteru injectnout továrničku. Takže v presenteru pak budeš mít:
<?php
class DefaultPresenter extends BasePresenter
{
public function renderDefault()
{
}
protected function createComponentItemsList()
{
$control = $this->itemsListFactory->create();
return $control;
}
}
?>
- jEhLa
- Člen | 70
Děkuji za odpovědi.
Takhle jsem to chtěl původně řešit, předat jen závislost na
session.
Ale zapomněl jsem podotknout, že tato komponenta bude použita na více
místech, a nechci aby měli tu session stejnou (sdílenou) chtěl jsem si
nastavit sessionSection až podle názvu komponenty a toho kde bude vytvořená.
A to mohu provést až po attached, a né v constructoru. :-/
Ale můžu komponentě předat sessionSection z presenteru generovanou jen podle názvu presenteru a aktuální action. To by mělo stačit.
Stejně mi ale vrtá hlavou proč to nejde udělat právě až v metodě attached :-/
Editoval jEhLa (8. 9. 2016 17:38)
- CZechBoY
- Člen | 3608
@jEhLa Moc dobře nechápu co teď řešíš… předáš si
Session
a z ní si vytáhneš SessionSection
jakou
potřebuješ.
public function __construct(Session $session)
{
$this->session = $session;
}
public function attached($component)
{
parent::attached($component);
$this->sessionSection = $this->sesion->getSection($this->getUniqueId());
}
protected function createComponentForm()
{
$form = ...;
$form->setValues($this->sessionSection['values']);
return $form;
}
- jEhLa
- Člen | 70
@CZechBoY Ano, tohle funguje u formuláře.
Ale řeším to, že pokud v metodě attached, když už vím jakou
sessionSection použít. Vytáhnu si zni data, nastavím je do persistentního
parametru, tak když chci vygenerovat odkaz na aktuální stránku {link this},
tak se vygeneruje odkaz jako by byl tento persistentní parametr prázdný.
I když si ten persistentní parametr potom dumpnu, tak prázdný není, ale
vygenerovaný odkaz jej neobsahuje.
Editoval jEhLa (17. 9. 2016 15:31)