How can I set the textfield as disabled and when typed, it will be enabled again? - reactjs

How can I code this where the textfield's original state will be disabled and then when typed in, it will be enabled. Then that textfield will be the only one be updated when submitted?
<form onSubmit={handleSubmit}>
<TextField
id="input"
margin="dense"
type="text"
label="Name"
placeholder={user.displayName}
value={displayName}
fullWidth
onChange={(e) => setdisplayName(e.target.value)}
/>
<TextField
disabled
margin="dense"
type="text"
label="address"
value={address}
fullWidth
onChange={(e) => setAddress(e.target.value)}
/>
<Button type="submit">Update</Button>
</form>

Even though you disable one input, It still re-render everytime you typing (because you setState on change). You can use ref like this to prevent unnecessary render.
const nameRef = useRef(null);
const addressRef = useRef(null);
const handleSubmit = (e) => {
e.preventDefault();
console.log(nameRef.current.value);
console.log(addressRef.current.value);
};
return (
<div>
<form onSubmit={handleSubmit}>
<TextField
id="input"
margin="dense"
type="text"
label="Name"
placeholder={user.displayName}
fullWidth
inputRef={nameRef}
/>
<TextField
margin="dense"
type="text"
label="address"
fullWidth
inputRef={addressRef}
/>
<Button type="submit">Update</Button>
</form>
)

You can add a validation on handleSubmit because if a textfield is disabled, you need another action to make it enable and it's not ok for the user also.
You can try to add something like:
const handleSubmit = () => {
if ((displayName === "" || displayName == null) && (address == "" || address === null) {
//show error for user that both fields have to be completed
} else {
//do the form submit
}
}

Related

Close input textfield on value change

I have the following problem: I have an input textfield and scanning a barcode. But the textfield will not close automatically. If I enter the numbers by keyboard it will close automatically. Did I something wrong? Is the scanner to fast? Any idea?
const [open, setOpen] = useState(false);
const onValueChange = (event) => {
if(event.target.value.length===16){
setOpen(false);
}
};
<TextField autoFocus onChange={onValueChange} margin="dense" id="number" type="text" inputProps={{minlength: 16,maxlength:16}} fullWidth variant="outlined" />
Do this:
<TextField autoFocus
onChange={onValueChange}
margin="dense"
id="number"
type="text"
inputProps={{minlength: 16,maxlength:16}}
fullWidth
variant="outlined"
onBlur={() => setOpen(false)} /* NEW */
/>
It seems that at the scanner is adding a LF character at the end of the input

How to clear input fields after submit in react

so i'm creating my portfolio and i am now on the final page, the contact page. I have it almost finished. I have it hooked up with emailjs and i receive emails with the message inputted as expected.
The problem i'm having is, when the form is submitted, i don't know how to clear the UI input fields. I could disregard using e.preventDefault(), however, i would like to keep that, as i want to style the page if the desired result has been achieved(message sent), or if an error has occurred. I would like to mention that i had used state for the name, email and message beforehand, however, i was unable to use the state variables in conjunction with the emailjs syntax, more specifically, with the "e.target" section. When the form is submitted, the result is the message being sent to my email, with the text inputted by the user still in the input fields.
The code is below, with some names left as hidden for privacy reasons:
import React, { useState } from 'react'
import { Box, Grid, Typography, Button} from '#material-ui/core'
import Navbar from './Navbar';
import Styles, { InputField } from './Styles'
import SendIcon from '#material-ui/icons/Send'
import emailjs from 'emailjs-com'
function Contact() {
const classes = Styles()
function sendEmail(e) {
e.preventDefault()
emailjs.sendForm('gmail', 'hidden', e.target, 'hidden')
.then((result) => {
console.log(result.text);
result.text ==="OK" ? console.log("it worked") : console.log("didnt work")
}, (error) => {
console.log(error.text);
});
}
return (
<Box component='div'>
<Navbar/>
<Grid container justify='center'>
<Box component='form' className={classes.contactContainer} onSubmit={sendEmail}>
<Typography variant='h5' className={classes.contactHead}>Contact Me</Typography>
<InputField
id="name"
name="name"
fullWidth={true}
label="Name"
variant="outlined"
margin='dense'
size='medium'
/>
<br/>
<InputField
id="email"
name="email"
fullWidth={true}
label="Email"
variant="outlined"
margin='dense'
size='medium'
/>
<br/>
<InputField
id="message"
name="message"
fullWidth={true}
label="Enter Message Here"
multiline
rows={8}
variant="outlined"
margin='dense'
size='medium'
/>
<br/>
<Button
type="submit"
variant='outlined'
fullWidth={true}
endIcon={<SendIcon/>}
className={classes.contactButton}>
Contact Me
</Button>
</Box>
</Grid>
</Box>
)
}
export default Contact
For the simplest way to do it in your code, use useState to declare initial value of the fields such as:
const [name, setName] = useState("");
Then you need to set the "value" param in your InputField component, eg:
<InputField
id="name"
name="name"
fullWidth={true}
label="Name"
variant="outlined"
margin='dense'
size='medium'
value={name}
/>
And after receiving the result in emailjs.sendForm, use setName to reset the value of the name field, eg:
setName("")
Use the similar method for other fields.
Thank you for the answer, it helped, however did not fully fix the problem. That being said, i was able to find a solution. I used the onChange param and passed through a function which changes the state AND the value. Also, after receiving the result in emailjs.sendForm, i reset the value of all the fields.
const handleChange = (event) => {
event.target.name=="name"
? setName(event.target.value)
: event.target.name=="email"
? setEmail(event.target.value)
: event.target.name=="message"
? setMessage(event.target.value)
: console.log("error")
};
function sendEmail(e) {
e.preventDefault()
emailjs.sendForm('gmail', 'hiddenForPrivacy', e.target, 'hiddenForPrivacy')
.then((result) => {
console.log(result.text);
result.text ==="OK" ? console.log("it worked") : alert("didnt work")
setName("")
setMessage("")
setEmail("")
}, (error) => {
console.log(error.text);
});
}
The input fields now look like this:
return (
<Box component='div'>
<Navbar/>
<Grid container justify='center'>
<Box component='form' className={classes.contactContainer} onSubmit={sendEmail}>
<Typography variant='h5' className={classes.contactHead}>Contact Me</Typography>
<InputField
id="name"
name="name"
fullWidth={true}
label="Name"
variant="outlined"
margin='dense'
size='medium'
onChange={(e) => handleChange(e)}
value={name}
/>
<br/>
<InputField
id="email"
name="email"
fullWidth={true}
label="Email"
variant="outlined"
margin='dense'
size='medium'
onChange={(e) => handleChange(e)}
value={email}
/>
<br/>
<InputField
id="message"
name="message"
fullWidth={true}
label="Enter Message Here"
multiline
rows={8}
variant="outlined"
margin='dense'
size='medium'
onChange={(e) => handleChange(e)}
value={message}
/>
<br/>
<Button
type="submit"
variant='outlined'
fullWidth={true}
endIcon={<SendIcon/>}
className={classes.contactButton}>
Contact Me
</Button>
</Box>
</Grid>
</Box>

ref value undefined ReactJs

i Used material Design For my login From but when i get console.log in onsubmitForm show ref value undefined...
In the following simple example, both this.UserEmail.value & this.UserPassword.value are undefined when the submit is clicked.
export default class SignIn extends React.Component {
UserEmail= null;
UserPassword=null;
onsubmitForm = (e) =>
{
e.preventDefault();
let EmailData = this.UserEmail.value;
let PassData = this.UserPassword.value;
let data = {EmailData,PassData}
console.log("this is the submit form function");
console.log(data); // I Get Data Obj Undefined
}
render(){
return (
<div>
<form>
<TextField
variant="outlined"
margin="normal"
required
ref={el => this.UserEmail = el}
id="email"
label="Email"
name="email"
autoComplete="email"
autoFocus
/>
<TextField
variant="outlined"
margin="normal"
fullWidth
ref={el => this.UserPassword = el}
name="password"
label="Password"
type="password"
id="password"
autoComplete="current-password"
/>
<Button
type="submit"
onClick={this.onsubmitForm}
variant="contained"
color="primary"
>
Login
</Button>
</form>
</div>
);
}
}
The value of the ref is undefined because for Material-UI's API requires that you use inputRef instead of ref to access the input elements inside the nested components.
export default class SignIn extends React.Component {
onsubmitForm = e => {
e.preventDefault();
const email = this.email.value;
const password = this.password.value;
let data = { email, password };
console.log("this is the submit form function");
console.log(data);
};
render() {
return (
<div>
<form>
<TextField
variant="outlined"
margin="normal"
required
inputRef={email => (this.email = email)}
id="email"
label="Email"
name="email"
autoComplete="email"
autoFocus
/>
<TextField
variant="outlined"
margin="normal"
fullWidth
inputRef={password => (this.password = password)}
name="password"
label="Password"
type="password"
id="password"
autoComplete="current-password"
/>
<Button
type="submit"
onClick={this.onsubmitForm}
variant="contained"
color="primary"
>
Login
</Button>
</form>
</div>
);
}
}
Working example here

Why button's onClick event is triggered when i typing in TextField ReactJS

I have a sample code for Signing page as follows, When I am typing the username and passwords inside the text fields with every character the onClick event of the button is triggered and I can see the output of console.log(). Why it is triggered?
class Signin extends React.Component {
state = {
username: null,
password: null,
}
render () {
const { t, classes } = this.props;
return (
<div >
<div >
<div >
<Card>
<CardContent>
<form>
<TextField
inputProps={{ style:{fontSize:20, textAlign:'center', direction:'ltr'} }}
value={this.state.username}
onChange={e => this.setState({username: e.target.value})}
id="username"
label={t("Username")}
className={classes.textField}
fullWidth
margin="normal"
/>
<TextField
inputProps={{ style:{fontSize:20, textAlign:'center', direction:'ltr'} }}
value={this.state.password}
onChange={e => this.setState({password: e.target.value})}
id="password"
label={t("Password")}
className={classes.textField}
type="password"
fullWidth
margin="normal"
/>
<Button variant="raised" color="primary" fullWidth type="submit" onClick={console.log(this.state.username,this.state.password)} >{t("Login")}</Button>
</form>
</CardContent>
</Card>
</div>
</div>
</div>
);
}
}
Change your console.log from:
onClick={console.log(this.state.username,this.state.password)}
to like this below:
onClick={() => console.log(this.state.username,this.state.password)}
try this
it is happening because It depends on where exactly are you using the Arrow function. If the Arrow function is used in the render method, then they create a new instance every time render is called just like how bind would work.
<Button
variant="raised"
color="primary"
fullWidth type="submit"
onClick={()=>{console.log(this.state.username,this.state.password)} >{t("Login")}}</Button>

How to get input value of TextField from Material UI without using onChange event?

I tried to use this.refs.myField.getValue() or this.refs.myTextField.input.value. But, they are depreciated.
I don't want to use onChange inside TextField, I just convert the text when clicking button Convert
import React from 'react';
import TextField from '#material-ui/core/TextField';
import Button from '#material-ui/core/Button';
class Test extends React.Component {
constructor(props) {
super(props);
this.state = {
text: '',
};
};
handleConvertString = (event) => {
let str = this.refs.myField.getValue();
this.setState({
text: str.replace(/[dog]/gi, ''),
})
};
render() {
return (
<div>
<TextField
ref="myField"
fullWidth
/>
<Button variant="outlined" href="#outlined-buttons" onClick={this.handleConvertString}>
Convert
</Button>
<h1>{this.state.text}</h1>
</div>
)
}
}
export default Test;
Take a look at the MUI text field API docs.
You are trying to access the underlying value of the text area, so you need the ref of the HTML DOM element.
For the text area, use:
<TextField
inputRef={ref => { this.inputRef = ref; }}
fullWidth
/>
And then in your method access the value with this.inputRef.value.
const { register, handleSubmit } = useForm();
<form onSubmit={handleSubmit(formSubmit)}>
<label>
<TextField
id="outlined-basic"
label="email"
name="email"
fullWidth
variant="outlined"
inputRef={register}
required
/>
</label>
<br />
<label>
<br />
<TextField
id="outlined-secondary:cyan"
label="password"
name="password"
type="password"
fullWidth
variant="outlined"
inputRef={register}
required
/>
</label>
<br />
<br />
<Button
className={classes.root}
variant="contained"
color="primary"
fullWidth
type="submit"
>
Login
</Button>
</form>
Then handling it with :
const formSubmit = (data) => {
// Post Data
const postData = {
email: data.email,
pass: data.password,
};
console.log(data)

Resources