manevrovanie medzi action{Action} a render{view}

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

Mam {action}, kde kombinujem prehlad zaznamov tabulky a formular. Ako mi to doteraz vychadza:

  1. Formular musi byt v action{Action}, pretoze signal je spracovany po action{Action} a v tom momente ak neexistuje object AppForm, processSignal() nevie ako nalozit so spracovavanym signalom. Pravda ?
  2. Ak {action} potrebuje reagovat na signaly, musi byt umiestneny v render{view}. Ak by bol umiestneny v action{Action}, signal bude spracovany az po vygenerovani {view} a ten ak sa meni vdaka tomuto signalu, ta zmena sa prejavi az po dalsom kliku, co je hlupost samozrejme. Pravda ?

Tak a teraz spat k mojmu problemu. Pre lepsiu nazornost sshot. Strankovanie, sortovanie, to su vsetko {signaly}!. Buttony su SubmitButton vo formulari. Kazdy riadok ma checkbox, pre multiple operacie, ako napriklad mazanie viacerych zaznamov.

Ten problem spociva prave v tom, ze v tom {view} kombinujem formular, ktory by mal byt v action{Action} s dalsou castou, ktora by mala byt v render{view}. A nemozem to ani rozdelit, teda formular do action{Action} a zbytok do render{view}, pretoze checkboxy viem vygenerovat az ked mam spocitane strankovanie, spracovane {signaly}!, teda v render{view}. A ak ich k formularu pripojim az v render{view}, po odoslani formulara buttonom nie je v ->getValues() samozrejme.

Co vcul ?

edke
Člen | 198
+
0
-

edke wrote:

Co vcul ?

Dumal som a nasiel som 2 riesenia a ani jedno sa mi nepaci :)

1. riesenie

	protected $form;

	public function actionDefault() {

		$form = new AppForm($this, 'main_table');

		$form->addSubmit('add', 'Pridať záznam' )
			->onClick[] = array( $this, 'default_onAdd');

		$form->addSubmit('delete', 'Zmazať záznam' )
			->onClick[] = array( $this, 'default_onDelete');

		$this->form=$form;
	}


	public function renderDefault() {
		$form= $this->form;

		...

		foreach( $res as $row ) {
			$_loop= array();

			$control= $form->addCheckbox( $row['id'], null );
			$_loop[]= array( 'align' => 'center', 'content' => $control->control );

		...

Cast form mame v action aj so submitmi a zadefinovanymi signalmi. Cast tabulka mame v render, teda signaly! v <a href> na order a na zmenu strany budu fungovat tiez korektne.

Jediny problem je so submitmi add, delete:

	public function default_onEdit( SubmitButton $button )
	{
		$values= $button->getForm()->getValues();
		var_dump( $_POST );
		var_dump( $values );

Oznacene checkboxy vo $values samozrejme nebudu, pretoze neboli definovane v action, ale az v render. Ale obidem to tak, ze si ich vyberiem priamo z $_POST.

Samozrejme riesenie je „prasarna“, zrusil som velku vyhodu Nette\Forms a to ze nespracuje ziadne hodnoty, pokial neboli predtym definovane v aplikacii. Podstrcenie hodnot musim osetrit sam. Ale hlavne to je nesystemove riesenie.

2. riesenie

Vsetko, aj tabulku aj formular presuniem do actionDefault. Submitovanie z formulara je uplne v poriadku, cely objekt AppForm je definovany v action. Problem je so signalmi! order a page. Tie uz nebudu fungovat. Tak ich prerobim na view:

	public function actionPage( $page )
	{
		$page= (int) $page;

		if ( !( $page > 0) ) {
			throw new Exception('page is not valid');
		}

		$namespace= Environment::getSession($this->tableName);
		$namespace->page= $page;

		$this->redirect( 'default');
	}

Co sa mi zas na tomto rieseni nepaci je, ze pouzivam view ako handler, musim pouzit redirect, takze kvoli „signalu“ musim aplikaciu volat 2×.

edke
Člen | 198
+
0
-

3. riesenie

Persistentne premenne pre page a order ale to sa mi uz vobec nepaci. Persistentne premenne platia pre cely presenter tak ? Tieto premenne su ale potrebne len pre view default a tych views tam bude viac.

LM
Člen | 206
+
0
-

Pokud ty view nebudou používat stejný parametry, pak nevidím důvod, proč je mít v jednom presenteru. Nebo bych zvážil z toho udělat komponentu…

Editoval LM (15. 10. 2008 12:31)

romansklenar
Člen | 655
+
0
-

LM napsal(a):

Pokud ty view nebudou používat stejný parametry, pak nevidím důvod, proč je mít v jednom presenteru. Nebo bych zvážil z toho udělat komponentu…

Možná pomůže: Návrh struktury presenters/views

edke
Člen | 198
+
0
-

romansklenar wrote:

Možná pomůže: Návrh struktury presenters/views

Toto mam precitane, myslim, ze ta struktura je navrhnuta dobre. Jeden presenter je sprava jednej tabulky.

  1. view default – zobrazuje tabulku zaznamov a umoznuje :
    • sortovanie zaznamov
    • strankovanie zaznamov
    • nastavovanie filtrov
    • zmena view na formular
  2. view form – zobrazuje formular, ktory umoznuje pridavat/updavovat/editovat zaznamy.

Zaujimal by ma Davidov nazor, ci by vedel poradit nejake cistejsie systemove riesenie.

LM
Člen | 206
+
0
-

No pak v tom nevidím problém, má to jen výhodu, pokud začne uživatel editovat záznamy může tam být odkaz zpět který ho vrátí na stejnou stránku, stejné číslo stránky a řazení záznamů.

David Grudl
Nette Core | 8142
+
0
-

Ty potřebuješ, aby pořadí úkolů bylo:

  1. inicializace presenteru (včetně např. připojení k db, …)
  2. provedení signálů „Strankovanie, sortovanie“
  3. vytvoření formuláře
  4. provedení signálů pro formulář
  5. vykreslení stránky

To je zcela legitimní požadavek. Takže jak na to…

Životní cyklus presenteru je rozdělen do několika částí představovaných voláním volitelně existujících metod. Jde o action{Action}, handle{Signal} a render{View}.

Platí tu určitá pravidla: v okamžiku volání render{view} už nemá docházet k žádným změnám parametrů, „vnitřní stav“ je konečný. Protipólem je action{action}, kde je prostor pro manipulaci s modelem s možností následného přesměrování.

Tudíž v kterékoliv fázi předcházející handle{signal} můžeme vykonat signál manuálně zavoláním metody $this->processSignal(). Příklad:

if ($this->isSignalReceiver($this, 'strankovanie') || $this->isSignalReceiver($this, 'sortovanie')) {
	$this->processSignal();
}

Tím je signál provedený a už se nebude znovu volat.

Metoda isSignalReceiver() ověří, zda je komponenta (první argument) příjemcem signálu (druhý argument). Druhý argument můžeme vynechat – pak zjišťuje, jestli je komponenta příjemcem jakéhokoliv signálu. Experimentálně lze jako druhý parametr uvést TRUE a tím ověřit, jestli je příjemcem nejen uvedená komponenta, ale také kterýkoliv její potomek.

ps: zjednodušil jsem ověřování příjemce, takže isSignalReceiver vyžaduje poslední revizi Nette