diff --git a/src/Forms/Controls/TextBase.php b/src/Forms/Controls/TextBase.php
index 3c3c52e08..d72d0750b 100644
--- a/src/Forms/Controls/TextBase.php
+++ b/src/Forms/Controls/TextBase.php
@@ -137,6 +137,12 @@ protected function getRenderedValue(): ?string
/** @return static */
public function addRule($validator, $errorMessage = null, $arg = null)
{
+ foreach ($this->getRules() as $rule) {
+ if (!$rule->canExport() && !$rule->branch) {
+ return $this;
+ }
+ }
+
if ($validator === Form::LENGTH || $validator === Form::MAX_LENGTH) {
$tmp = is_array($arg) ? $arg[1] : $arg;
if (is_scalar($tmp)) {
diff --git a/src/Forms/Controls/TextInput.php b/src/Forms/Controls/TextInput.php
index 15b354aff..8d3645267 100644
--- a/src/Forms/Controls/TextInput.php
+++ b/src/Forms/Controls/TextInput.php
@@ -68,6 +68,12 @@ public function getControl(): Nette\Utils\Html
/** @return static */
public function addRule($validator, $errorMessage = null, $arg = null)
{
+ foreach ($this->getRules() as $rule) {
+ if (!$rule->canExport() && !$rule->branch) {
+ return $this;
+ }
+ }
+
if ($this->control->type === null && in_array($validator, [Form::EMAIL, Form::URL, Form::INTEGER], true)) {
static $types = [Form::EMAIL => 'email', Form::URL => 'url', Form::INTEGER => 'number'];
$this->control->type = $types[$validator];
diff --git a/src/Forms/Controls/UploadControl.php b/src/Forms/Controls/UploadControl.php
index 7024dbfb8..cbb481ecb 100644
--- a/src/Forms/Controls/UploadControl.php
+++ b/src/Forms/Controls/UploadControl.php
@@ -33,7 +33,8 @@ public function __construct($label = null, bool $multiple = false)
$this->control->type = 'file';
$this->control->multiple = $multiple;
$this->setOption('type', 'file');
- $this->addRule([$this, 'isOk'], Forms\Validator::$messages[self::VALID]);
+ $this->addCondition(true) // not to block the export of rules to JS
+ ->addRule([$this, 'isOk'], Forms\Validator::$messages[self::VALID]);
$this->addRule(Form::MAX_FILE_SIZE, null, Forms\Helpers::iniGetSize('upload_max_filesize'));
$this->monitor(Form::class, function (Form $form): void {
diff --git a/src/Forms/Helpers.php b/src/Forms/Helpers.php
index 3db7b1356..6a7d01f9a 100644
--- a/src/Forms/Helpers.php
+++ b/src/Forms/Helpers.php
@@ -100,12 +100,18 @@ public static function exportRules(Rules $rules): array
{
$payload = [];
foreach ($rules as $rule) {
- if (!is_string($op = $rule->validator)) {
- if (!Nette\Utils\Callback::isStatic($op)) {
+ if (!$rule->canExport()) {
+ if ($rule->branch) {
continue;
}
+ break;
+ }
+
+ $op = $rule->validator;
+ if (!is_string($op)) {
$op = Nette\Utils\Callback::toString($op);
}
+
if ($rule->branch) {
$item = [
'op' => ($rule->isNegative ? '~' : '') . $op,
diff --git a/src/Forms/Rule.php b/src/Forms/Rule.php
index 9f3c628f8..1d2fa0344 100644
--- a/src/Forms/Rule.php
+++ b/src/Forms/Rule.php
@@ -36,4 +36,12 @@ class Rule
/** @var Rules|null for conditions */
public $branch;
+
+
+ /** @internal */
+ public function canExport(): bool
+ {
+ return is_string($this->validator)
+ || Nette\Utils\Callback::isStatic($this->validator);
+ }
}
diff --git a/tests/Forms/Controls.TextArea.render.phpt b/tests/Forms/Controls.TextArea.render.phpt
index 660f48d46..45e708c79 100644
--- a/tests/Forms/Controls.TextArea.render.phpt
+++ b/tests/Forms/Controls.TextArea.render.phpt
@@ -119,3 +119,13 @@ test('setEmptyValue & setNullable', function () {
Assert::null($input->getValue());
Assert::same('', (string) $input->getControl());
});
+
+
+test('addFilter() & rules', function () {
+ $form = new Form;
+ $input = $form->addTextArea('text')
+ ->addFilter(function () {})
+ ->addRule(Form::MAX_LENGTH, 'maxl', 10);
+
+ Assert::same('', (string) $input->getControl());
+});
diff --git a/tests/Forms/Controls.TextInput.render.phpt b/tests/Forms/Controls.TextInput.render.phpt
index 01ae9da13..397955472 100644
--- a/tests/Forms/Controls.TextInput.render.phpt
+++ b/tests/Forms/Controls.TextInput.render.phpt
@@ -235,3 +235,15 @@ test('addInteger', function () {
Assert::same('', (string) $input->getControl());
});
+
+
+test('addFilter() & rules', function () {
+ $form = new Form;
+ $input = $form->addText('text')
+ ->addRule(Form::MIN, 'min', 1)
+ ->addFilter(function () {})
+ ->addRule(Form::MAX, 'max', 10)
+ ->addRule(Form::MAX_LENGTH, 'maxl', 10);
+
+ Assert::same('', (string) $input->getControl());
+});
diff --git a/tests/Forms/Helpers.exportRules.phpt b/tests/Forms/Helpers.exportRules.phpt
index 1cfd41cf7..649602319 100644
--- a/tests/Forms/Helpers.exportRules.phpt
+++ b/tests/Forms/Helpers.exportRules.phpt
@@ -91,3 +91,16 @@ test('', function () {
],
], Helpers::exportRules($input2->getRules()));
});
+
+
+test('addFilter', function () {
+ $form = new Form;
+ $input = $form->addText('text');
+ $input->addRule(Form::PATTERN, 'match pattern', '\d+');
+ $input->addFilter(function () {});
+ $input->setRequired(false);
+ $input->addRule(Form::EMAIL);
+ Assert::same([
+ ['op' => ':pattern', 'msg' => 'match pattern', 'arg' => '\\d+'],
+ ], Helpers::exportRules($input->getRules()));
+});