CheckboxList – validace položek

Pepino
Člen | 245
+
0
-

Zdravím, buď jsem špatně hledal, nebo jsem na fóru řešení nenašel.
Mám následující kód:

$form->addCheckboxList('barvy', 'Barvy', [
	0 => 'Bílá',
	1 => 'Černá',
	2 => 'Modrá',
	3 => 'Zelená'
]);

Je nějaké validační pravidlo, aby bylo povinné vybrat položky [0, 2]? Můžu místo CheckboxListu použít obyčejné checkboxy, ale zajímá mě, zda to jde právě u CheckboxListu.

m.brecher
Generous Backer | 713
+
+1
-

Ahoj,

zkusil jsem jen tak podle nápovědy tohle a zdá se , že to je to co potřebuješ:

        $form->addCheckboxList('barvy', 'Barvy', [
            0 => 'Bílá',
            1 => 'Černá',
            2 => 'Modrá',
            3 => 'Zelená'
        ])->addRule($form::IS_IN, 'Sorry, musíte zvolit bílá a modrá', [0,2]);
Pepino
Člen | 245
+
0
-

@m.brecher funguje jen pokud není nutné vybrat žádnou položku. Ale já potřebuju mít vybrané minimálně ty povinné položky. Když teda upravím na:

$form->addCheckboxList('barvy', 'Barvy', [
	0 => 'Bílá',
	1 => 'Černá',
	2 => 'Modrá',
	3 => 'Zelená'
])
->setRequired('Vyberte barvy.')
->addRule($form::IS_IN, 'Sorry, musíte zvolit bílá a modrá', [0,2]);

Tak to nefunguje vůbec.

uestla
Backer | 796
+
+4
-

Form::IS_IN kontroluje, že vybrané hodnoty jsou v daném poli, ale ne že tam jsou všechny.

@Pepino Použil bych callback validaci:

$form->addCheckboxList('barvy', 'Barvy', $barvy)
	->setRequired('Zvolte prosím barvy.')
	->addRule(
		fn(CheckboxList $control) => array_diff([0, 2], $control->getValue()) === [],
		'Barvy "Bílá" a "Modrá" jsou povinné.'
	)
;
Pepino
Člen | 245
+
+2
-

@uestla Jo tohle funguje, ale zase tam není JS validace. Nakonec jsem to pořešil vlastním validátorem. Kdyby někdo hledal něco podobného tak pro inspiraci.

class MyValidator {
	public static function validateContain(Control $control, $args): bool
	{
		if (!$control instanceof CheckboxList && !$control instanceof MultiSelectBox)
			return true;

		if (is_array($args)) {
			return array_diff($args, $control->getValue()) === [];
		} else {
			return in_array($args, $control->getValue());
		}
	}
}
Nette.validators['MyValidator_validateContain'] = (elem, args, val) => {
	if (Number.isInteger(args)) {
		args = args.toString();
	}

	if ((elem.tagName == 'SELECT' && elem.hasAttribute('multiple')) ||
		(elem.tagName == 'INPUT' && elem.getAttribute('type') == 'checkbox' && document.querySelectorAll('input[name="' + elem.getAttribute('name') + '"]').length > 1)) {
		if (Array.isArray(args)) {
			let isValid = true;
			args.forEach((el) => {
				if (Number.isInteger(el)) {
					el = el.toString();
				}
				if (val.includes(el) === false) {
					isValid = false;
					return;
				}
			});
			return isValid;
		} else {
			if (elem.tagName == 'INPUT' && elem.value !== args) return true;
			return val.includes(args);
		}
	}
	return true;
};