Open rdsedmundo opened 5 years ago
I agree that this would be a welcome change. I have been fighting with this for the last couple of days. It is a dealbreaker for our app because the autocomplete control overlays the react-select menu. We have resorted to forking the project, but it would be nice if this were supported natively.
As you can see, there's no way of configuring that property manually.
@rdsedmundo Yes, there is a possibility to configure it. It is hard coded as a prop to the Input
component, that is true. But this library offers in its current version the possibility to overwrite its internal components using its components framework.
You just have to overwrite the Input
component and overwrite the prop being passed to the component.
import Select, { components } from 'react-select';
const Input = ({ autoComplete, ...props }) => <components.Input {...props} autoComplete="new-password" />;
<Select
{ ... }
components={{
Input
}}
/>
We have resorted to forking the project, but it would be nice if this were supported natively.
@kylehurt-rkv Here is your native support, without forking the repository.
That's a smarter solution than what I did. I knew I could just overwrite the Input
, that's what I did for fixing it, but I just copied its source code originally and pasted on my codebase. I haven't thought about the possibility of just importing it from the package.
I still can see value of having it configurable though.
@Rall3n We actually tried that exact solution, but whenever the page would try to load, Chrome would get of memory errors and crash. We are supplying several other custom components into the Select component, so it may be possible that something we did on one of the other custom components was conflicting with custom input component. Or maybe we are doing something in a non-standard way. Here is our code with the addition of the custom input component. Chrome throws an out of memory error and never loads the page. I'm guessing there is a circular reference somewhere. ` import React from 'react'; import PropTypes from 'prop-types'; import RSelect from 'react-select'; import { withStyles } from '@material-ui/core/styles'; import Typography from '@material-ui/core/Typography'; import NoSsr from '@material-ui/core/NoSsr'; import TextField from '@material-ui/core/TextField'; import Paper from '@material-ui/core/Paper'; import MenuItem from '@material-ui/core/MenuItem'; import FormControl from '@material-ui/core/FormControl/FormControl'; import FormHelperText from '@material-ui/core/FormHelperText/FormHelperText'; import { remove } from 'react-icons-kit/fa/remove'; import { chevronDown } from 'react-icons-kit/fa/chevronDown'; import { Icon } from 'react-icons-kit'; import Tooltip from '@material-ui/core/Tooltip'; import { isErrorState } from './reduxFormHelper';
const styles = theme => ({
root: {
flexGrow: 1,
},
input: {
display: 'flex',
paddingTop: 2,
paddingBottom: 3,
},
valueContainer: {
display: 'flex',
flexWrap: 'wrap',
flex: 1,
alignItems: 'center',
},
noOptionsMessage: {
padding: ${theme.spacing.unit}px ${theme.spacing.unit * 2}px
,
},
singleValue: {
fontSize: 16,
},
placeholder: {
position: 'absolute',
left: 2,
fontSize: 16,
},
paper: {
position: 'absolute',
zIndex: 1,
marginTop: 0,
paddingTop: 0,
left: 0,
right: 0,
},
});
class Select extends React.Component { findOption() { const { input, options } = this.props; const value = input.value._id || input.value; return options.find(option => option.value === value); }
render() { const { classes, theme, fullWidth, label, id, placeholder, required, meta: { touched, error }, options, isReadOnly, input, } = this.props;
function NoOptionsMessage(props) {
return (
<Typography
color="textSecondary"
className={props.selectProps.classes.noOptionsMessage}
{...props.innerProps}
>
{props.children}
</Typography>
);
}
function inputComponent({ inputRef, ...props }) {
return <div ref={inputRef} {...props} />;
}
const Control = props => {
return (
<div className="app-input-group">
<FormControl
fullWidth={fullWidth}
error={isErrorState(touched, error)}
>
<TextField
error={isErrorState(touched, error)}
label={label}
id={id}
required={required}
InputProps={{
inputComponent,
inputProps: {
className: props.selectProps.classes.input,
inputRef: props.innerRef,
children: props.children,
...props.innerProps,
},
}}
{...props.selectProps.textFieldProps}
/>
<FormHelperText>{touched && error}</FormHelperText>
</FormControl>
</div>
);
};
function Option(props) {
return (
<MenuItem
buttonRef={props.innerRef}
selected={props.isFocused}
component="div"
style={{
fontWeight: props.isSelected ? 500 : 400,
}}
{...props.innerProps}
>
{props.children}
</MenuItem>
);
}
function Placeholder(props) {
return (
<Typography
color="textSecondary"
className={props.selectProps.classes.placeholder}
{...props.innerProps}
>
{props.children}
</Typography>
);
}
function SingleValue(props) {
return (
<Typography
className={props.selectProps.classes.singleValue}
{...props.innerProps}
>
{props.children}
</Typography>
);
}
function ValueContainer(props) {
return (
<div className={props.selectProps.classes.valueContainer}>
{props.children}
</div>
);
}
function Menu(props) {
return isReadOnly ? null : (
<Paper
square
className={props.selectProps.classes.paper}
{...props.innerProps}
>
{props.children}
</Paper>
);
}
function ClearIndicator(props) {
const {
innerProps: { ref, ...restInnerProps },
} = props;
return (
<div
{...restInnerProps}
ref={ref}
className="app-select-clear-ind-container"
>
<Tooltip title="Clear">
<Icon icon={remove} className="app-select-clear-ind" />
</Tooltip>
</div>
);
}
function DropdownIndicator(props) {
return (
<div className="app-select-dd-ind-container">
<Icon className="app-select-dd-ind" icon={chevronDown} />
</div>
);
}
function IndicatorsContainer(props) {
return isReadOnly ? null : (
<div className="app-select-ind-container">{props.children}</div>
);
}
function IndicatorSeparator(props) {
return <span className="app-select-ind-sep" {...props.innerProps} />;
}
const Input = ({ autoComplete, ...props }) => (
<components.Input {...props} autoComplete="new-password" />
);
const components = {
Control,
Menu,
NoOptionsMessage,
Option,
Placeholder,
SingleValue,
ValueContainer,
DropdownIndicator,
ClearIndicator,
IndicatorsContainer,
IndicatorSeparator,
Input,
};
const selectStyles = {
input: base => ({
...base,
color: theme.palette.text.primary,
'& input': {
font: 'inherit',
},
}),
};
return (
<div className={classes.root}>
<NoSsr>
<RSelect
isClearable
classes={classes}
styles={selectStyles}
isDisabled={isReadOnly}
textFieldProps={{
InputLabelProps: {
shrink: true,
},
}}
options={options}
components={components}
value={this.findOption()}
onChange={
!isReadOnly
? option => input.onChange(option ? option.value : null)
: null
}
placeholder={placeholder}
openMenuOnClick={!isReadOnly}
/>
</NoSsr>
</div>
);
} }
Select.defaultProps = { fullWidth: true, };
Select.propTypes = { classes: PropTypes.object.isRequired, theme: PropTypes.object.isRequired, };
export default withStyles(styles, { withTheme: true })(Select);
`
This the debugger window Chrome throws up.
@kylehurt-rkv If I´m seeing this correctly, you are creating the custom components inside your render
function? This could be the source of your problem.
Creating the components inside the render
causes a complete rerender, because with each call of render
the variables are recreated. Try declaring the components outside the render
function (I would recommend outside of the class if you can, else inside the class).
@Rall3n Turns out I was right. I WAS doing something in a non-standard way. Moving the custom components outside of the class took care of the issue I was having with Chrome crashing. Makes sense now that I know the answer. Thank you very much for your insight.
Seems like there's a good reason to have this autoComplete
configurable, as based on the age and responses of https://github.com/JedWatson/react-select/pull/2395
I have a similar problem in #4006 : I am looking for a way to make sure that the Dashlane autofill icon does not get active in my AsyncComponent which results in a crash of the Chrome browser. Dashlane support hasn't been helpful so far, so if anybody of you has an idea on how to lock Dashlane out of my AsyncComponent, i'd be happy to hear!
This seems somewhat unnecessary given the existing component api as Rall3n has already mentioned.
Here you can already pass in an autoComplete
prop to the Select and have it rendered in a custom Input component.
Note: This can be applied to any prop you want to apply to the Input
Working demo: codesandbox
const Input = (props) => {
const { autoComplete = props.autoComplete } = props.selectProps;
return <components.Input {...props} autoComplete={autoComplete} />;
};
const MySelect = (props) => (
<Select components={{ Input }} autoComplete="new-password" options={options} />
);
This really needs to be added
Greetings all,
It seems that Google has perhaps changed their stance on this and per the top answer here, autocomplete=off
appears to now be working as expected. Can anyone confirm if this is the case or find any documentation supporting this?
In case this isn't correct, I have filed the following comment in the relevant the Chromium bugs thread: https://bugs.chromium.org/p/chromium/issues/detail?id=587466#c591
Greetings all,
It seems per the above stackoverflow post and in my own testing that newer versions of Chrome do appear to respect "autocomplete=off". If anyone is experiencing any differently, please provide a codesandbox example so we can reproduce and investigate further.
If anyone needs or wants to change this attribute on the Input, this is already possible as provided here: https://github.com/JedWatson/react-select/issues/3500#issuecomment-748568931
As such I will be closing this issue, but happy to re-open if we can confirm that this is still an issue.
Looked into this further and several users are still experiencing autoComplete from Chrome. I will reopen this.
This is still a problem in safari and setting custom input component and autoComplete="new-password"
doesn't always fix it.
It may have something to do with situational rendering
Wrapping with this works
<div className={showingMenu ? "": "hidden"}>
and hidden is display: none;
Wrapping with this does not work
{showingMenu &&
edit:
name: search
seems to work better
https://stackoverflow.com/a/30873633
<Input
{...commonProps}
autoCapitalize="none"
autoComplete="off"
autoCorrect="off"
id={id}
innerRef={this.getInputRef}
isDisabled={isDisabled}
isHidden={inputIsHidden}
onBlur={this.onInputBlur}
onChange={this.handleInputChange}
onFocus={this.onInputFocus}
spellCheck="false"
tabIndex={tabIndex}
form={form}
type="text"
value={inputValue}
{...ariaAttributes}
/>
I see that search input is hardcoded to type="text"
. If I change it to type="search"
- it solves issue with browser autofill.
Currently, the default Input component is forcefully setting
autoComplete="off"
which doesn't disable Chrome's autofill functionality on latest browser versions. For achieving that, we need to passautoComplete="new-password"
.The problem is that the value is hardcoded and can't be configured unless we implement our own Input component and configure this property properly there.
It's hardcoded here: https://github.com/JedWatson/react-select/blob/ba76246a92fe9371b5d4f8795d30119b045dcaba/src/Select.js#L1401
And it gets passed to the default Input component here: https://github.com/JedWatson/react-select/blob/ba76246a92fe9371b5d4f8795d30119b045dcaba/src/components/Input.js#L53
As you can see, there's no way of configuring that property manually.