Form Boost: experiment, který bude snad někoho zajímat

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

Zdravím,

ani nevím proč, ale zdála se mi jako zajímavá myšlenka oddělit definici formuláře do samostatného souboru a definovat samotný formulář anotacemi. „Blázen!“, říkáte si. A možná i jsem. Jen mě zajímalo, jak by to fungovalo, jak by to vypadalo a jak by se s tím dělalo. Jde tedy hlavně o experiment a já bych rád věděl váš názor.

Po pár hodinách práce mi vyšel tento funkční výsledek:

class RegisterForm {

	/**
	 * @Text(Jméno)
	 * @Pattern('[a-zA-Z0-9_.]+', msg = Nesprávné uživatelské jméno)
	 * @MaxLength(12, msg = Délka musí být max. 12)
	 * @MinLength(2, msg = Délka musí být min. 2)
	 * @Required(msg = Povinný údaj)
	 */
	public $username;

	/**
	 * @Password(Heslo)
	 * @Required(msg = Povinný údaj)
	 */
	public $password;

	/**
	 * @Password(Heslo znovu)
	 * @Required(msg = Povinný údaj)
	 * @Equal(password, msg = Hesla se neshodují)
	 */
	public $passwordValidation;

	/**
	 * @Text(E-mail, emptyValue = '@')
	 * @Email(msg = Nesprávný formát emailu, required = false)
	 */
	public $email;

	/**
	 * @Select(Národnost, prompt = Vyberte)
	 */
	public $nationality;

	public $nationalityItems = array('cz' => 'Česká', 'sk' => 'Slovenská');


	/** @Submit('Registrovat') */
	public function onSubmit() {
		dump($this);
	}

}

Propojení s presenterem jsem zatím moc neřešil, zatím zjednodušeně takto:

	protected function createComponentForm() {
		return FormBoost::from(new RegisterForm);
	}

Výhody

  • přehlednější kód
  • odeslaná data dostaneme přímo v properties objektu, nezabýváme se tedy s polem (bez napovídání)
  • default hodnoty můžeme nastavit jednotlivým properties (rovnou nebo konstruktorem)
  • renderuje se naprosto stejně jako normální formulář, mohl by se i rozšířit o vlastní šablonu s manuálním vykreslením
  • podporuje filtrování hodnot přes callback na filter<ControlName>($value)
  • podle mě je kód o něco kratší, ale může to být jen zdání

Nevýhody

  • paradoxně samotné anotace (nenapovídání kódu, překlepy v názvech, možné konflikty)
  • zatím bez větší podpory condition, conditionOn apod.
  • bez podpory groups a containerů (neřešil jsem, zatím)
  • bez podpory wrappers a CSS tříd (neřešil jsem, zatím)
  • a všechno ostatní, co jsem ještě neřešil

Co si o tom myslíte? Má vůbec cenu pokračovat dál? (pokračoval bych, kdyby byl zájem a hlavně čas, který ale stejně asi nebude)

awsickness
Člen | 98
+
0
-

ma to smysl jen ve spojeni s nejakou db entitou / osobne mam postaveny automaticky generator formularu nad doctrine a na zaklade anotaci takze pak staci jen predat entitu nad kterou chci formular a je to.

Nox
Člen | 378
+
0
-

Podstatná nevýhoda je absence jakékoli dynamičnosti, tzn. podmíněné, opakované formulářové prvky, statické položky v selectech; nekompatibilita (myslim) s dependentselectbox, replicatorem atd.

Ale pokud toto někomu nevadí a je to pro něj přehlednější, pak proč ne

Filip Procházka
Moderator | 4668
+
0
-

Annotace nad vlastnostmi objektu ano, ale takto asi ne. Nette\Database to neumí, Doctrine s tím kamarádit nebude a jen tak si psát schránky pro formuláře mi přijde zbytečné.

Jelikož používám Doctrine, tak nějaký takovýto builder budu co nevidět potřebovat. Ale naštěstí už mám vyřešení mapování formulářů na entity, takže to bude hračka :)

@**awsickness**: nechceš to někam nahodit? že bych se inspiroval ;)

voda
Člen | 561
+
0
-

Mám něco podobného, pracuje to rovnou s entitami. Zatím ve stádiu vývoje. Většinu věcí to načítá s Doctrine anotací, pro zbytek tam je @Input.

Továrnička pak vypadá asi takto:

public function createComponentCreateForm() {
	$form = $this->context->formBuilder->build('\Article'); // název třídy nebo entita
	$that = $this;
	$form->onSuccess[] = function(\Article $article) use ($that) {
		$that->context->articleModel->createArticle($article);
		$that->flashMessage("Článek byl vytvořen.", 'success');
		$that->redirect('default');
	};
	// tady se může s formulářem dělat cokoliv dalšího
	return $form;
}

K vidění na https://github.com/…/FormBuilder

awsickness
Člen | 98
+
0
-

hospilan: nemyslim si ze bych neco delal lepe nez ty,ale jen pro zajimavost kam jsem dosel po nekolika mesicich si s tim hrani.

pro kazdy typ v entite jako je string int 1:n m:n jsem si udelal doctrine → form kde prochazim anotaci a pokud najdu jednoduchy typ vytvorim objekt ktery vi jak sam sebe nasetovat pridat filtry … a prida se do daneho formulare.

zpetne to funguje podoben akorad pro values z formulare hledam v metadatech jaky je to ty a novou value predan tomu samemu objektu ktery presne vi co s ni ma delat a kde hledat pripadne objekty.

plus navic umim prepsat annotacni definici kdykoliv vytvarim formular atd.

jedine co ted bojuji ze bychom radi udelali N subform pro navazane entity
napriklad user adresy 1:n tak aby v jednom adresari mel n subformularu pro adresy. to mi jelo ale nebylo to pekne takze me ceka predelavani.

v pripade zajmu ukazu casti kodu ale bohuzel to nemuzu davat verejne komplet.

redhead
Člen | 1313
+
0
-

@awsickness: Pokud to řeší pouze Doctrine anotace, tak se myslím ochudíš o pár pravidel, které Doctrine neřeší (min. length, regexp pattern, závislosti, atp.).

@Nox: Jasně. Popřemýšlím o způsobech, jakým by to šlo řešit a třeba to i půjde. Já jsem tyto komponenty nikdy nepoužil a tak nevím, co všechno potřebují.

@HosipLan: Tak s Nette\Database to ani nemá co dělat. Navíc se nic neliší od jejího používání i s tímto objektem – prostě jen místo setDefaults() to nasetuješ propertám tohoto objektu (což by se pro result z DB dalo zautomatizovat).

S Doctrine je to pravda, tam to hapruje. Ale nezdá se mi nereálný využít Doctrine anotace a namapovat je na pravidla ve formulářích. Pak bys nemusel psát @MaxLentgh jako to mám teď já, ale vzalo by se to z definice sloupce. Přiznám se, že Doctrine jsem nikdy nepoužíval, ale neviděl bych v tom velký problém.


Čili další směřování by bylo asi sjednotit výhody obou – Doctrine anotací a formulářových anotací.

Editoval redhead (21. 3. 2012 11:37)

awsickness
Člen | 98
+
0
-

co se tyce FILLTRU samozrejme plne podporuji completni filtry jake ma NETTE staci je zapsat do annotace.

Honza Marek
Člen | 1664
+
0
-

Třeba v Symfony řeší podobný problém, ale trochu jinak. Využívají dat z doctrine metadat a z definovaných validačních pravidel (oboje jde zapsat jako anotace třídy). Pak se to používá asi takto (přesnou syntaxi si vůbec nepamatuju):

$form = $formFactory->createFrom('Blabla\Model\Clanek')
	->add('name')
	->add('description')
	->add('publishDate');

if ($form->isSubmitted()) {
	$entity = $form->getData();
	// ...
}

Výhodou je, že se nemíchá v jedné třídě logika formuláře (submit) a vlastnosti datového objektu formuláře (db entita nebo třída reprezentující data vč. validací).