contributte / forms-multiplier

:repeat: Form multiplier & replicator for Nette Framework
https://contributte.org/packages/contributte/forms-multiplier.html
MIT License
26 stars 21 forks source link

Add/Delete Button validation #22

Closed ajaxovic closed 4 years ago

ajaxovic commented 6 years ago

I have:

Composer.json

"require": {
        ...
        "webchemistry/forms-multiplier": "dev-master"
    },

updated at e9983931f9

Form factory:

/** @var \WebChemistry\Forms\Controls\Multiplier $multiplier */
$multiplier = $form->addMultiplier('rows', function (Nette\Forms\Container $container, Nette\Forms\Form $form) {

    $container->addText('name', 'Name')
        ->setRequired('Please, fill name');
}

$multiplier->addCreateButton('Add row', 1, function (SubmitButton $submitter) {
    $submitter->setValidationScope(FALSE);
});

In generated HTML code, there is

<input type="submit" name="rows[multiplier_creator]" value="Add row" formnovalidate="" data-nette-validation-scope="[&quot;rows&quot;]" class="ajax prepareLines">

But when I click twice od add button, nette $form->hasErrors() contains validation error 'Please, fill name'

I expect no validation on add button, user can add multiple rows and then fill them...

MartkCz commented 6 years ago

Can you try last commit?

ajaxovic commented 6 years ago

Revision 2e3d657e79 does not work

Nette\MemberAccessException

Call to undefined method WebChemistry\Forms\Controls\Multiplier::getCreateButtons(), did you mean addCreateButton()?

Problematic code (generated in cache):

<?php
        $_multiplier = end($this->global->formsStack)["rows"];
        if (isset($_multiplier->getCreateButtons()[1])) {$_input = $_multiplier->getCreateButtons()[1];
            echo $_input->getControl()->addAttributes(['class' => 'ajax prepareLines']);
        }
?>

cache deleted..

MartkCz commented 6 years ago

now?

ajaxovic commented 6 years ago

Sorry for delay...

Textbox works now, but problem is with prompt on select:

$container->addSelect('parent_id', 'Parent', $this->names)
                ->setPrompt('Choose parent');

When I hit add button, exception appears:

Value '' is out of allowed set [1, 2, 3, 10] in field 'parent_id'

When I remove prompt, all works. Checked out commit: b1c11b7000c1da818f653f82550e909e303b60aa

MartkCz commented 6 years ago

Sorry, this is built-in behavior of nette select box :/

ajaxovic commented 6 years ago

Thanks for answer.

Are you sure? Validation work when select is not in Multiplier...

ajaxovic commented 5 years ago

Are you sure? This is still issue...

MartkCz commented 5 years ago

Ah, sorry.

Problem code is

$multiplier = $form->addMultiplier('rows', function (Nette\Forms\Container $container, Nette\Forms\Form $form) {
    $container->addSelect('parent_id', 'Parent', $this->names)
                ->setPrompt('Choose parent');
}

with new version?

s1t2e3 commented 5 years ago

Mam rovnaky problem. Ak do selectu pridam ->setPrompt(...) nette hlasi chybu Value '' is out of allowed set [0] in field

BigOHenry commented 5 years ago

at dev-master problem still persist

BigOHenry commented 4 years ago

I have problem with validation on createButton. I tried to set ->setNoValidate() and ->setValidationScope(null), but on + button form is still validating.

BigOHenry commented 4 years ago

Thank you for the fix, but problem still persist at latest dev-master.

MartkCz commented 4 years ago

@BigOHenry I fix only Value '' is out of allowed set [0] in field not validation on createButton. I tried

    protected function createComponentMultiplier() {
        $form = new Form();

        $form['multiplier'] = $mul = new Multiplier(function (Container $container) {
            $container->addText('name')
                ->setRequired();
        });

        $mul->addCreateButton()
            ->setNoValidate();

        $form->addSubmit('send');

        return $form;
    }

and it works, please send your code

BigOHenry commented 4 years ago
                /** @var Multiplier $containers */
                $containers = $form->addMultiplier($itemGroup->getName(), function (Container $container) use ($itemGroup) {

                        $container->addInteger(
                            'sequence_priority',
                            $this->translator->translate('config.definition.sequence_priority')
                        )
                                  ->setRequired($this->translator->translate("forms.validation.required"))
                                  ->setOption('group_name', $itemGroup->getName())
                                  ->setOption('example', '')
                                  ->setOption('note', '');

                        /** @var ItemDefinition $itemDefinition */
                        foreach ($itemGroup->getItemDefinitions() as $itemDefinition) {
                            $translated_item_definition = $this->translator->translate('config.definition.' . $itemDefinition->getName());

                            $container->addText($itemDefinition->getName(), $translated_item_definition)
                                      ->setOption('group_name', $itemGroup->getName())
                                      ->setOption('example', $itemDefinition->getExample())
                                      ->setOption('note', $itemDefinition->getNote());

                            if ($itemDefinition->isNotNull()) {
                                $container[$itemDefinition->getName()]
                                    ->setRequired($this->translator->translate("forms.validation.required"));
                            }
                        }
                        $container->addHidden('dummy_format')->setOption('group_name', $itemGroup->getName());
                    }, 0);

                /** @var \Nette\Application\UI\Presenter $presenter */
                $presenter = $this;

                $containers->addCreateButton('', 1)
                           ->setNoValidate()
                           ->setValidationScope([])
                           ->addOnCreateCallback(
                                function (Submitter $submitter) use ($presenter, $itemGroup) {
                                    $submitter->setHtmlAttribute('class', 'btn-success btn-sm fad fa-plus ajax ' . $itemGroup->getName() . '-multiplier-creator-config config-recurring-add-button');
                                    $submitter->setOption('group_name', $itemGroup->getName());
                                    $submitter->onClick[] = function () use ($presenter) {
                                        $presenter->redrawControl('configForm');
                                    };
                                }
                            );
MartkCz commented 4 years ago

@BigOHenry I tried your code and all works. Which version of nette / contributte/forms-multiplier (commit) do you have?

Does submit button have attribute formnovalidate?

Is validation on client or server side?

BigOHenry commented 4 years ago

I have my own onValidate ($form->onValidate[] = array($this, 'onValidate');) validations. On multiplier add button is called onValidate too. I think with setNoValidate() should be onValidate skipped too.

Thank you!

MartkCz commented 4 years ago

https://doc.nette.org/en/3.0/form-validation#toc-disabling-validation

onValidate event on the form is always invoked and is not affected by the setValidationScope. onValidate event on the container is invoked only when this container is specified for partial validation.

yess-webioza commented 4 years ago

Is this issue resolved? I'm having trouble with Value '' is out of allowed set [...] in field xy

Used version: "contributte/forms-multiplier": "^3.0"

Code:

...
$list = $form->addMultiplier('list', function (Container $container, Nette\Forms\Form $form) {  
   $container->addSelect( 'select', 'Pick one' , ['a' => 'a', 'b' => 'b'] )  
      ->setPrompt('')  
      ->setRequired(true);
}, 0);

$list ->addRemoveButton('Remove', function (SubmitButton $submitter) use ($self) {
  $submitter->setValidationScope(false);
  $submitter->onClick[] = [$self, 'onClick'];
});
...

Steps to reproduce error:

  1. Click on createButton to add new copy and fill out all inputs
  2. Click on createButton again and leave inputs empty (especially select)
  3. Click on removeButton and voila

If you need some more info to resolve it. I'll be happy to help.