For a credit card expiration date, which form elements are “correct” and play nicely with browser autofill?
I’ve seen two main ways of doing it. As a Safari user, this is the most common field that silently fails when I’m auto-filling payment information. Here’s a failure from a real-life experience:
<select>-based field
<label for="billing-cc-exp" class="inputLabelPayment">Expiration Date:</label>
<select name="billing-cc-exp" id="billing-cc-exp" onfocus="methodSelect('pmt-gps')" autocomplete="off">
<option value="0322" selected="selected">03/2022</option>
<option value="0422">04/2022</option>
<option value="0522">05/2022</option>
<option value="0622">06/2022</option>
…
</select>
<input>-based field
<label for="frmCCExp">Expiry</label>
<input name="cc-exp" id="frmCCExp" required placeholder="MM-YYYY" autocomplete="cc-exp">
<input> is more frequently recommended (StackOverflow and tutorial examples), but I’m not sure if <select> StackOverflow example) is specifically a problem, or if it’s just more frequently implemented wrong. So what about the above <select> example breaks autofill, and how would you fix it?
Update: autocomplete isn't the problem
I’ve tested autocomplete="cc-exp”, and the form is still broken for Safari AutoFill, so my self-answer answer is wrong (or at least insufficient).
<select name="billing-cc-exp" id="billing-cc-exp" onfocus="methodSelect('pmt-gps')" autocomplete="cc-exp">
<option value="0322" selected="selected">03/2022</option>
<option value="0422">04/2022</option>
…
</select>
Look at the HTML autocomplete attribute on each of those form fields!
The form elements are not the problem here.
Your broken example has autocomplete=off, as dumb as that is for an expiration date field. The (presumably) working examples have some combination of autocomplete=cc-exp or cc-exp-month and cc-exp-year.
Fixed webform:
<label for="billing-cc-exp" class="inputLabelPayment">Expiration Date:</label>
<select name="billing-cc-exp" id="billing-cc-exp" onfocus="methodSelect('pmt-gps')" autocomplete="cc-exp">
<option value="03/2022" selected="selected">03/2022</option>
<option value="04/2022">04/2022</option>
<option value="05/2022">05/2022</option>
<option value="06/2022">06/2022</option>
…
</select>
There's nothing special about Safari going on here. Chrome looks to the same attribute (related post). Autofill can work without the attribute, as in this JSFiddle example, but autocomplete=off will break it!
Related
We need to update our forms to be accessibility compliant. I am looking for information on how to write an inline error for a form select. I have the form field labeled and have an inline error, but the readers do not announce the error.
Here is what we are using
<div class="select-wrapper">
<label for="securityQuestion" class="control-label bolded">Security Question</label>
<select id="securityQuestion" name="securityQuestion" class="form-control" aria-describedby="securityQuestion_error">
<option value="0">Select a Question</option>
<option value="10">What is your mother's maiden name?</option>
<option value="9">What's your town of birth?</option>
<option value="11">What is your father's middle name?</option>
<option value="12">What street did you live on when you were 10 years old?</option>
</select>
<div class="clear form-error-msg" id="securityQuestion_error"><span class="shop-icon icon" aria-label="Attention">r</span><span id="error-msg-text">Please select a security hint question.</span></div>
</div>
So if the user doesn't select an option and submits we dynamically inject an error just after the form field as shown above. This works fine for inputs and text boxes, but for the select, the reader skips it.
I been reading different blogs and specs and have read many times, don't use selects, but use radios or text boxes instead.
So any ideas?
Your issue might be linked to the following bug:
JAWS does not announce aria-describedby on select box in IE
This is also described on WebAim mailing list.
This is a bug, you have multiple alternatives to avoid this bug :
including the error text in the label
ARIA21: Using Aria-Invalid to Indicate An Error Field
SCR18: Providing client-side validation and alert
Re-displaying a form with a summary of errors
Providing error notification as the user enters information
Including error notification information in the page title
For instance, you can use aria-labelledby to target both the label and the error text.
<div class="select-wrapper">
<div id="securityQuestion_label">Security Question</div>
<select id="securityQuestion" name="securityQuestion"
aria-labelledby="securityQuestion_label securityQuestion_error">
<option value="0">Select a Question</option>
<option value="10">What is your mother's maiden name?</option>
<option value="9">What's your town of birth?</option>
<option value="11">What is your father's middle name?</option>
<option value="12">What street did you live on when you were 10 years old?</option>
</select>
<div class="clear form-error-msg" id="securityQuestion_error">Error message</span></div>
</div>
Well, get got our answer. Selects are not consistently supported across screen readers/os/browser combinations. The code works correctly with Safari and voiceover. However, chrome and voice-over do not play nice 100%. Further testing, sadly using chrome vox with chrome doesn't even read text input inline errors.
After some research, we found this from WebAim :
Firefox works best with NVDA
Chrome & Internet Explorer with JAWS on Windows
Safari with VoiceOver
Edge with Narrator
I have a simple form with some select options that need to do stuff when the options are changed (create new form elements). This all works fine, however when a select option is chosen and the user clicks elsewhere on the page (either another form option or a blank area of the page) the text of the chosen option remains highlighted blue.
I've used select's before and not had this problem, however they weren't linked to the .change function. Is that something to do with why this is happening? Has anybody encountered this issue before? All help greaty appreciated! Code is below...
<div id="container1" class="form-group">
<label class="control-label">Select an option</label>
<div>
<select class="form-control" id="mySelect">
<optgroup label="A">
<option value="1A">Option1A</option>
<option value="2A">Option2A</option>
<option value="3A">Option3A</option>
<option value="4A">Option4A</option>
</optgroup>
<optgroup label="B">
<option value="1B">Option1B</option>
<option value="2B">Option2B</option>
<option value="3B">Option3B</option>
<option value="4B">Option4B</option>
</optgroup>
</select>
</div>
</div>
I've seen the issue brought up here
Remove Blue highlighting of option
However I don't think this quite describes my problem, as it seems to me that that person wants to remove the blue highlighting whilst using the form (hard to be 100% sure though). I don't mind the blue highlighting being there when using the form, I just want it to stop persisting when you stop using the form and do something else on the page.
UPDATE: Problem only seems to occur in Internet Explorer (tested versions 9, 10 and 11). Tested in Chrome and issue doesn't occur. Just to elaborate on the comments, the issue has nothing to do with JS (so I have removed the JQuery code and subsequent tags). The issue occurs when using optgroups in a select form. Loading the HTML outlined above into IE produces the error.
I have a dropdown in an Angular 2 project:
<div class="form-group">
<label for="vendors">Vendors</label>
<select class="form-control" id="vendor_id" name="vendor_id" [(ngModel)]="selectedVendor" (ngModelChange)="onVendorChange($event)" required>
<option *ngFor=" let vendor of vendors " [ngValue]="vendor"> {{vendor.business_name}} </option>
</select>
</div>
This works fine in Chrome, but when I open it in Safari, when the page is loaded it shows the first item as selected even if I didn't selected anything. However, if I click "Submit" it will show "This field is mandatory".
In Safari it shows the first item as selected, but actually it's not selected. How to fix this?
In fact, you may find that the accepted answer is insufficient. At least using Angular 5 and Safari, I have found that you must explicitly make the option undefined. In other words:
<option disabled selected value=undefined> --Select-- </option>
Otherwise, the option will simply be marked as disabled and Safari will continue to show that it has the first real option selected, when in fact it isn't (and can't be).
This is not an angular issue, this is the default behavior on safari/mobile safari. An easy solution/workaround is shown below.
If you add another option box such as:
<option disabled selected value> --Select-- </option>
Then your code becomes:
<div class="form-group">
<label for="vendors">Vendors</label>
<select class="form-control" id="vendor_id" name="vendor_id" [(ngModel)]="selectedVendor" (ngModelChange)="onVendorChange($event)" required>
<option disabled selected value> --Select-- </option>
<option *ngFor=" let vendor of vendors " [ngValue]="vendor"> {{vendor.business_name}} </option>
</select>
</div>
This way you cannot re-select the first "Select" box after the user has made a valid selection, answer taken from this answer.
Using "required" on a dropdown form element with a "disabled" selection works in Firefox to prevent users from submitting a form without selecting something from the dropdown list, but not in Chrome. Can you help?
<select id="topic" class="form-control" required="required">
<option disabled selected>select genre</option>
<option>All genres (whatever works)</option>
<option>boogers</option>
<option>cheese</option>
<option>dumplings</option>
</select>
This may work
<option selected="true" disabled="disabled">select genre</option>
src: How to show disable HTML select option in by default?
To get it working just add value="" to your default option. This answer provides some HTML5 documentation on the matter.
Can I apply the required attribute to <select> fields in HTML5?
I have a basic form like so:
<form id="test-form">
<select id="multi" name="mymulti" multiple required>
<option value="">Choose a different Option</option>
<option>Foo</option>
<option>Bar</option>
<option>Baz</option>
</select><br>
<select id="single" name="myselect" required>
<option value="">Choose a different Option</option>
<option>Foo</option>
<option>Bar</option>
<option>Baz</option>
</select> <br>
<input type="submit">
</form>
The key point here is two selects, both required, but one is multiple and the other is not.
If you choose the default options (note you actually have to click on them), and then submit the form, it will tell you that the single select is required, but not the multiple select.
I looked at the relevant portion of the html5 spec, and although there is some talk about how the required select interacts with placeholder elements, I don't see anything about how multiple+required behaves.
The above behaviour is only in Chrome, other browsers seem to behave the same for both types. My question is, why? It seems... inconsistent. I understand how to work around it with some javascript, just not why I would have to? Can anyone explain the rationale behind this?
Demo (remember to actually choose the placeholder options).
Chrome is acting right here. While implementation in FF is simply simpel. But chrome's implementation does not only follow the spec, it is also simply logic. If a mutliple or size > 1 select is used, there is no placeholder by definition. And without a selected attribute there is indeed nothing :checked (i.e.: selected) initially.
In case of a single select with size=1. The select > option:first-child with an empty value is the placeholder option. And a single select has always one option :checked/selected.
Here is a definition of placeholder option in JS: https://github.com/aFarkas/webshim/blob/gh-pages/src/shims/form-shim-extend.js#L88-94 and here a definition of valueMissing for select: https://github.com/aFarkas/webshim/blob/gh-pages/src/shims/form-shim-extend.js#L128-130