Client and server side validation of checkbox array in container using own validator or onValidate method

4 years ago

fronty
Member | 16
+
0
-

Hi,

I may be blind, but can't find this anywhere. I would like to validate array of checkboxes in container, so at least one have to be checked, both client and server side. I managed to validate them server side, but my form is in modal window and is submitted without AJAX (thus the modal window is closed), so primary I need client side validation.
My code in form component currently looks similar to this:

<?php
class MyForm extends \Nette\Application\UI\Form {

    public function __construct(\Nette\Database\Table\Selection $items) {
        // Add array of checkboxes
        $container = $this->addContainer('id_items');
        foreach ($items as $item) {
            $container->addCheckbox($item->id, $item->name);
        }

        // Submit and process
        $this->addSubmit('send', 'Save');
        $this->onSuccess[] = $this->processMyForm;
        $this->onValidate[] = $this->validateMyForm;
    }

    public function validateMyForm(MyForm $form) {
        $values = $form->getValues(TRUE);

        $items = array_filter($values['id_items']);
        if (empty($items)) {
            $form->addError('Choose at least one item.');
        }
    }

    public function processMyForm(MyForm $form) {
        // ... insert to DB or whatever
    }
}
?>

According to this and this I tried to create my own validator so I can create it's client side counterpart like so:

checkboxRules.php

<?php
namespace App\Validators;

use Nette\ComponentModel\IContainer;

class CheckboxRules {
    const ONE_CHECKED = 'CheckboxRules::validateOneChecked';

    public static function validateOneChecked(IContainer $control, $args) {
        // Somehow check at least one selected item (probably from form instance in $args)
    }
}
?>

myForm.php

<?php
public function __construct(\Nette\Database\Table\Selection $items) {
    $container = $this->addContainer('id_items');
    foreach ($items as $item) {
        $container->addCheckbox($item->id, $item->name)
            ->addRule(CheckboxRules::ONE_CHECKED, 'Choose at least one item.');
    }

    ...
}
?>

main.js

<script>
Nette.validators.CheckboxRules_validateOneChecked = function(elem, args, val) {
    // console.log(args);
    // Somehow validate at least one checked input with the same name
    return false;
};
</script>

But I ended very soon with Tracy error Unknown validator 'CheckboxRules::validateOneChecked' for control '1'., which is very strange, because ONE_CHECKED constant value was output as string ‘CheckboxRules::validateOneChecked’, so the file should be included correctly. So I changed the callback argument in myForm.php like so:

<?php
...
$container->addCheckbox($item->id, $item->name)
    ->addRule(callback(CheckboxRules::ONE_CHECKED), 'Choose at least one item.');
...
?>

With this code I am able to view the form, but after the form is submitted, I end up with Tracy error Callback 'CheckboxRules::validateOneChecked' is not callable.. I tried to remove arguments from CheckboxRules::validateOneChecked(), but the error remained.

What am I doing wrong or how can be this type of validation achieved?

4 years ago

japlavaren
Backer | 411
+
0
-

Hi,

use CheckboxList and setRequired().

4 years ago

fronty
Member | 16
+
0
-

Well, I was blind. Thank's a lot!

4 years ago

japlavaren
Backer | 411
+
0
-

fronty wrote:

Well, I was blind. Thank's a lot!

;)