Presmerovani z komponenty (reload)
- dawe
- Člen | 59
Ahoj,
prosim jak muzu v komponente obnovit stranku? Jde mi o to, ze v ni mam
formular a ten po ulozeni nastavi session.
Tuto komponentu nacita BasePresenter (protoze se vyuziva ve vice presenterech). Takze treba v HomepagePresenter (extends BasePresenter) mam tu komponentu vykreslenou. Potrebuji po vyberu polozky odeslat formular, nastavit session dle vysledku a vykreslit aktualni data dle session.
$form->onSuccess[] se mi vola pozdeji nez vykresleni obsahu stranky, takze se mi vykresli jeste stara data.
nepodarilo se mi zadnym zpusobem obnovit stranku, jak na to?
zkousel jsem $this->getPresenter()->redirect(„this“), ale to mi to
nebere.
komponentu vytvarim v BasePresenteru takto:
protected function createComponentDateSelector(){
return new \DateSelectorBlock($this->dateRepository, $this->session);
}
- dawe
- Člen | 59
Zpracovani formulare mam v te komponente. Vyresil jsem to pomoci header, nevim zda je to tak idealni reseni?
public function selectDateFormSucceeded(Form $form) {
$values = $form->getValues();
if($values->date== "live"){
unset($this->sessionSection->date);
unset($this->sessionSection->dateId);
} else{
$this->sessionSection->date= "date";
$this->sessionSection->dateId = $values->date;
}
header("Location: http://".$_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"]);
die();
}
Mam nekolik presenteru, jako treba HomePresenter, NewsPresenter, atd…
Vsechny rozsiruji BasePresenter. V BasePresenteru mam ve funkci
startup()
metodu:
$this->addComponent(new \DateSelectorBlock($this->dateRepository, $this->session), 'dateSelector');
Tuto komponentu nasledne vykresluju v @layout.latte
- Pavel Macháň
- Člen | 282
dawe napsal(a):
Zpracovani formulare mam v te komponente. Vyresil jsem to pomoci header, nevim zda je to tak idealni reseni?
public function selectDateFormSucceeded(Form $form) { $values = $form->getValues(); if($values->date== "live"){ unset($this->sessionSection->date); unset($this->sessionSection->dateId); } else{ $this->sessionSection->date= "date"; $this->sessionSection->dateId = $values->date; } header("Location: http://".$_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"]); die(); }
Mam nekolik presenteru, jako treba HomePresenter, NewsPresenter, atd… Vsechny rozsiruji BasePresenter. V BasePresenteru mam ve funkci
startup()
metodu:$this->addComponent(new \DateSelectorBlock($this->dateRepository, $this->session), 'dateSelector');
Tuto komponentu nasledne vykresluju v
@layout.latte
@dawe Na addComponent se vyprdni a udelej to klasicky továrničkou.
abstract class BasePresenter extends extends \Nette\Application\UI\Presenter {
/** @var \IDateSelectorBlockFactory @inject */
public $dateSelectorBlockFactory;
/** @return \DateSelectorBlock */
public function createComponentDateSelector() {
return $this->dateSelectorBlockFactory->create();
}
}
interface IDateSelectorBlockFactory {
/** @return \DateSelectorBlock */
public function create();
}
services:
- IDateSelectorBlockFactory
Je to určitě více ukecané, ale nemusíš řešit vytváření instance a je to čistější a hlavně přehlednější.
Oli napsal(a):
Přes header bych to určitě nedělal. Udělal bych to jak píše @Šaman, jen nevím proč to není akademicky čisté. Respektive jak by to mělo být čisté? Já to takhle používám všude. např.
$this->presenter->redirect('Articles:default');
@Oli Čisté to není z důvodu volání presenteru. Komponenta by o presenteru neměla „vědět“. Jestli to má třeba formulář tak ten má event onSuccess, který můžes dokončit v presenteru. Nebo si vytvořit vlastní event viz Nette\Object
class BasePresenter extends extends \Nette\Application\UI\Presenter {
/** @var \IDateSelectorBlockFactory @inject */
public $dateSelectorBlockFactory;
/** @return \DateSelectorBlock */
public function createComponentDateSelector() {
$form = $this->dateSelectorBlockFactory->create();
$form->onSuccess[] = function() {
$this->redirect('Articles:default');
};
return $form;
}
}
Pokud komponenta potřebuje překreslovat snippety pro ajax tak nezjišťovat pomocí,
if($this->getPresenter()->isAjax()) { .... }
ale injectnout si do komponenty Nette\Http\Request a tím se zase zbavíme presenteru.
class MyComponent extends \Nette\Application\UI\Control {
/** @var \Nette\Http\Request */
private $request;
public function __construct(\Nette\Http\Request $request) {
$this->request = $request
}
public function handleSomething() {
if($this->request->isAjax()) {
$this->redrawControl();
} else {
$this->redirect('this');
}
}
}
Každopádně není problém volání presenteru používat, jen to není „košér“ :)
Editoval Pavel Macháň (24. 9. 2014 11:03)
- dawe
- Člen | 59
A jak tedy zprovoznit ten redirect? $this->presenter->redirect(); toto mi neobnovi stranku a hodi to chybu, ze neni zadny parametr. Ja ale nevim jaky parametr bych mel predat. Nevim kam chci odkazovat, protoze nevim v jakem presenteru se zrovna nachazim, jelikoz je to ve tride BasePresenter, ktera je dedena
- dawe
- Člen | 59
Mohl bys mi prosimte rict, kam bych mel dat ten interface a jak predam ty dva parametry co tam mam? Ty parametry si do ty BasePresenter injectuju, inject v komponente mi nefungoval, nevim proc. Takze, kdyby to slo nejak jinak, tak by to bylo jeste lepsi. Diky
Pavel Macháň napsal(a):
@dawe Na addComponent se vyprdni a udelej to klasicky továrničkou.abstract class BasePresenter extends extends \Nette\Application\UI\Presenter { /** @var \IDateSelectorBlockFactory @inject */ private $dateSelectorBlockFactory; /** @return \DateSelectorBlock */ public function createComponentDateSelector() { return $this->dateSelectorBlockFactory->create(); } } interface IDateSelectorBlockFactory { /** @return \DateSelectorBlock */ public function create(); }
services: - IDateSelectorBlockFactory
Je to určitě více ukecané, ale nemusíš řešit vytváření instance a je to čistější a hlavně přehlednější.
Editoval dawe (23. 9. 2014 13:59)
- Pavel Macháň
- Člen | 282
dawe napsal(a):
A jak tedy zprovoznit ten redirect? $this->presenter->redirect(); toto mi neobnovi stranku a hodi to chybu, ze neni zadny parametr. Ja ale nevim jaky parametr bych mel predat. Nevim kam chci odkazovat, protoze nevim v jakem presenteru se zrovna nachazim, jelikoz je to ve tride BasePresenter, ktera je dedena
@dawe Pokud chceš pokaždé směrovat na presenter ve ktrém ta komponenta momentálně je puštěná tak použij ‚this‘.
$this->redirect('this');
To provede refresh místa kde momentálně aplikace je.
dawe napsal(a):
Mohl bys mi prosimte rict, kam bych mel dat ten interface a jak predam ty dva parametry co tam mam? Ty parametry si do ty BasePresenter injectuju, inject v komponente mi nefungoval, nevim proc. Takze, kdyby to slo nejak jinak, tak by to bylo jeste lepsi. Diky
Ja si interface udržuju u té komponenty něco ve stylu:
- App
|- Library
|- Components
|- MyComponent
|- templates
| |- default.latte
| |- something.latte
|- MyComponent.php
|- IMyComponentFactory.php
Služby ti do konstruktoru automaticky injectne Nette pokud je továrnička uvedena v konfiguraci jak sem ti tam ukázal.
Editoval Pavel Macháň (23. 9. 2014 15:18)
- dawe
- Člen | 59
Tak tak uz to funguje diky, plus jsem si upravil strukturu te komponenty a jeji volani :)
edit: tak po smazani cache, mi to nejde, hazi mi to chybu na:
Call to a member function create() on a non-object
/** @var \IDateSelectorFactory @inject */
33: private $dateSelectorFactory;
34:
35: /** @return \DateSelector */
36: public function createComponentDateSelector() {
37: return $this->dateSelectorFactory->create();
nemel byt ten interface spis jako trida, ktera to zpracovava?
Editoval dawe (23. 9. 2014 21:56)
- dawe
- Člen | 59
Stale na to nemuzu prijit, asi tam budu mit nejakou blbost nebo nevim.
config.neon
services:
- IDateSelectorFactory`
app/AdminModule/presenters/BasePresenter.php
/** @var \IDateSelectorFactory @inject */
public $dateSelectorFactory;
/** @return \DateSelector */
public function createComponentDateSelector() {
return $this->dateSelectorFactory->create($this->datesRepository, $this->session);
}
App/Library/Components/DateSelector/IDateSelectorFactory.php
<?php
interface IDateSelectorFactory {
/** @return \DateSelector */
public function create();
}
?>
App/Library/Components/DateSelector/DateSelector.php
public function __construct(\DatesRepository $datesRepository, \Nette\Http\Session $session)
{
parent::__construct();
$this->datesRepository = $datesRepository;
$this->session = $session;
}
App/AdminModule/templates/@layout.latte
{control dateSelector}
Editoval dawe (24. 9. 2014 9:06)
- Pavel Macháň
- Člen | 282
Šaman napsal(a):
Jestli nepouživáš nějaké Kdyby vychytávky, ale jen standardní Nette, tak anotace @inject umí injectovat jen do public proměnných. Tj, změň viditelnost na řádku 33 z private na public.
@Šaman Jej moje chyba. Já ten @inject moc nepoužívám, tak sem zase zapoměl, že to musí být public :)
dawe napsal(a):
Stale na to nemuzu prijit, asi tam budu mit nejakou blbost nebo nevim.
/** @return \DateSelector */ public function createComponentDateSelector() { return $this->dateSelectorFactory->create($this->datesRepository, $this->session); }
App/Library/Components/DateSelector/IDateSelectorFactory.php
<?php interface IDateSelectorFactory { /** @return \DateSelector */ public function create(); } ?>
@dawe Podívej se co má za parametry metoda create() a co do ní vkládáš ty.
/** @return \DateSelector */
public function createComponentDateSelector() {
return $this->dateSelectorFactory->create();
}
Editoval Pavel Macháň (24. 9. 2014 11:02)
- Pavel Macháň
- Člen | 282
dawe napsal(a):
upravil jsem tedy interface, ale porad mi to vraci to stejne :/
<?php interface IDateSelectorFactory { /** @return \DateSelector */ public function create($datesRepository, $session); } ?>
@dawe Ale nééé… normálně nech public function create();, služby si injectuješ pomocí konstruktoru. Nette ti to do konstruktoru doplní samo. Parametry v create se využívají pouze pokud tam chceš dodat něco jiného jak službu (třeba nějaký typ, který řekne komponentě jakou šablonu má použít).
interface IDateSelectorFactory {
/** @return \DateSelector */
public function create();
}
V presenteru to budeš mít také bez parametrů viz
/** @return \DateSelector */
public function createComponentDateSelector() {
return $this->dateSelectorFactory->create();
}
A tvoje komponenta bude mít konstuktor:
use Nette\Http\Session;
class DateSelector {
/** @var \DateRepository */
private $rDate;
/** @var Session */
private $session;
public function __construct(\DateRepository $rDate, Session $session) {
$this->rDate = $rDate;
$this->session = $session;
}
}
Editoval Pavel Macháň (25. 9. 2014 11:42)