Browser autocomplete issue - reactjs

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>
)

Related

Can't get formik validation to work with react-router

Good morning,
I want a react-router link to forward ONLY when the form has no errors, unfortunately the code that's below does forward before the form is even validated so no error shows up and so on. Can you please guide me on how to fix this, so that the form is validated and if it has no errors, the link forwards further?
Here's my code:
<Link to={this.props.formikProps.isValid?'mainMenu': 'itemDetail'}>{!this.props.disabled && <button className="buttons-panel__button" type="button" onClick={() => (this.props.handleSubmit(false), this.props.formikProps.isValid? '' : this.onValidationFail())} >Save</button>}</Link>
The method is(it's basically only to display a popup error, and it's working):
onValidationFail() {
setAlertMessage("You need to fill all mandatory fields")
}
So far the best I've achieved is that it works as intended in every case, but if the form hasn't been touched at all. I've tried several different ways, including formValidate from formik, for some reason it didn't work too.
I'm looking forward to some tips/hints/solutions on the case.
I think that your solution looks bit overcomplicated. Maybe just use simple form submit, and after form submission redirect user to route.
It would look like that:
import { Formik, Form, Field } from 'formik'
class MyForm {
render() {
return (
<Formik
initialValues={...}
onSubmit={() => {this.props.history.push('/go-somewhere')}}
>
<Form>
<Field name="firstName" type="text" />
<button type="submit">Submit</button>
</Form>
</Formik>
)
}
}

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]);

Autofocus on reactstrap alerts using react functional component

I am using react hooks for my frontend designs and while creating a register form I have used various validations and I am depicting errors using reactstrap warning alerts.
And things are working fine but when focus is not implemented on these alers means when my page shows any of alert, it doesn't focus on that automatically.
I have tried basic codes for autofocus/ autoFocus or Focus() but nothing is working as per need.
My alert code look as shown below:
{
showAlreadyRegisteredAlert?
<Alert variant="warning" onClose={() => setShowAlreadyRegisteredAlert(false)} dismissible>
<p className="mb-0">
{content}
</p>
</Alert>
:null
}
I am just writing these alert codes in between my form inputs and whenever I need to call any of them I simply setValue for the commponent and alert box is called but still it lacks autofocus.
Any help will be appreciated. Thanks in advance!
I found the desired solution as I wanted my page should automatically focused on appearing alert boxes. I searched react-hooks official documention and get to know that we can use "useRef" for the purpose and below is my code for better understanding and clarification:
First: import useRef from react.
import React, {useState, useRef} from "react";
Second: create const with desired name using useRef as null.
const inputUser = useRef(null);
Third: set focus on your ref const after alert.
setShowAlreadyRegisteredAlert(true);
inputUser.current.focus();
Fourth: pass ref as const which you defined in step 2 inside your input field.
ref= {inputUser}

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.

antd Select turn off autocomplete

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>

Resources