Presmerovani z komponenty (reload)

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

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);
   	}
Šaman
Člen | 2666
+
0
-

Spíš napiš, jak zpracováváš formulář. Volání $this->presenter->redirect(); by fungovat mělo (i když není akademicky čisté).

dawe
Člen | 59
+
0
-

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

Oli
Člen | 1215
+
0
-

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');
Pavel Macháň
Člen | 282
+
+1
-

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
+
0
-

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
+
0
-

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
+
+1
-

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
+
0
-

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)

Šaman
Člen | 2666
+
+1
-

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.

dawe
Člen | 59
+
0
-

zmenil jsem, ale ted nevim jeste s cestou
Component with name ‚dateSelector‘ does not exist. nechapu proc ji to nemuze najit :/

dawe
Člen | 59
+
0
-

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
+
0
-

Š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)

dawe
Člen | 59
+
0
-

upravil jsem tedy interface, ale porad mi to vraci to stejne :/

<?php
interface IDateSelectorFactory {

    /** @return \DateSelector */
    public function create($datesRepository, $session);

}
?>
Pavel Macháň
Člen | 282
+
+1
-

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)

dawe
Člen | 59
+
0
-

Uff tak uz mi to funguje, ja jsem mel spatne nazev v sablone u komponenty. Clovek by nemel pracovat moc unavenej… Jinak diky moc, alespon jsem se priucil jak zachazet s komponentama, ted uz mi to vse funguje dle tveho reseni.