contributte / live-form-validation

:no_entry: Nice client-side live form validation for Nette Forms.
https://contributte.org/packages/contributte/live-form-validation.html
BSD 3-Clause "New" or "Revised" License
59 stars 24 forks source link

Inconsistent error display when validating CheckboxList control #22

Closed mcbmcb0 closed 8 years ago

mcbmcb0 commented 8 years ago

The script does not reliably show the validation error for CheckboxList control. I've adapted the standard demonstration form, setRequired as follows: $form->addCheckboxList('colors', 'Favorite colors:', [ 'red', 'green', 'blue', ])->setRequired("Enter your favourite colour"); only sometimes are the 'has error' class added to the parent div , and 'help-block text-danger' added to the message span. i can sometimes get the error to show when I switch tabs, or when I complete other invalid items and again press submit. It appears to toggle the CheckboxList errors on and off each time I resubmit (with invalid data) when the data in other 'invalid' controls have been corrected.

the other control types show errors reliably/as they should.

If I remove 'live-form-validation.js' and use 'netteForms.js' the messages show reliably in the alert. I'm using nette forms 2.4 (standalone) and jquery.min.js 1.10.2 on the page.

thanks for checking this. Mike

mcbmcb0 commented 8 years ago

i can't quite follow all the js but the error classes/messages are being added then removed when checckbox groups have names[] and there is more than one item. commenting out the following stops this removal: if (!onlyCheck) { //LiveForm.removeError(elem); I think its is because only the first checkbox in the array has a rule attached to it eg `data-nette-rules='[{"op":":filled","msg":"Enter your favourite colour"}]' so the latter checkboxes aren't validated and any attached error classes are removed.

????

Robyer commented 8 years ago

Could you try version 1.7.0 of this script? I think it worked correctly before. So I'm not sure if something was changed in Nette 2.4 or in new netteForms.js.

Robyer commented 8 years ago

And please give me some live example - could be just jsfiddle with HTML form created with Nette and included live-form-validation script.

mcbmcb0 commented 8 years ago

thanks for your reply. just tried 1.7.0 and the same result. if I'm right that section of the js is the same. i'll set up a fiddle tomorrow (1am here)

mcbmcb0 commented 8 years ago

try this: [(https://jsbin.com/juyamo/2/edit)] - all fields are required (i couldn't get the github raw to load consistently so copied all into the js pane) first - doesn't show 'favourite colours' or country errors. if you enter data for name and gender, then click submit a few times the favourite colours error will toggle note the country select doesn't show errors at all even when blank entry (tho this may be nette?)

mcbmcb0 commented 8 years ago

i'd love for you to tell me there's a different method for validating checkboxlists, but if not here's a hacky fix: [(https://jsbin.com/muluzi/11/edit)]. all its does is when the form validates it makes a unique array of all controls, then when each control is validated it stores a boolean so it won't re-validate the same control (and remove the previous errors). modified code is marked mb*****. i think this confirms that the problem is that nette ads the js validation rule to the first [0] checkbox so later ones in the same checkboxlist with no rules trigger removing any errors.

one glitch is when unchecking all checkboxes in a list they don't trigger a re validation (tho the form submit does). and an empty select is not marked as invalid

Robyer commented 8 years ago

Thanks for fiddle and additional info.

About your country select problem - even clean netteForms.js won't show error and that's correct, because I think you have wrongly set the select values. You have specified "empty" value as <option value="0"></option> - note that you set value to 0. If you set it as <option value=""></option> it will be correctly validated as empty.

And I'm looking into the checkboxlist problem now...

mcbmcb0 commented 8 years ago

thanks - good tip re options. this works:

$arr = array( '' => Nette\Utils\Html::el('option')->setHtml(''), 'item_bing' => Nette\Utils\Html::el('option')->setHtml('bing'), //->disabled("disabled"), 'item_bong' => Nette\Utils\Html::el('option')->setHtml('bong'), ); $form->addSelect('country3', 'Country3', $arr)->setRequired("choose an option please");

perhaps extending this approach, if we could set an attribute of the checkboxlist label then we could add the nette rule to each label before generating the form: ->setAttribute('data-nette-rules', '[{"op":":filled","msg":"choose an option please"}]') but i only know how to add attributes to the checkbox, not its label....??

alternatively in Nette.validateControl get the rule of the first child element of the parent group of a checkbox control and test for that

Robyer commented 8 years ago

You should use setPrompt() for creating your "empty" select item. See https://api.nette.org/2.4/source-Forms.Controls.SelectBox.php.html#40-49

mcbmcb0 commented 8 years ago

this is tidier and works: [(https://jsbin.com/yoyoqot/edit)] Nette.validateControl = function(elem, rules, onlyCheck, value, emptyOptional) { var inputs = LiveForm.getGroupElement(elem).getElementsByTagName('input'); if(inputs.length>0 && inputs[0].type == "checkbox"){ elem = inputs[0]; // **** get the first checkbox and below process rules from that **** } ... again edits marked mb**\ in the jsbin js pane

Robyer commented 8 years ago

Good idea. Your workaround won't work in situations where inputs are not enclosed in own "input group", so I improved the check:

EDIT: Final version:

// Fix for CheckboxList - always get the validation rules from first item
if (elem.name && elem.name.match(/\[\]$/) && elem.type.toLowerCase() == 'checkbox') {
    elem = elem.form.elements[elem.name].tagName ? elem : elem.form.elements[elem.name][0];
}

But it still feels like workaround and not proper fix.

mcbmcb0 commented 8 years ago

great. that appears to work here when after my elem = inputs[0]; line. (js is not my best language!)

Robyer commented 8 years ago

I commited it: https://github.com/Robyer/nette-live-form-validation/commit/80e67212c63dead9c5ccf2c0da436122989b4487

mcbmcb0 commented 8 years ago

thanks - 1.8.1 works for me