CheckboxList – validace položek
- Pepino
- Člen | 257
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.
- Pepino
- Člen | 257
@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 | 799
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 | 257
@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;
};