Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds support for browser autofill #2174

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,46 @@ function onInputKeyDown(event) {
/>
```

### Supporting browser autofill

Add the `autoComplete` prop to your select. Please notice that this feature is ignored for a Multiselect. The `autosize` prop should be set to `false` because autosize will shrink the input so the clickable area to trigger autofill suggestions does not expand over the whole select field.

The value for `autoComplete` should be from [this list of possible values](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-autocomplete).

Usage example:
```JS
<Select
id="country"
name="country"
autoComplete="country"
multi={false} //required with autoComplete
autosize={false} //recommended with autoComplete
options={COUNTRIES}
onAutoFill={this.handleAutoFill}
//... other props
/>
```

Example for credit card expiry date selects:
```JS
<Select
autoComplete="cc-exp-month"
multi={false} //required with autoComplete
autosize={false} //recommended with autoComplete
//... other props
/>
<Select
autoComplete="cc-exp-year"
multi={false} //required with autoComplete
autosize={false} //recommended with autoComplete
//... other props
/>
```

You can use the `onAutoFill` callback to react to autofill state changes, for example to adjust the styling of a wrapper component.

This feature is currently only tested in Chrome >= v63.

### Select Props

| Property | Type | Default | Description |
Expand All @@ -345,6 +385,7 @@ function onInputKeyDown(event) {
| `aria`-labelledby | string | undefined | HTML ID of an element that should be used as the label (for assistive tech) |
| `arrowRenderer` | function | undefined | Renders a custom drop-down arrow to be shown in the right-hand side of the select: `arrowRenderer({ onMouseDown, isOpen })`. Won't render when set to `null`
| `autoBlur` | boolean | false | Blurs the input element after a selection has been made. Handy for lowering the keyboard on mobile devices |
| `autoComplete` | string | undefined | Value to support autofill feature |
| `autofocus` | boolean | undefined | deprecated; use the autoFocus prop instead |
| `autoFocus` | boolean | undefined | autofocus the component on mount |
| `autoload` | boolean | true | whether to auto-load the default async options set |
Expand Down Expand Up @@ -381,6 +422,7 @@ function onInputKeyDown(event) {
| `multi` | boolean | undefined | multi-value input |
| `name` | string | undefined | field name, for hidden `<input />` tag |
| `noResultsText` | string | 'No results found' | placeholder displayed when there are no matching search results or a falsy value to hide it (can also be a react component) |
| `onAutoFill` | function | undefined | onAutoFill handler: `function(event) {}` |
| `onBlur` | function | undefined | onBlur handler: `function(event) {}` |
| `onBlurResetsInput` | boolean | true | Whether to clear input on blur or not. If set to false, it only works if onCloseResetsInput is false as well. |
| `onChange` | function | undefined | onChange handler: `function(newOption) {}` |
Expand Down
2 changes: 2 additions & 0 deletions examples/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ import NumericSelect from './components/NumericSelect';
import BooleanSelect from './components/BooleanSelect';
import Virtualized from './components/Virtualized';
import States from './components/States';
import AutoComplete from './components/AutoComplete';

ReactDOM.render(
<div>
<States label="States" searchable />
<AutoComplete label="AutoComplete" autoComplete="country" />
<Multiselect label="Multiselect" />
<Virtualized label="Virtualized" />
<Contributors label="Contributors (Async)" />
Expand Down
54 changes: 54 additions & 0 deletions examples/src/components/AutoComplete.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React from 'react';
import createClass from 'create-react-class';
import PropTypes from 'prop-types';
import Select from 'react-select';
import { COUNTRIES } from '../data/countries';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use module.exports = ... in that file (or export default?!) and import countries = ... here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I implemented it this way because other files in /data had the same structure

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok mark as resolved


var AutoCompleteField = createClass({
displayName: 'AutoCompleteField',
propTypes: {
label: PropTypes.string,
autoComplete: PropTypes.string,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you were a bit too eager here. The label prop is still in use.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right

},
componentDidMount() {
// reveal hidden input for testing
document.querySelector('[autocomplete="country"]').classList.remove('Select-hidden');
},
getInitialState () {
return {
selectValue: '',
};
},
updateValue (newValue) {
this.setState({
selectValue: newValue,
});
},
handleAutoFill (e) {
console.log(e);
},
render () {
return (
<div className="section">
<h3 className="section-heading">{this.props.label} <a href="https://github.com/JedWatson/react-select/tree/master/examples/src/components/AutoComplete.js">(Source)</a></h3>
<input placeholder="email (for testing autoComplete)" type="email" autoComplete="email" />
<Select
id="country"
ref="autoCompleteSelect"
multi={false}
autosize={false}
options={COUNTRIES}
simpleValue
name="country"
value={this.state.selectValue}
onChange={this.updateValue}
autoComplete={this.props.autoComplete}
onAutoFill={this.handleAutoFill}
/>
</div>
);
}
});


module.exports = AutoCompleteField;
245 changes: 245 additions & 0 deletions examples/src/data/countries.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
exports.COUNTRIES = [
{ label: 'Afghanistan', value: 'AF' },
{ label: 'Åland Islands', value: 'AX' },
{ label: 'Albania', value: 'AL' },
{ label: 'Algeria', value: 'DZ' },
{ label: 'American Samoa', value: 'AS' },
{ label: 'AndorrA', value: 'AD' },
{ label: 'Angola', value: 'AO' },
{ label: 'Anguilla', value: 'AI' },
{ label: 'Antarctica', value: 'AQ' },
{ label: 'Antigua and Barbuda', value: 'AG' },
{ label: 'Argentina', value: 'AR' },
{ label: 'Armenia', value: 'AM' },
{ label: 'Aruba', value: 'AW' },
{ label: 'Australia', value: 'AU' },
{ label: 'Austria', value: 'AT' },
{ label: 'Azerbaijan', value: 'AZ' },
{ label: 'Bahamas', value: 'BS' },
{ label: 'Bahrain', value: 'BH' },
{ label: 'Bangladesh', value: 'BD' },
{ label: 'Barbados', value: 'BB' },
{ label: 'Belarus', value: 'BY' },
{ label: 'Belgium', value: 'BE' },
{ label: 'Belize', value: 'BZ' },
{ label: 'Benin', value: 'BJ' },
{ label: 'Bermuda', value: 'BM' },
{ label: 'Bhutan', value: 'BT' },
{ label: 'Bolivia', value: 'BO' },
{ label: 'Bosnia and Herzegovina', value: 'BA' },
{ label: 'Botswana', value: 'BW' },
{ label: 'Bouvet Island', value: 'BV' },
{ label: 'Brazil', value: 'BR' },
{ label: 'British Indian Ocean Territory', value: 'IO' },
{ label: 'Brunei Darussalam', value: 'BN' },
{ label: 'Bulgaria', value: 'BG' },
{ label: 'Burkina Faso', value: 'BF' },
{ label: 'Burundi', value: 'BI' },
{ label: 'Cambodia', value: 'KH' },
{ label: 'Cameroon', value: 'CM' },
{ label: 'Canada', value: 'CA' },
{ label: 'Cape Verde', value: 'CV' },
{ label: 'Cayman Islands', value: 'KY' },
{ label: 'Central African Republic', value: 'CF' },
{ label: 'Chad', value: 'TD' },
{ label: 'Chile', value: 'CL' },
{ label: 'China', value: 'CN' },
{ label: 'Christmas Island', value: 'CX' },
{ label: 'Cocos (Keeling) Islands', value: 'CC' },
{ label: 'Colombia', value: 'CO' },
{ label: 'Comoros', value: 'KM' },
{ label: 'Congo', value: 'CG' },
{ label: 'Congo, The Democratic Republic of the', value: 'CD' },
{ label: 'Cook Islands', value: 'CK' },
{ label: 'Costa Rica', value: 'CR' },
{ label: 'Cote D\'Ivoire', value: 'CI' },
{ label: 'Croatia', value: 'HR' },
{ label: 'Cuba', value: 'CU' },
{ label: 'Cyprus', value: 'CY' },
{ label: 'Czech Republic', value: 'CZ' },
{ label: 'Denmark', value: 'DK' },
{ label: 'Djibouti', value: 'DJ' },
{ label: 'Dominica', value: 'DM' },
{ label: 'Dominican Republic', value: 'DO' },
{ label: 'Ecuador', value: 'EC' },
{ label: 'Egypt', value: 'EG' },
{ label: 'El Salvador', value: 'SV' },
{ label: 'Equatorial Guinea', value: 'GQ' },
{ label: 'Eritrea', value: 'ER' },
{ label: 'Estonia', value: 'EE' },
{ label: 'Ethiopia', value: 'ET' },
{ label: 'Falkland Islands (Malvinas)', value: 'FK' },
{ label: 'Faroe Islands', value: 'FO' },
{ label: 'Fiji', value: 'FJ' },
{ label: 'Finland', value: 'FI' },
{ label: 'France', value: 'FR' },
{ label: 'French Guiana', value: 'GF' },
{ label: 'French Polynesia', value: 'PF' },
{ label: 'French Southern Territories', value: 'TF' },
{ label: 'Gabon', value: 'GA' },
{ label: 'Gambia', value: 'GM' },
{ label: 'Georgia', value: 'GE' },
{ label: 'Germany', value: 'DE' },
{ label: 'Ghana', value: 'GH' },
{ label: 'Gibraltar', value: 'GI' },
{ label: 'Greece', value: 'GR' },
{ label: 'Greenland', value: 'GL' },
{ label: 'Grenada', value: 'GD' },
{ label: 'Guadeloupe', value: 'GP' },
{ label: 'Guam', value: 'GU' },
{ label: 'Guatemala', value: 'GT' },
{ label: 'Guernsey', value: 'GG' },
{ label: 'Guinea', value: 'GN' },
{ label: 'Guinea-Bissau', value: 'GW' },
{ label: 'Guyana', value: 'GY' },
{ label: 'Haiti', value: 'HT' },
{ label: 'Heard Island and Mcdonald Islands', value: 'HM' },
{ label: 'Holy See (Vatican City State)', value: 'VA' },
{ label: 'Honduras', value: 'HN' },
{ label: 'Hong Kong', value: 'HK' },
{ label: 'Hungary', value: 'HU' },
{ label: 'Iceland', value: 'IS' },
{ label: 'India', value: 'IN' },
{ label: 'Indonesia', value: 'ID' },
{ label: 'Iran, Islamic Republic Of', value: 'IR' },
{ label: 'Iraq', value: 'IQ' },
{ label: 'Ireland', value: 'IE' },
{ label: 'Isle of Man', value: 'IM' },
{ label: 'Israel', value: 'IL' },
{ label: 'Italy', value: 'IT' },
{ label: 'Jamaica', value: 'JM' },
{ label: 'Japan', value: 'JP' },
{ label: 'Jersey', value: 'JE' },
{ label: 'Jordan', value: 'JO' },
{ label: 'Kazakhstan', value: 'KZ' },
{ label: 'Kenya', value: 'KE' },
{ label: 'Kiribati', value: 'KI' },
{ label: 'Korea, Democratic People\'S Republic of', value: 'KP' },
{ label: 'Korea, Republic of', value: 'KR' },
{ label: 'Kuwait', value: 'KW' },
{ label: 'Kyrgyzstan', value: 'KG' },
{ label: 'Lao People\'S Democratic Republic', value: 'LA' },
{ label: 'Latvia', value: 'LV' },
{ label: 'Lebanon', value: 'LB' },
{ label: 'Lesotho', value: 'LS' },
{ label: 'Liberia', value: 'LR' },
{ label: 'Libyan Arab Jamahiriya', value: 'LY' },
{ label: 'Liechtenstein', value: 'LI' },
{ label: 'Lithuania', value: 'LT' },
{ label: 'Luxembourg', value: 'LU' },
{ label: 'Macao', value: 'MO' },
{ label: 'Macedonia, The Former Yugoslav Republic of', value: 'MK' },
{ label: 'Madagascar', value: 'MG' },
{ label: 'Malawi', value: 'MW' },
{ label: 'Malaysia', value: 'MY' },
{ label: 'Maldives', value: 'MV' },
{ label: 'Mali', value: 'ML' },
{ label: 'Malta', value: 'MT' },
{ label: 'Marshall Islands', value: 'MH' },
{ label: 'Martinique', value: 'MQ' },
{ label: 'Mauritania', value: 'MR' },
{ label: 'Mauritius', value: 'MU' },
{ label: 'Mayotte', value: 'YT' },
{ label: 'Mexico', value: 'MX' },
{ label: 'Micronesia, Federated States of', value: 'FM' },
{ label: 'Moldova, Republic of', value: 'MD' },
{ label: 'Monaco', value: 'MC' },
{ label: 'Mongolia', value: 'MN' },
{ label: 'Montserrat', value: 'MS' },
{ label: 'Morocco', value: 'MA' },
{ label: 'Mozambique', value: 'MZ' },
{ label: 'Myanmar', value: 'MM' },
{ label: 'Namibia', value: 'NA' },
{ label: 'Nauru', value: 'NR' },
{ label: 'Nepal', value: 'NP' },
{ label: 'Netherlands', value: 'NL' },
{ label: 'Netherlands Antilles', value: 'AN' },
{ label: 'New Caledonia', value: 'NC' },
{ label: 'New Zealand', value: 'NZ' },
{ label: 'Nicaragua', value: 'NI' },
{ label: 'Niger', value: 'NE' },
{ label: 'Nigeria', value: 'NG' },
{ label: 'Niue', value: 'NU' },
{ label: 'Norfolk Island', value: 'NF' },
{ label: 'Northern Mariana Islands', value: 'MP' },
{ label: 'Norway', value: 'NO' },
{ label: 'Oman', value: 'OM' },
{ label: 'Pakistan', value: 'PK' },
{ label: 'Palau', value: 'PW' },
{ label: 'Palestinian Territory, Occupied', value: 'PS' },
{ label: 'Panama', value: 'PA' },
{ label: 'Papua New Guinea', value: 'PG' },
{ label: 'Paraguay', value: 'PY' },
{ label: 'Peru', value: 'PE' },
{ label: 'Philippines', value: 'PH' },
{ label: 'Pitcairn', value: 'PN' },
{ label: 'Poland', value: 'PL' },
{ label: 'Portugal', value: 'PT' },
{ label: 'Puerto Rico', value: 'PR' },
{ label: 'Qatar', value: 'QA' },
{ label: 'Reunion', value: 'RE' },
{ label: 'Romania', value: 'RO' },
{ label: 'Russian Federation', value: 'RU' },
{ label: 'RWANDA', value: 'RW' },
{ label: 'Saint Helena', value: 'SH' },
{ label: 'Saint Kitts and Nevis', value: 'KN' },
{ label: 'Saint Lucia', value: 'LC' },
{ label: 'Saint Pierre and Miquelon', value: 'PM' },
{ label: 'Saint Vincent and the Grenadines', value: 'VC' },
{ label: 'Samoa', value: 'WS' },
{ label: 'San Marino', value: 'SM' },
{ label: 'Sao Tome and Principe', value: 'ST' },
{ label: 'Saudi Arabia', value: 'SA' },
{ label: 'Senegal', value: 'SN' },
{ label: 'Serbia and Montenegro', value: 'CS' },
{ label: 'Seychelles', value: 'SC' },
{ label: 'Sierra Leone', value: 'SL' },
{ label: 'Singapore', value: 'SG' },
{ label: 'Slovakia', value: 'SK' },
{ label: 'Slovenia', value: 'SI' },
{ label: 'Solomon Islands', value: 'SB' },
{ label: 'Somalia', value: 'SO' },
{ label: 'South Africa', value: 'ZA' },
{ label: 'South Georgia and the South Sandwich Islands', value: 'GS' },
{ label: 'Spain', value: 'ES' },
{ label: 'Sri Lanka', value: 'LK' },
{ label: 'Sudan', value: 'SD' },
{ label: 'Suriname', value: 'SR' },
{ label: 'Svalbard and Jan Mayen', value: 'SJ' },
{ label: 'Swaziland', value: 'SZ' },
{ label: 'Sweden', value: 'SE' },
{ label: 'Switzerland', value: 'CH' },
{ label: 'Syrian Arab Republic', value: 'SY' },
{ label: 'Taiwan, Province of China', value: 'TW' },
{ label: 'Tajikistan', value: 'TJ' },
{ label: 'Tanzania, United Republic of', value: 'TZ' },
{ label: 'Thailand', value: 'TH' },
{ label: 'Timor-Leste', value: 'TL' },
{ label: 'Togo', value: 'TG' },
{ label: 'Tokelau', value: 'TK' },
{ label: 'Tonga', value: 'TO' },
{ label: 'Trinidad and Tobago', value: 'TT' },
{ label: 'Tunisia', value: 'TN' },
{ label: 'Turkey', value: 'TR' },
{ label: 'Turkmenistan', value: 'TM' },
{ label: 'Turks and Caicos Islands', value: 'TC' },
{ label: 'Tuvalu', value: 'TV' },
{ label: 'Uganda', value: 'UG' },
{ label: 'Ukraine', value: 'UA' },
{ label: 'United Arab Emirates', value: 'AE' },
{ label: 'United Kingdom', value: 'GB' },
{ label: 'United States', value: 'US' },
{ label: 'United States Minor Outlying Islands', value: 'UM' },
{ label: 'Uruguay', value: 'UY' },
{ label: 'Uzbekistan', value: 'UZ' },
{ label: 'Vanuatu', value: 'VU' },
{ label: 'Venezuela', value: 'VE' },
{ label: 'Viet Nam', value: 'VN' },
{ label: 'Virgin Islands, British', value: 'VG' },
{ label: 'Virgin Islands, U.S.', value: 'VI' },
{ label: 'Wallis and Futuna', value: 'WF' },
{ label: 'Western Sahara', value: 'EH' },
{ label: 'Yemen', value: 'YE' },
{ label: 'Zambia', value: 'ZM' },
{ label: 'Zimbabwe', value: 'ZW' }
];
Loading