Kombinace normální HTML formulář + zpracování AppFormem

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

Mám klasický HTML formulář v @layoutu, který potřebuju submitovat a validovat v viewu Uzivatel:prihlaseni AppFormem. Jde to?

AppForm jsem na vykreslení formuláře používat nechtěl… Potřebuji akorát zpracování formuláře.

Kód formuláře:

<h3>Přihlášení</h3>
<form action="{plink Uzivatel:prihlaseni}" method="post" id="login-form">
<fieldset>
<input type="text" class="username text" value="e-mail" name="username" title="Váš e-mail" onclick="if(this.value=='e-mail')this.value='';" onblur="if(this.value=='')this.value='e-mail';" />
<input type="password" class="password text" value="heslo" name="password" title="Vaše heslo" onclick="if(this.value=='heslo')this.value='';" onblur="if(this.value=='')this.value='heslo';" />
<input type="submit" name="submit" value="Přihlásit" class="autowidth button1 submitlogin" />
<div class="loginoptions">
<a href="{plink Uzivatel:zapomenute}">zapomenuté heslo</a> | <a href="{plink Uzivatel:registrace}">registrovat</a>
</div>
</fieldset>
</form>

Předem díky.

Editoval gmvasek (7. 4. 2009 19:46)

romansklenar
Člen | 655
+
0
-

Nějak mě nenapadá, jak toho dosáhnout (pro klasické formulářové handlery tak i tak předáváš instanci formuláře, se kterým pracuješ, takže abys využil těch featurek musíš komponentu stejně někde vytvořit a udělat to tak aby se na ni zaslal signál) … jedině si ve startup toho presenteru takový požadavek odchytit a předat ho na zpracování bez featurek AppFormu ale přes $_POST nebo si to vytáhnout z Environment::getHttpRequest()->getPost() (tuším že)… ale i tak – přijde mi jednoduchší ten formulář přepsat do AppForm… je nějaký rozumný důvod proč vymýšlet takový cross-over?

Honza Marek
Člen | 1664
+
0
-

Proč nepoužiješ ten AppForm?

Html atributy se nastaví takto:

$form["prvek"]->getControlPrototype()->class("trida trida2 trida3")->onclick("....");

A v šabloně nemusíš vykreslovat celý formulář, ale můžeš vykreslit jen

{? $form->render("start") }
{!$form["prvek"]->label} {!$form["prvek"]->control}
{? $form->render("end") }

Nejsem si jist, jak moc přesně si to všechno pamatuju.. Mrkni kdyžtak do dokumentace.

Aurielle
Člen | 1281
+
0
-

Přepsal jsem to teda do AppFormu, ale mám 2 dotazy:

  1. Jak dát inputu (text) výchozí hodnotu? Před getControlPrototype to nefunguje (mimochodem v API o tom není ani zmínka)
  2. Jak formulář nasměrovat na view Uzivatel:prihlaseni?
R2D2
Člen | 22
+
0
-

gmvasek napsal(a):

Přepsal jsem to teda do AppFormu, ale mám 2 dotazy:

  1. Jak dát inputu (text) výchozí hodnotu? Před getControlPrototype to nefunguje (mimochodem v API o tom není ani zmínka)
  2. Jak formulář nasměrovat na view Uzivatel:prihlaseni?
  1. z dokumentace
<?php
    $form->addText('email', 'Email:', 35)
        ->setEmptyValue('@');
?>
  1. formulář přímo nesměruj, dáš si v tom presenteru který má nadefinovaný formulář taky funkci pro jeho vyhodnocení, přiřadíš ji na odeslání takto:
<?php
$form->onSubmit[] = array($this, 'jmenoFunkceNaZpracovani');
?>

a funkce (definovaná ve stejném presenteru jako formulář) vypadá zhruba takto:

<?php
public function jmenoFunkceNaZpracovani(AppForm $form)
{
    $data = $form->getValues();
// zpracuj data

// tady doporucuji jeste pridat neco jako $this->flashMessage('Prihlaseni se povedlo');, pokud mas zobrazovani techto zprav, da se to udelat docela pekne a jednoduse

$this->redirect('Uzivatel:prihlaseni', $pripadneParametry);
}
?>

Redirect je dobré mít za každým odeslaným formulářem, aby fungovalo refreshování stránky, tlačítko zpět a tak :)

Editoval R2D2 (7. 4. 2009 21:23)

Aurielle
Člen | 1281
+
0
-

Dá se ta fce upravit takto? Nechtěl bych mít přihlašování v BasePresenteru…

<?php
public function jmenoFunkceNaZpracovani(AppForm $form)
{
    $data = $form->getValues();
// zpracuj data

$this->redirect('Uzivatel:prihlaseni', $data['username'], $data['password']);
}
?>
R2D2
Člen | 22
+
0
-

to není vhodné, protože se pak heslo napíše do url adresy, redirect skutečně přesměrovává, ale mělo by takhle jít použít forward:

<?php
public function jmenoFunkceNaZpracovani(AppForm $form)
{
    $data = $form->getValues();
    $this->forward('Uzivatel:prihlaseni', $data);
    // je možné dát jako parametr pole, ono se rozhodí do potřebných parametrů samo
}
?>
kravčo
Člen | 721
+
0
-

Funkcia, ktorá spracúva prihlásenie nemusí byť v prezenteri. Pri nastavení handlera onSubmit resp. ešte lepšie onClick (dokumentácia) môžeš použiť ľubovoľný callback, napríklad:

$form->addSumit('login', 'Log in')
    ->onClick[] = 'AuthModel::handleLogin';

// alebo cez inštanciu...

$form->addSumit('login', 'Log in')
    ->onClick[] = array($this->model, 'handleUserLogin');

Záleží na tom, ako máš spravený model, alebo to, čo spracúva prihlásenie…

Aurielle
Člen | 1281
+
0
-

Trochu jsem se posunul, teď mi BasePresenter::renderDefault vypadá takto (renderDefault volá každý zděděný view):

<?php
	public function renderDefault()
	{
		// Login
		$form = new AppForm($this, 'login');
		$form->addText('username', 'Váš e-mail')
			->setEmptyValue('e-mail');
		$form->addPassword('password', 'Vaše heslo')
			->setEmptyValue('heslo');
		$form->addSubmit('loginsubmit', 'Přihlásit')
			->setValidationScope(false);
		$form->addProtection();
		$form->onSubmit[] = array($this, 'handleLogin');

		$form['username']->getControlPrototype()->class('username text')->onclick("if(this.value=='e-mail')this.value='';")->onblur("if(this.value=='')this.value='e-mail';");
		$form['password']->getControlPrototype()->class('password text')->onclick("if(this.value=='heslo')this.value='';")->onblur("if(this.value=='')this.value='heslo';");
		$form['loginsubmit']->getControlPrototype()->class('autowidth button1 submitlogin');

		$this->template->form = $form;

		/* Dalsi promenne do sablony */
	}

	public function handleLogin(AppForm $form)
	{
		Debug::dump($form->getValues());
	}
?>

Proč se formulář neodešle, když má prázdný konstruktor? Když doplním do konstruktoru $this a jméno formuláře tak mi Laděnka zahlásí „The signal receiver component ‚login‘ is not found.“

Jod
Člen | 701
+
0
-

Miesto renderDefault použi actionDefault. Komponenta musí byť vytvorená ešte pred spracovaním signálu, alebo použi továreň na componenty createComponent..

Editoval Jod (8. 4. 2009 18:18)

kravčo
Člen | 721
+
0
-

Pretože podľa životného cyklu prezenteru, v čase spracovania signálov ten formulár neexistuje – vytvorí sa až vo fáze renderovania. Použi na jeho vytvorenie továrničku, alebo formulár vytváraj v metóde prepareDefault().

Aurielle
Člen | 1281
+
0
-

Když to dám do prepareDefault tak bych to logicky musel volat v každém zděděném viewu… nejde to vyřešit nějak elegatněji? (Ještě zkusím ty továrničky.)

Edit: továrničky fungují, díky :)

Editoval gmvasek (8. 4. 2009 20:47)

kravčo
Člen | 721
+
0
-

gmvasek napsal(a):

… (renderDefault volá každý zděděný view)

Tomuto som celkom nerozumel – dovysvetlíš?

Když to dám do prepareDefault tak bych to logicky musel volat v každém zděděném viewu…

Tomuto tiež nerozumiem – detto?

Nejde to vyřešit nějak elegatněji?

Továrnička.

Ještě zkusím ty továrničky.

Skús :)