Jak přidat vlastní pravidlo?

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Tomáš Votruba
Moderator | 1114
+
0
-

Chtěl bych si přidat vlastní pravidlo, např. pro ročné číslo, FORM::RC, a zajímá mne, zda toho lze dostáhnout jinak než poděděním TextInputu, přidáním vlastního pravidla a přetížením metody addText ve vlastní třídě Form?

Tomáš Votruba
Moderator | 1114
+
0
-

Napadá mne, šlo by to nějak přes extension method?

Nette\Forms\Control\TextInput::extensionMethod('validateRc', function ($control) {
    return Validators::isRc($control->getValue());
});

Editoval Schmutzka (20. 8. 2012 17:39)

vvoody
Člen | 910
+
0
-

Schmutzka napsal(a):

… a přetížením metody addText ve vlastní třídě Form?

alebo (bez dedenia Form) cez extensionMethod nad \Nette\Forms\Container ako to robí napríklad DateInput

Panda
Člen | 569
+
0
-

Signatura addRule obsahuje jako první parametr $operation. To není nic jiného než callback, jen s drobnou úpravou: pokud je callback string začínající na :, přeloží se na statickou metodu s názvem validate<operation> nad třídou právě validovaného inputu. Konstanty Form::* nejsou nic jiného, než stringy typu :filled (které se u textového inputu přeloží na callback TextInput::validateFilled).

Z toho vyplývají následující poznatky:

  • Aby bylo možné přidat pravidlo, které by šlo zadat stringem typu :rule, musela by být možnost přidat třídě statickou extension metodu. To Nette v současnosti nepodporuje.
  • Jako pravidlo je možné přidat jakoukoliv statickou i nestatickou metodu. Nestatickou metodu pravděpodobně bude potřeba přidat pomocí callback($object, 'validateRule'), ale možná projde i prosté pole – nezkoumal jsem. Statickou metodu je možné předat jako string.

Já osobně vlastní pravidla přidávám asi takto:

class MyRules
{
	const RULE1 = 'MyApp\MyRules::validateRule1';
	const RULE2 = 'MyApp\MyRules::validateRule2';

	public static function validateRule1(BaseControl $control)
	{
		// ...
	}

	public static function validateRule2(BaseControl $control)
	{
		// ...
	}
}
$form->addText(...)
	->addRule(MyRules::RULE1, ...);

Nějaké vrtání ve Formu, TextBase atd. mi přijde nepohodlné, nebezpečné a zbytečné.

Mimochodem, takhle to funguje někdy od dřevních dob Nette 0.8.

Editoval Panda (20. 8. 2012 18:54)

Tomáš Votruba
Moderator | 1114
+
0
-

@Panda: Vřelé díky, přesně to jsem hledal! Jak prosté.

Myslíš, že bys to mohl přidat do Planette? Pokud by se ti nechtělo, můžu to udělat po vyzkoušení sám. Je možné, že některá pravidla „navíc“ se často při programování opakují, jen se nikomu nechce pro složitost psát.

Panda
Člen | 569
+
0
-

Je to tam: https://doc.nette.org/…s/validation. Kdyby to bylo moc ukecané, mohu to zkrátit.

redhead
Člen | 1313
+
0
-

Pando, mohl bys možná ještě doplnit, že lze tyto vlastní pravidla definovat i na klientské straně, jako rozšíření objektu Nette.validators (viz https://github.com/…etteForms.js#L130). Z Namespace\Validator::validatePassword se na klientu zavolá (pokud existuje) metoda Nette.validators.NamespaceValidator_validatePassword

Panda
Člen | 569
+
0
-

Dobrý nápad, úplně jsem na tu možnost zapomněl. Doplněno.

Tomáš Votruba
Moderator | 1114
+
0
-

Luxusní práce, díky :)

Možná ten úvodní text bych proložil citacemi kódu – názornými příklady, aby to nebylo zdlouhavě popsáno ve větách.

Editoval Schmutzka (22. 8. 2012 18:31)

Tomáš Votruba
Moderator | 1114
+
0
-

Dnes jsem pár hodin hledal drobný bug v určení názvu pravidla, který zatím nesouhlasí s kuchařkou: viz git, doplnil bych tedy zatím nějaké upozornění (případně do budoucnosti info o nutnosti nového netteForms.js), nemyslím, že je často měněno.