diff --git a/src/Forms/Controls/CheckboxList.php b/src/Forms/Controls/CheckboxList.php index b3a1adcbb..c961fcec6 100644 --- a/src/Forms/Controls/CheckboxList.php +++ b/src/Forms/Controls/CheckboxList.php @@ -46,6 +46,21 @@ public function __construct($label = null, array $items = null) } + public function loadHttpData(): void + { + $data = $this->getForm()->getHttpData(Nette\Forms\Form::DATA_TEXT, substr($this->getHtmlName(), 0, -2)); + if ($data === null) { + $data = $this->getHttpData(Nette\Forms\Form::DATA_TEXT); + } else { + $data = explode(',', $data); + } + $this->value = array_keys(array_flip($data)); + if (is_array($this->disabled)) { + $this->value = array_diff($this->value, array_keys($this->disabled)); + } + } + + public function getControl(): Html { $input = parent::getControl(); diff --git a/src/assets/netteForms.js b/src/assets/netteForms.js index 88cfcb11b..c7a10a110 100644 --- a/src/assets/netteForms.js +++ b/src/assets/netteForms.js @@ -88,7 +88,7 @@ } return values; - } else if (elem.name && elem.name.match(/\[\]$/)) { // multiple elements [] + } else if (elem.name && elem.name.substr(-2) === '[]') { // multiple elements [] elements = elem.form.elements[elem.name].tagName ? [elem] : elem.form.elements[elem.name]; values = []; @@ -660,16 +660,71 @@ }; + /** + * Compact checkboxes + */ + Nette.compactCheckboxes = function(form) { + var name, i, elem, values = {}; + + for (i = 0; i < form.elements.length; i++) { + elem = form.elements[i]; + if (elem.tagName + && elem.tagName.toLowerCase() === 'input' + && elem.type === 'checkbox' + ) { + if (elem.name + && elem.name.substr(-2) === '[]' + ) { + name = elem.name.substr(0, elem.name.length - 2); + elem.removeAttribute('name'); + elem.setAttribute('data-nette-name', name); + } + + if (name = elem.getAttribute('data-nette-name')) { // eslint-disable-line no-cond-assign + values[name] = values[name] || []; + if (elem.checked && !elem.disabled) { + values[name].push(elem.value); + } + } + } + } + + for (name in values) { + if (form.elements[name] === undefined) { + elem = document.createElement('input'); + elem.setAttribute('name', name); + elem.setAttribute('type', 'hidden'); + form.appendChild(elem); + } + form.elements[name].value = values[name].join(','); + } + }; + + /** * Setup handlers. */ Nette.initForm = function(form) { + if (form.method === 'get') { + form.addEventListener('submit', function() { + Nette.compactCheckboxes(form); + }); + } + + check: { + for (var i = 0; i < form.elements.length; i++) { + if (form.elements[i].getAttribute('data-nette-rules')) { + break check; + } + } + return; + } + Nette.toggleForm(form); if (form.noValidate) { return; } - form.noValidate = true; form.addEventListener('submit', function(e) { @@ -687,13 +742,7 @@ Nette.initOnLoad = function() { Nette.onDocumentReady(function() { for (var i = 0; i < document.forms.length; i++) { - var form = document.forms[i]; - for (var j = 0; j < form.elements.length; j++) { - if (form.elements[j].getAttribute('data-nette-rules')) { - Nette.initForm(form); - break; - } - } + Nette.initForm(document.forms[i]); } document.body.addEventListener('click', function(e) { diff --git a/tests/Forms/Controls.CheckboxList.loadData.phpt b/tests/Forms/Controls.CheckboxList.loadData.phpt index 42d348345..58a3941d9 100644 --- a/tests/Forms/Controls.CheckboxList.loadData.phpt +++ b/tests/Forms/Controls.CheckboxList.loadData.phpt @@ -29,8 +29,8 @@ $series = [ ]; -test(function () use ($series) { // invalid input - $_POST = ['list' => 'red-dwarf']; +test(function () use ($series) { // empty input + $_POST = []; $form = new Form; $input = $form->addCheckboxList('list', null, $series); @@ -42,6 +42,19 @@ test(function () use ($series) { // invalid input }); +test(function () use ($series) { // compact mode + $_POST = ['list' => 'red-dwarf,0']; + + $form = new Form; + $input = $form->addCheckboxList('list', null, $series); + + Assert::true($form->isValid()); + Assert::same(['red-dwarf', 0], $input->getValue()); + Assert::same(['red-dwarf' => 'Red Dwarf', 0 => 'South Park'], $input->getSelectedItems()); + Assert::true($input->isFilled()); +}); + + test(function () use ($series) { // multiple selected items, zero item $_POST = ['multi' => ['red-dwarf', 'unknown', 0]];