jednodussi formsy

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

Ahoj, zacinam s Nette a trochu jsem se zastavil nad formsy (doufam, ze jako zacatecnik nerejpu).
Uplne se mi nelibi ty if-bloky, ktere je potreba vytvaret, kdyz se zpracovava form ve stejne metode, zajimalo by me, jestli by se neujal o neco jednodussi PEAR/Html_QuickForm pristup.

Soucasny stav ( zdroj z: http://zdrojak.root.cz/…roduktivitu/ )

if ($form->isSubmitted()) {
	// a jestliže jsou všechny položky vyplněny správně
	if ($form->isValid()) {
		echo '<h1>Formulář byl odeslán</h1>';
		$values = $form->getValues();
		Debug::dump($values);
		exit;
	}
} else { // a jestliže nebyl odeslán, nastavíme výchozí hodnoty
	$form->setDefaults(
		array( 'promo' => TRUE)
	);
}

PEAR/Html_QuickForm pristup

		$form = new Html_QuickForm();
		$form->setDefaults($oDataObject->toArray());
		$form->addElement('text', 'name', 'Jmeno:', array('maxlength' => 255));
		# ...
		$form->addRule('title', 'chybí nadpis', 'required');
		# ...

		if ($form->validate()) {
			$submitValues = $form->getSubmitValues();
			# ...
			# napr. ulozim do db

			# redirectuju
		}
		# jinak se form zobrazi

V Pearu proste validate() vrati true jenom pokud byly data odeslany a zaroven jsou validni. To je myslim to, co chceme v 90% osetrovat. setDefaults() je mozne nastavit kdykoliv po zalozeni formu.

Ondřej Mirtes
Člen | 1536
+
0
-

setDefaults() se na submitovaný formulář už taky neaplikují.

PetrP
Člen | 587
+
0
-

Form::setDefaults se nastavuje jen když není odesláno (viz api) je možné ho nastavovat kdykoliv.

A podle api Form::isValid() se může použít jen když bylo zavoláno setDefaults nebo isSubmitted. Hádam že by tedy mělo být v pořádku toto:

$form->setDefaults(
        array( 'promo' => TRUE)
);
if ($form->isValid()) {
        echo '<h1>Formulář byl odeslán</h1>';
        $values = $form->getValues();
        Debug::dump($values);
        exit;
}
//EDIT když na to ale koukám dál, tak to v pořádku není ;] musi se použít isSubmitted

Editoval PetrP (19. 5. 2009 22:23)

_Martin_
Generous Backer | 679
+
0
-

V tom článku to není zmíněné, ale kód lze zapsat i pomocí obsluh událostí stisknutí tlačítka. Taková obsluha se zavolá pouze, pokud je formulář odeslán a je validní. Více v Best practise: obsluha formulářů, v sekci S obsluhou událostí. A protože v nových revizích frameworku už jde setDefaults volat přímo, kód bude ještě jednodušší.

PetrP napsal(a):

//EDIT když na to ale koukám dál, tak to v pořádku není ;] musi se použít isSubmitted

Jakto? setDefaults přeci metodu isSubmitted volá.

vlna
Člen | 34
+
0
-

Diky za odpovedi / rady.
Ja bych prave radeji vyuzival ten styl udelat vsechno v jedne metode. Prijde mi to vic soudrzny a rozhrani te tridy mi pak prijde prehlednejsi, ale to je ciste nazor. Pokud problem resi setDefaults(), snad jsme spokojeni vsichni.

PetrP
Člen | 587
+
0
-

_Martin_ napsal(a):

Jakto? setDefaults přeci metodu isSubmitted volá.

// V Form::validate()
596:         if (!$this->isPopulated) {
597:             throw new InvalidStateException('Form was not populated yet. Call method isSubmitted() or setDefaults().');
598:         }

// Cesta k nastavení isPopulated je nássledující
Form::isSubmitted()
Form::processHttpRequest() // když není odesláno tak se tady zastaví
Form::loadHttpData()
480:         $this->isPopulated = TRUE;

// takže i když je isSubmited zavolaný tak se nenastaví isPopulated a isValid skončí vyjímkou.

// nevim jestli je to bug, nebo požadované chování, protože formy jsem k něčemu většímu ještě nepoužil
arron
Člen | 464
+
0
-

Ha, setDefaults() si samo zjisti isSubmited()…hezke:-) ale co kdyz budu chtit zavola setDefault() i kdyz bude formular submitnuty?

Ja bych prave radeji vyuzival ten styl udelat vsechno v jedne metode. Prijde mi to vic soudrzny a rozhrani te tridy mi pak prijde prehlednejsi, ale to je ciste nazor.

Priklad na zdrojaku je v podstate nejprimitivnejsim prikladem na pouziti formularu. Pokrocile metody prace s formulari uz potom pouzivaji Obsluhu udalosti tak, jak to tu psal _Martin_. Ma to nekolik naprosto zasadnich vyhod. Hlavni je, ze se vubec nemusis starat o validaci, protoze prislusna udalost se zavola jenom tehdy, kdyz je formular submitnuty a zaroven je validni. Takze Ti odpada nejen volani isSubmited, ale zaroven volani isValid().

Co se prehlednosti tyce, tak u velmi jednoduchych formularu je zpracovani v jedne funkci asi opravdu prehlednejsi (ackoliv ja jsem liny myslet na vsechny ty validate apod.), ale obycejne je po submitu formulare treba udelat pomerne dost operaci, takze nakonec ten zpracovavaci blok celou funkci roztříští, cimz se stane neprehlednou. Pak se ukaze vyhoda oddeleni zpracovani do zvlastni funkce:-)

vlna
Člen | 34
+
0
-

arron napsal(a):

Hlavni je, ze se vubec nemusis starat o validaci, protoze prislusna udalost se zavola jenom tehdy, kdyz je formular submitnuty a zaroven je validni. Takze Ti odpada nejen volani isSubmited, ale zaroven volani isValid().

Pokud se stara o validaci jenom jedna metoda, tak me to volani nijak neobtezuje. Naopak jsem rad, kdyz v te funkci vidim takle vyjadreny lifecyclus.
Pri komplikovanych formularich pravda metoda naroste, ale pokud se to pouziva v celem projektu jako konvence, orientaci to nesnizi.
Vzdycky je mozne udelat neco jako:

if ($form->isValid())
{
	$this->_formIsSubmited($form);
}

ale pokud jsou udalosti zase konvence v Nette, taky si na to asi zvyknu.

Editoval vlna (20. 5. 2009 10:27)

Jod
Člen | 701
+
0
-

a mať v jednom ife dve veci if($form->isSubmitted() && $form->isValid()) je už príliš zložité? :D

PetrP
Člen | 587
+
0
-

arron napsal(a):

Ha, setDefaults() si samo zjisti isSubmited()…hezké:-) ale co když budu chtít zavolá setDefault() i kdyz bude formular submitnuty?

Na to by si možná mohl použít Form::setValues(), otázka je existuje situace kdy by si to potřeboval?
Než obsahoval setDefaults tu podmínku na neodeslání tak se tady na fóru množily problémy.

Když na to ještě znova koukám tak se $this->isPopulated = TRUE; nastavuje i v Form::setValues() takže asi ten kód co jsem psal pár příspěvků výše bude fungovat. Nemám chuť to zkoušet ;]

PetrP
Člen | 587
+
0
-

Jod napsal(a):

a mať v jednom ife dve veci if($form->isSubmitted() && $form->isValid()) je už príliš zložité? :D

Řešíme tu pěkné koniny to je pravda, jdu dělat něco užitečnějšího… třeba koukat z okna (je tam pěkně)

vlna
Člen | 34
+
0
-

Jod napsal(a):

a mať v jednom ife dve veci if($form->isSubmitted() && $form->isValid()) je už príliš zložité? :D

Ne, problem to neni. V puvodnim dotazu jsem myslel, ze je potreba volat setDefaults v else … resp. pouzivat ten pomerne slozity if, coz mi slozite prislo.

Diky vsem za vysvetleni.

Jod
Člen | 701
+
0
-

No ja to tak niekedy robím, aby som zbytočne nerobil select po odoslaní formu.

vlna
Člen | 34
+
0
-

Jod napsal(a):

No ja to tak niekedy robím, aby som zbytočne nerobil select po odoslaní formu.

To jo, v tomhle pouziti je to ok, ale pokud by to byla jedina cesta, jak zvalidovat formular a clovek to musel kopirovat pokazde, nebylo by to uz asi uplne DRY.

_Martin_
Generous Backer | 679
+
0
-

PetrP napsal(a):

Tak či onak, hláška té výjimky Form was not populated yet. Call method isSubmitted() or setDefaults(). je trochu zavádějící, neb metoda isSubmitted musí být volána v podmínce, na které isValid závisí. Každopádně, asi je něco zle, když bychom pro správný chod aplikace potřebovali znát implementační detaily jednotlivých metod. Takže bych to uzavřel tím, že (jak říká výjimka) setDefaults nás zachrání=)

P.S. Zvláštní, kolik příspěvků se tu stačilo urodit, než jsem prošel API a sesmolil odpověď=D

Jod
Člen | 701
+
0
-

Ja napríklad pokiaľ robím v nette používam AppForm a tam neni treba ani jeden taký if :) (mám ich tam plno, ale to len preto že sa jeden formulár používa na 10 vecí x)

arron
Člen | 464
+
0
-

Tak či onak, hláška té výjimky Form was not populated yet. Call method isSubmitted() or setDefaults(). je trochu zavádějící, neb metoda isSubmitted musí být volána v podmínce, na které isValid závisí.

Uf to je veta:-D Ctu ji uz po x-te a porad na ni nemam zadny poradny nazor;-)

Každopádně, asi je něco zle, když bychom pro správný chod aplikace potřebovali znát implementační detaily jednotlivých metod.

Jako v zasade nemusis, ze jo (ackoliv jsem zjistil, ze to rozhodne neni na skodu;-)). Staci v zasade respektovat pravidla pro pouzivani formularu:-) Ona Te v podstate tahle vyjimka jemne upozorni, ze to co delas odporuje dobrym mravum psani v Nette;-)

Ja napríklad pokiaľ robím v nette používam AppForm a tam neni treba ani jeden taký if :)

Ale jenom tehdy, kdyz pouzivas udalosti:-)

Jod
Člen | 701
+
0
-

Tak hádam nebudeme predpotopný a pôjdeme z dobou a udalosťami ,)

_Martin_
Generous Backer | 679
+
0
-

arron napsal(a):

Tak či onak, hláška té výjimky Form was not populated yet. Call method isSubmitted() or setDefaults(). je trochu zavádějící, neb metoda isSubmitted musí být volána v podmínce, na které isValid závisí.

Uf to je veta:-D Ctu ji uz po x-te a porad na ni nemam zadny poradny nazor;-)

Mě to po ránu vždycky chvilku trvá, než se naučím vyjadřovat=D Tu výjimku by si někdo mohl vyložit následovně:

$form->isSubmitted();
if ($form->isValid()) {
	// ...
}

což by nefungovalo. Takže asi tak (těžko říct, jestli by někoho napadlo volat isSubmitted mimo podmínku, to těžko soudit z pohledu zaběhlého Nettaře).

arron
Člen | 464
+
0
-

_Martin_ napsal(a):

Mě to po ránu vždycky chvilku trvá, než se naučím vyjadřovat=D Tu výjimku by si někdo mohl vyložit následovně:

$form->isSubmitted();
if ($form->isValid()) {
	// ...
}

což by nefungovalo. Takže asi tak (těžko říct, jestli by někoho napadlo volat isSubmitted mimo podmínku, to těžko soudit z pohledu zaběhlého Nettaře).

Me zase zhruba do obeda trva, nez se probudim a zacnu chapat;-)

Vidim, kam miris. Ono asi dost zalezi na zkusenosti programatora, protoze nazev isSubmitted je dosti vymluvny, nicmene si dovedu predstavit, ze to nekomu zpusobi zmatek…mozna tu vyjimku nejak preformulovat? Na druhou stranu jsme sakra probramatori, cili zadne LAMY ne? :-D

vlna
Člen | 34
+
0
-

_Martin_ napsal(a):

Tak či onak, hláška té výjimky Form was not populated yet. Call method isSubmitted() or setDefaults(). je trochu zavádějící, neb metoda isSubmitted musí být volána v podmínce, na které isValid závisí.

Co kdyby se hodil boolean do isValid($bForce=false). Standardne by mohla isValid vracet false
pokud:
formular jeste nebyl odeslany nebo neni validni

//sorry edited krkolomny vyjadreni :-)

Pokud by chtel nekdo validovat jeste pred odeslanim (tezko si predstavit duvod, ale vic by to kopirovalo soucasny princip), dal by isValid(true). Souhlasim, ze by bylo cistsi nemuset vedet, jak kod uvnitr funguje.

Editoval vlna (20. 5. 2009 12:15)

_Martin_
Generous Backer | 679
+
0
-

Když nad tím tak přemýšlím, začínám mít pocit, že jsme tady do hloubky rozebrali něco, s čím se nikdy nikdo nesetkal=D

Ono chování je asi správné, formulář svým způsobem nemůže o datech říct „nejsou validní“, když ve skutečnosti „nejsou žádná“. A kdyby někdo neznalý potkal tu výjimku a měl s ní problémy, tak díky tomuhle vláknu ho řešení přímo praští mezi oči=D Takže bych to nechal, jak to je.

P.S. Nejlépe se tomuto problému vyhneme přechodem na Zend Framework =P