antd Select turn off autocomplete - reactjs

I am trying to turn off autocomplete on an ant design Select but nothing I try works. This is obviously problematic as chromes (only one tested at this point) autocomplete completely covers the Select Options (Image below).
I am using antd in React and have tried the following on both the Select tag and Form tag:
autoComplete="off"
autoComplete="nope"
autoComplete="business-state"
and none of them seem to turn it off.
Here is a link to a code sandbox with almost the same code but the problem is it does not reproduce the same issue. For some reason the exact same code on sandbox doesn't show the autocomplete. I added an email input to show to test if autocomplete works on that and sure enough it does. I am at a loss for why this is working differently in sandbox than from my server.
https://codesandbox.io/s/wovnzpl9xw
Here is what it looks like when a user is typing to search the Options
Here is what it should look like (it only looks like this on focus but as soon as a user types chrome shows autocomplete)

Figured out a solution to my question, thanks to #trkaplan for pointing me in the right direction. Not the most elegant solution I am guessing so if anyone else has a better way to implement this I am all ears. I essentially had to create an onFocus method for the Select that grabs all of the elements with class ant-select-search__field loops through them and utilize setAttribute to change the autocomplete attribute to an arbitrary value in order to disable it.
onFocus={() => {
if (!this.state.autocompleteDisabled) {
let i;
const el = document.getElementsByClassName(
"ant-select-search__field"
);
for (i = 0; i < el.length; i++) {
el[i].setAttribute(
"autocomplete",
"registration-select"
);
}
this.setState({ autocompleteDisabled: true });
}
}}

I have applied to add the autocomplete="none" into the Select and it is looking fine.
<Select
showSearch
optionFilterProp="children"
onChange={onChange}
onFocus={onFocus}
onBlur={onBlur}
onSearch={onSearchZipCode}
filterOption={(input, option) => option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
placeholder="Choose a City"
autoComplete="none"
// disabled={true}
>
{cities.map((city) => (
<Select.Option key={city.id} value={city.id}>
{city.name}
</Select.Option>
))}
</Select>;

You could also use AutoComplete instead of Select, because with this it's possible to change the underlying Input
<AutoComplete ... >
<Input autoComplete='off' id='myId' />
</AutoComplete>
AutoComplete is "new" and intended to be used if you are fetching data for the input instead of the data being static, but essentially its just a copy of Select and could be used the same way.

Another thing that worked very well for me was the following:
<FormItem>
<Select
autoComplete="new-state"
{...otherProps}
/>
</FormItem>
The autoComplete prop currently isn't documented properly and they don't even cater for TS users properly.
But this worked, if you've got that new word in the autoComplete prop, Chrome (and hopefully other browsers) will ignore that field.
For TypeScript users that have justifiably strict type rules:
<Select
// eslint-disable-next-line #typescript-eslint/ban-ts-comment
// #ts-ignore
autoComplete="new-state"
{...otherProps}
/>

You have to set filterOption to false
See this code sandbox

The only "clean" way I found to have no autocomplete when the label of the input is supposed to be aucompleted according to chrome (see here: Which Attributes Does Chrome Autofill Expect?) is to modify the labels by inserting invisible character ‍ in the label
<Form.Item label={<>Cou‍ntry</>}>
for example will be interpreted as
<Form.Item label={<>Cou‍ntry</>}>
But chrome does not recognize it as a Country input field
In my project I had dynamic inputs so the solution was (using _.times):
<Form.Item key={id} label={_.times(name.length, num => <>{tag.name.charAt(num)}‍</>)}>
Hacky but future proof (I hope)

Going to the FormItem component you can set the name props to "stateEnum" and then your browser won't just assume the field name from the label.
It works nicely for me on Google Chrome.
Example:
<FormItem label="State" name="stateEnum">
...
</FormItem>

Related

React: How to tell if Form is Valid/Invalid

How do I tell if a Form is Valid / Invalid in React?
Angular has this syntax on Formbuilders.
this.form.valid;
I am using this coding syntax. Curious if anything exists in the React library?
Currently using Material UI Library.
Right now, I am doing if else statements and error checking all 10 fields. Looking for shorthand method.
https://onestepcode.com/creating-a-material-ui-form/
<form onSubmit={handleSubmit}>
<Grid container alignItems="center" justify="center" direction="column">
<Grid item>
<TextField
id="name-input"
name="name"
label="Name"
type="text"
value={formValues.name}
onChange={handleInputChange}
/>
</Grid>
<Grid item>
<TextField
id="age-input"
name="age"
label="Age"
type="number"
value={formValues.age}
onChange={handleInputChange}
/>
I'd recommend using a library called Formik. It takes a bit of time to learn, but it's a really powerful library, and I use it all the time now (with MUI).
As far as i understood your problem, you want to validate the form.
Which can be done by checking if the states are valid or not.
function handleSubmit(e){
e.preventDefault(); // to stop the form submission refresh the page
// now you can check the the validation part
// here are some sample validation that will check if the uername has 5
// characters or not and checks if the age is greater than 18 or not.
// validations
if(formValues.name.length < 5 ) return;
if(formValues.age < 18) return;
//if the code reaches this point then it is valid form
sendToDb();
//similar more functions or statements can be called
}
By checking the state value in the submission of the form it can be
validated.
The above mentioned way is the manual way but if you want to validate it using a single line validation by using some third party liberary, then this is the solution that i would likely go with.
I found this package in npmjs it works fine. This is how you can use it.
1. Install the package.
npm install react-native-input-validator
2. Usage:
import TextInput from "react-native-input-validator";
<TextInput type="email" ref={someReference}/>
// check the value is valid or not in the submission of the form by using
//[reference].isValid() method
someReference.isValid();
Hope it helps thank you.
for more reference check the package and see the use in more details in the examples.
package : https://www.npmjs.com/package/react-native-input-validator
To tell if a form content is valid or not - regardless the framework - you can simply use the following:
const handleSubmit = (e) => {
e.preventDefault();
const formElement = e.target;
const isValid = formElement.checkValidity();
// add more logic here
}
...
<form
action={action}
onSubmit={handleSubmit}
className={style.form}
>
<input type='email' name='email' />
<input type='number' name='age' required />
</form>
This will use the built-in validation function and will return true if the email is correct and the age is provided.
Please note that email is not 'required', i.e. an empty value is considered correct.
I just wrote an article where I discuss exactly this: form validation/submission using built-in validation API.
No need to install any package!
https://medium.com/p/491327f985d0

Browser autocomplete issue

I am having a hard time trying to find a proper way to disable autocomplete from browser in antd forms.
In normal form inputs
<Input autoComplete="none" />
works perfectly.
the problem is that in Select and Autocomplete components it does not work, it does not accept this prop, the question is:
is it posible to disable browser autocomplete in the whole form?, I have been browin for hours for an answer to this issue, and so far all I found is that it is not posible, but just want to give it last try asking here.
Thanks a lot
I guess there is, Set autoComplete 'off' to the entire form.
const handleSubmit(e) {
e.preventDefault();
//... Submit Actions
}
return (
<form autoComplete='off' onSubmit={handleSubmit}>
// ... form contents ...
</form>
)

React autoFocus attribute is not rendered

I'm trying to render an <input> field with autofocus:
<input type="text" autoComplete="off" autoFocus={true} className="form-control" />
But it's being rendered as:
<input type="text" autocomplete="off" class="form-control">
And the input does not focus.
Why is that? How can I get the autofocus attribute to render?
This is expected, actually. React will manually call focus() on the relevant element, but it will not add the attribute itself.
Here is a quote from Dan Abramov from a ticket response from ~2 years ago:
This is intentional because it works very differently in different browsers. So instead of actually setting a DOM attribute, we polyfill its behavior in JavaScript.
Also, from another thread:
Chrome respects dynamically added elements with autoFocus if there hasn’t been one before. Even creating an input with autoFocus, adding it to the document, and removing it in the next tick is enough to disable autofocusing of any elements added in the future in Chrome.
Firefox just doesn’t care about any dynamically added elements with autoFocus at all.
And Safari always respects them.
That being said, you could still force the attribute with autofocus="true" instead of autoFocus={true} but it might not actually work in a reliable fashion. After all, there is a reason the React team polyfilled this.
In other words, if you want a reliable, consistent cross-browser behavior use autoFocus, if you must have the native attribute you can use autofocus="true", but know that you'll be at the mercy of letting the browser decide when and how said element will be focused.
You can try using a ref, and setting the focus when your component is ready.
const YourComponent = (props) => {
const inputEl = useRef(null);
useEffect(() => {
inputEl.current.focus();
}, []);
return <div>
<input autofocus="true" ref={inputEl} />
</div>;
}
Answer by Brandon works perfectly. Additionally, if you want to autofocus on an input on a Modal for example, just keep track of the modal state and use that to focus. For example:
const refModal = useRef(null);
useEffect(() => {
if(modalOpen) {
refModal.current.focus();
}
}, [modalOpen]);

React input - cursor jump to the end

I'm using this package react-phone-number-input
Context
I've this phone number field
<InputPhone
{...input}
value={input.value || ''}
placeholder={intl.formatMessage(
placeholder ? messages[placeholder] : messages.placeholder,
)}
style={{
borderColor: meta && meta.touched && meta.error && 'red',
}}
tabIndex={index}
size={size}
/>
This is inside a functional component, I cannot use another textInput because we use this little component in multiple forms plus it has special function inside it, like the style and the placeholder.
Problem
The problem is linked to this package react-phone-number-input: the caret jump to the end if i try to edit a number in the firsts two portions.
Someoneknow how can i fix it since the function SmartCaret of react-phone-number-input was disabled ?
Take a look at this issue - sounds like your problem.
You could try out the Smart Caret feature - the last item on the docs page. Keep in mind it might have limitations on some Android devices.
import SmartInput from 'react-phone-number-input/smart-input'
<PhoneInput
inputComponent={ SmartInput }
placeholder="Enter phone number"
value={ this.state.value }
onChange={ value => this.setState({ value }) }/>
Hope it helps!
If this doesn't work, a minimal, reproducible example would be helpful, like Dupocas suggested.

Convenient way to mark a complete form as readonly

I have an antd form with multiple form items and try to find a way to mark the complete form as readonly. I could for sure set each input component to 'disabled' but I wonder if there is a convenient way to do so on the form via an API call that I do not know yet.
Wrapping the antd form inside a fieldset and setting this to 'disabled' works pretty well.
<fieldset disabled={editorDisabled}>
<Form>
...
<Form/>
<fieldset/>
I don't see such an option in the form api, and I think it's the rare use case, so I doubt it exists. However, you can simply add variable which will track the disabled status, i.e.:
const YourAwesomeComponent = (props) => {
const disabled = someLogicToCalculateTheDisabledStatus(props);
return <Form ...>
<Input disabled={disabled} ... />
<Select disabled={disabled} ... />
<Button disabled={disabled} ... />
</Form>
}
Hope it helps.
As of version 4.21.0 (Jun 6, 2022) the disabled prop can be used in the form to disable all fields, i.e.:
<Form disabled={true}>
...
</Form>
It is enforced as long as a <Form.Item/> isn't explicitly marked as not disabled with disabled={false}. You can see the reference in antd docs here.

Resources