forms icon indicating copy to clipboard operation
forms copied to clipboard

Filled validation in custom Nette\Forms\Control instance

Open hrach opened this issue 1 month ago • 3 comments

I have a custom form control implementing Nette\Forms\Control interface.

I want to add a common rule to check if that control is filled. Sadly, the default implementation delegates to the static Validator class that requires a BaseControl subtype.

https://github.com/nette/forms/blob/fcfc86c0a52530357568a0c68116570ef1f6556d/src/Forms/Validator.php#L162

I worked around this by providing custom rules that override the filled check:

class CustomControlRules extends Rules
{
	public static function validateRule(Rule $rule): bool
	{
		if ($rule->validator === Form::Filled) {
			$control = $rule->control;
			if (!$control instanceof \MyCustomImplementation) {
				throw new InvalidStateException();
			}
			return $control->isFilled();
		} else {
			return parent::validateRule($rule);
		}
	}
}

But, this is getting forbidden by the recent (Forms 3.2) changes that are making the Rules class final.

The simple solution is to remove the final once again, but since I got to report this, I'd ask you to consider some proper LSP solution -> ideally moving the required methods to the interface.

hrach avatar Nov 24 '25 21:11 hrach

Yeah, feel free to suggest some proper solutions.

dg avatar Nov 25 '25 12:11 dg

Which solution do you prefer?

  1. Add isFilled() to Control (BC break)
  2. Add isFilled() to Control but commented out (not a BC break, at least for now), add use method_exists
  3. Add ValidatedControl interface and implement in BaseControl a. add there just validateFilled & validateMinMax (to extract this datetime logic) b. add there more

hrach avatar Nov 29 '25 14:11 hrach

Another option implemented in #347.

hrach avatar Nov 29 '25 19:11 hrach