AppForm v Controle, handler v Presenteri inom ako parent

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

Pozdravujem vsetkych.

Prave riesim situaciu, kedy potrebujem mat formular ako napriklad login box, vyhladavanie na takmer kazdej stranke, preto som si vytvoril Control, ktory sa bude starat o renderovanie formularu, zobrazovanie, pripadne kesovanie vysledneho formularu.

Potrebujem ale nastavit AppForm v tomto Controle tak, aby bol formular po odoslani smerovany do Presenteru a casto krat ineho, ako je parent pre dany Control.

Potrebujem jednak nastavit konstruktor pre AppForm a jednak handler a jeho callback. Vie niekto poradit ako nato ?

Ondrej
Člen | 110
+
0
-

edke napsal(a):

Potrebujem ale nastavit AppForm v tomto Controle tak, aby bol formular po odoslani smerovany do Presenteru a casto krat ineho, ako je parent pre dany Control.

Potrebujem jednak nastavit konstruktor pre AppForm a jednak handler a jeho callback. Vie niekto poradit ako nato ?

To podle me nejde. Volani signalu (submit) controlu se dela nad stejnym presenterem.

Jod
Člen | 701
+
0
-

No tak si ku controlu pridaj metódu setSubmitCallback.

<?php
class Search extends Control
{
	protected $callback;
	protected $form;
	function setSubmitCallback($callback)
	{
		$this->callback = $callback;
	}

	...

	function createForm()
	{
		$form = new AppForm($this, 'form');
		$form->addSubmit('search', 'Seearch')
		$form->onSubmit[] = $this->callback;
		$this->form = $form;
	}
}
?>
<?php
class NejakyPresenter extends BasePresenter
{
	function actionIndex()
	{
		$search = new Search($this, 'search');
		$search->submitCallback = array($this, 'search_submitted');
	}

	function search_submitted(AppForm $form)
	{
		// submitnuté
	}
}
?>

Takto by to malo fungovať. Registrovať callback na iný než aktuálny presenter neviem. Ledaže by mal statickú metódu (array(DruhyPresenter, ‚search_submitted‘));

Možno by sa ešte niečo dalo cez perzistentné komponenty v BasePrezenteri.

Editoval Jod (12. 2. 2009 17:14)

kravčo
Člen | 721
+
0
-

edke napsal(a):

Potrebujem ale nastavit AppForm v tomto Controle tak, aby bol formular po odoslani smerovany do Presenteru a casto krat ineho, ako je parent pre dany Control.

Potrebujem jednak nastavit konstruktor pre AppForm a jednak handler a jeho callback. Vie niekto poradit ako nato ?

Dôležité je, čo sa myslí smerovaním do prezentera.

Vieme, že po každom odoslaní formulára by malo nasledovať presmerovanie… Logicky, ak má signál spracovať iný prezenter, ako ten, ktorý je aktuálny, potrebujeme inštanciu, ktorú asi nejakým jednoduchým spôsobom nezískame… Otázkou teda je, či je to spracovanie iným prezenterom naozaj nutné, v prípade, že áno, mohla by to vyriešiť statická metóda ako píše Jod…

Skús upresniť, prečo by požiadavku mal spracúvať iný prezenter…

edke
Člen | 198
+
0
-

kravco wrote:

Dôležité je, čo sa myslí smerovaním do prezentera.

Vieme, že po každom odoslaní formulára by malo nasledovať presmerovanie… Logicky, ak má signál spracovať iný prezenter, ako ten, ktorý je aktuálny, potrebujeme inštanciu, ktorú asi nejakým jednoduchým spôsobom nezískame… Otázkou teda je, či je to spracovanie iným prezenterom naozaj nutné, v prípade, že áno, mohla by to vyriešiť statická metóda ako píše Jod…

Skús upresniť, prečo by požiadavku mal spracúvať iný prezenter…

Situacia je nasledovna:

Defaultny presenter obsluhuje titulnu stranku, teda prehlad clankov a pod., dalej zobrazenie jedneho clanku atd.

Presenter ktory obsluhuje nieco ako user control panel sa vola User, v nom sa riesia vsetky ulohy, ktore navstevnik potrebuje, teda login, logout, registracia, sprava profilu atd.

Na kazdej stranke, ktoru zobrazim potrebujem zjednoduseny login form a napriklad search form ako ukazuje vo svojom priklade Jod. Ale po vyplneni a odoslani formulara som uz ostatne chcel riesit v Presenteri User, kedze napriklad pre zobrazovanie chybovych sprav (zadaj login, heslo, nespravny login, konto blokovane) nie je na titulke miesto. Preto po vyplneni formulara na login by malo nasledovat presmerovanie a spracovanie signalu v presenteri User, kde sa prihlasovanie vyhodnoti, alebo sa znovu zobrazi uz plna podoba login formularu aj s chybovymi hlaskami.

Nieco podobne je search form, tiez na titulnej stranke je len input na zadanie klucovyuch slov, po odoslani je potrebne presmerovat spracovanie signalu do Presenteru urceneho na vyhladavanie, kde sa znovu zobrazi input s nasimi zadanymi klucovymi slovami ale uz aj vysledkami vyhladavania.

edke
Člen | 198
+
0
-

Momentalne som nasiel riesenie, ktore ale mi pride ako velmi nesystemove a len som to obisiel:

1. v presenteri Guest mam kompletne funkcne prihlasovanie, teda formular a handler na jeho spracovanie:

final class FrontEnd_GuestPresenter extends FrontEnd_BasePresenter
{


	public function actionLogin()
	{

		$form = new AppForm($this, 'form');
		$form->renderer->clientScript = NULL;

		$form->addText('login', 'Prihlasovacie meno')
		->addRule(Form::FILLED, 'Zadajte prihlasovacie meno');

		$form->addPassword('password', 'Prihlasovacie heslo')
		->addRule(Form::FILLED, 'Zadajte prihlasovacie heslo');

		$form->addCheckbox('remember_me', 'Zapamätať si ma na tomto počítači.');

		$form->addSubmit('ok', 'Prihlásiť sa')
			->onClick[] = array( $this, 'Login_onSubmit');

		$this->template->form = $form;
		$this->template->title = "Log-in";
	}

	public function Login_onApply( SubmitButton $button)
	{
		try {

			$values= $button->getForm()->getValues();
			....

2. routa pre presenter Guest vyzera nasledovne:

$router[] = new Route('<view (register|login|forgot)>/<id>', array(
	'module' => 'FrontEnd',
	'presenter' => 'Guest',
	'id' => NULL,
));

3. komponenta LoginControl moze byt pridana do lub. presenteru a stara sa len o zobrazenie maleho prihlasovacieho formulara:

class LoginControl extends Control
{

	public function __construct(IComponentContainer $parent = NULL, $name = NULL)
	{
		parent::__construct($parent, $name);
	}

	public function render()
	{
		$form = new Form('loginform');
		$form->setAction('/login/?do=form-submit');
		$form->renderer->clientScript = NULL;

		$form->addText('login', 'Login')
			->setHtmlId('inputlogin');

		$form->addPassword('password', ' heslo')
			->setHtmlId('inputpassword');

		$form->addCheckbox('remember_me', 'Zapamätať si ma na tomto počítači.');

		$form->addImage('ok', $this->template->baseUri. 'gui/form-login-input-submit.gif', 'Prihlásiť sa');

		ob_start();
		$this->template->setFile(Environment::getVariable('templatesDir'). '/components/LoginControl.phtml');
		$this->template->registerFilter('CurlyBracketsFilter::invoke');
		$this->template->form= $form;
		$this->template->render();

		echo ob_get_clean();
	}

Vyhody

  • funguje to tak ako potrebujem

Nevyhody

  • nesystemove, nie je ziadna logicka vazba medzi strukturou formulara v Control a handlerom v presenteri Guest
  • definicia formulara na 2 miestach, ak bude potrebne formular upravovat, musim zmeny preniest aj do Control-u
  • ak zmenim v bootstrap-e routrovanie pre presenter Guest, musim rucne zmenit action pre form v Control-e

Teda ak niekto bude vediet poradit systemovejsie riesenie, budem vdacny a velmi rad aktualne spracovanie prerobim.

Jod
Člen | 701
+
0
-

Jednoduché riešenie pomocou BasePresenteru (neni predsa len na registráciu filtrov ,)

Ak myslíš nejaké také prihlasovanie ako je tu , tak to robím cez BasePresenter.
Môžeš si spraviť LoginControl ktorý vytvoríš v BasePresenteru a bude na každej stránke v layoute sa vykreslovať. Po odoslaní sa oblúži z metódy formSubmitted v BasePresenteru. Po nesprávnom prihlásení užívateľa môžeš presmerovať na GuestPresenter login ak ti to tam vyhovuje, alebo mu napísať nad formulárom chybu. A nakoniec v GuestPresenteri login buď zmeníš layout, alebo pridáš podmienku aby sa ti ten loginControl nerenderoval tam, ale si ho pridáš do šablony.

TeeBee87
Člen | 14
+
0
-

V komponentě vytvářím anketu (formulář)

public function __construct(/*Nette\*/IComponentContainer $parent = NULL, $name = NULL) {
	parent::__construct($parent, $name);
	$this->_setData();
}

private function _setData() {
	$form = new AppForm($this, 'poll');
	$form->onSubmit[] = array($this, 'processVote');

	if ($this->_voted == true) {
        	// get poll results
        	$poll = Poll::getInstance()->getPollByAnswerId($this->_answerId);
	} else {
		$poll = Poll::getInstance()->getPollByRand();
	}
	...

public function render() { ... }

public function processVote(AppForm $form) {
	$this->_voted = true;
	$this->_answerId = $form['answer_id']->getValue();
	...
}

Jde o to, že anketu vybírám náhodně a když se formulář odešle tak ho před zpracováním signálu musím znovu vytvořit – jenže dokud nezpracuju signál tak nevím, kterou anketu jsem měl vytvořenou …

Můžu si vzít id ankety (respektiwe odpovědi, ale to je jedno) z $_POSTu, ale.. jak by se tohle mělo řešit?

Jod
Člen | 701
+
0
-

Tak anketu plň dátami až po spracovaní signálu.
A na toto si mohol vytovirť novú tému.

TeeBee87
Člen | 14
+
0
-

Pardon. Jenže anketa je formulář a formulář musím vytvořit před zpracováním signálu.

Jod
Člen | 701
+
0
-

Facotry createComponent($name) si skúšal? Inofmáciu o tom aké je id ankety si môžeš uložiť napr. do session.