Prevent Page Reload When File Input Clicked - javascript

I appreciate anyone's response and suggestions. I have a react component that loads a form to edit a product. When the component is mounted, it will receive props from another function and I use these values within the prop as default value of the input fields in the form. I also have an input element that accepts uploading a file. When the file is selected, the component seems to be refreshing and setting other input fields to their default values. Here is my component:
<form onSubmit={handleSubmit}>
<div className="form-row">
<div className="col-md-4 mt-md-2">
<input
type="text"
className="form-control"
name="name"
placeholder="Name"
defaultValue={product!.name}
ref={register({
required: true,
pattern: /^[a-zA-Z ]*$/,
})}
/>
</div>
<div className="col-md-4 mt-2 mt-md-2">
<input
type="text"
className="form-control"
name="qty"
placeholder="Quantity"
defaultValue={product!.qty}
ref={register({ required: true, pattern: /^[0-9]+$/ })}
/>
</div>
</div>
<div className="form-row">
<div className="col-md-4 mt-2 mt-md-2">
<div className="input-group">
<div className="custom-file">
<input
type="file"
className="custom-file-input"
name="posImg"
id="img"
title="Add image to product if it is a menu item"
onChange={handleImg}
/>
<label
className="custom-file-label"
htmlFor="img"
aria-describedby="inputGroupFileAddon02"
>
{fileLabelState}
</label>
</div>
</div>
</div>
</div>
<div className="d-flex justify-content-end mt-2">
<button
type="submit"
className="btn zaad justify-content-end"
title="Submit product edit"
>
Update
</button>
</div>
</form>
The issue is when I choose the file and click on select, all the other input fields are reset to their default values. Here is my handleImg function:
const handleImg = (e: any) => {
e.preventDefault();
const file = e.target.files[0];
setFileLabelState(e.target.files[0].name);
setFile(file);
};
I have tried to work with the e.preventDefault(), but I have had no chance so far. Any suggestions on how I can go about this?
Thank you again.
EDIT:
I fixed the form handler and now here is my handleSubmit function:
const handleSubmit = (event: any) => {
event.preventDefault();
event.stopPropagation();
let editedProd = new FormData();
let isMenu: string = event.menuItemOption === "yes" ? "true" : "false";
editedProd.append("name", event.name);
editedProd.append("qty", event.qty);
editedProd.append("img", file);};

const handleSubmit = event => {
event.preventDefault();
let editedProd = new FormData();
let isMenu: string = event.menuItemOption === "yes" ? "true" : "false";
editedProd.append("name", event.name);
editedProd.append("qty", event.qty);
editedProd.append("img", file);};
}
try this answer note here i change (event: any) to event. this is working code from my project

Related

React JS on submit remove input fields and display "Thank You" only

My code has got 3 input fields i.e first name, last name, email and 1 useState to hold its value, I want to remove the div part containing all the input fields after i hit Sign up and display only Thank You
My code has got 3 input fields i.e first name, last name, email and 1 useState to hold its value, I want to remove the div part containing all the input fields after i hit Sign up and display only Thank You
Before signing up
AFter signing up
const Home = () => {
const [saveInput, setInput] = useState({
fname: '',
lname: '',
email: '',
});
const [message, setMessage] = useState('enter email');
const inputFields = (event) => {
const { value, name } = event.target;
setInput((preValue) => ({
...preValue,
[name]: value,
}));
};
const onSubmits = (event) => {
setMessage('thanks');
};
return (
<div className="homeMain">
<div className="row">
<img
className="home_img"
src="https://i.pinimg.com/originals/53/b5/d7/53b5d70023efa05ec6797b25df413b73.jpg"
/>
<h1 className="home_h1 text-center">Maryam's Restaurant</h1>
<Link
style={{
color: 'white',
textDecoration: 'inherit',
textAlign: 'center',
}}
to="/Restaurant"
className="home_button"
>
View Menu
</Link>
<h2 className="home_h2 text-center">
Binging with Babish is a cooking show dedicated to discovering what
the delectable (and occasionally horrible) foods from fiction actually
taste like.
</h2>
{receipeList.map((curElem) => (
<div className="home2Main">
<img className="home_img2" src={curElem.img} />
<p className="home2Mainp1">{curElem.h1}</p>
<p className="home2Mainp2">{curElem.date}</p>
</div>
))}
</div>
<homeMainDetails />
<div className="home4Main">
<h4>
<bold>Subscribe</bold>
<br />
<small>
Sign up with your email address to receive news and updates.
</small>
</h4>
<input
className="home4MainInput"
name="fname"
onChange={inputFields}
value={saveInput.fname}
type="text"
placeholder="First Name"
/>
<input
className="home4MainInput"
name="lname"
onChange={inputFields}
value={saveInput.lname}
type="text"
placeholder="Last Name"
/>
<input
className="home4MainInput"
name="email"
onChange={inputFields}
value={saveInput.email}
type="text"
placeholder="Email Address"
/>
<button onClick={onSubmits}>Sign Up</button>
<h4 className="home4Mainh4">
<small>{message}</small>
</h4>
</div>
</div>
);
};
export default Home;
You could use another state to indicate your submit state.
This way you can hold state value without affecting to the message state:
Use another state:
const [isSubmited, setIsSubmited] = useState(false);
Change that state when you submit:
const onSubmits = (event) => {
setMessage('thanks');
setIsSubmited(true);
};
Then render it conditionally:
{isSubmited ? (
<div className="home4Main">
...
</div>
) : message}
You can do it with a basic condition message !== "Thank you" like this:
<div className="home4Main">
{message !== "Thank you" && (
<>
<h4>
<bold>Subscribe</bold>
<br />
<small>Sign up with your email address to receive news and updates.</small>
</h4>
<input
className="home4MainInput"
name="fname"
onChange={inputFields}
value={saveInput.fname}
type="text"
placeholder="First Name"
/>
<input
className="home4MainInput"
name="lname"
onChange={inputFields}
value={saveInput.lname}
type="text"
placeholder="Last Name"
/>
<input
className="home4MainInput"
name="email"
onChange={inputFields}
value={saveInput.email}
type="text"
placeholder="Email Address"
/>
<button onClick={onSubmits}>Sign Up</button>
</>
)}
<h4 className="home4Mainh4">
<small>{message}</small>
</h4>
</div>
And update message
const onSubmits = (event) => {
setMessage('Thank you');
};
Create a useState that contains the value on the state of the form.
const [isSubmited, setIsSubmited] = useState(false);
Then use this value in the JSX to conditional render the elements you want to display.
isSubmitted ? <div> Thank You! </div> : <div> your form.... </div>
You can call setIsSubmited(true) when you submit the form.

How can I force re-render input fields in a form in React?

I am trying to create a form where the user can edit the information of a contact from a database and then save those changes. The form correctly loads and saves the information from the database, but when componentDidMount() loads the current information into the form fields, the fields don't re-render, causing both the template text (ie. Name, Email, etc) and the information loaded from the database to display on top of each other. Clicking any of the input fields causes the field that was clicked to render properly with the text displaying above the input field, rather than over the loaded text.
How can I force the form to rerender each field after the data has been loaded properly in componentDidMount()? I've tried forceUpdate() but it didn't work, and I haven't been able to find anyone else with this issue. I suspect it has something to do with me using the bootstrap styles wrong, but even after reading all of bootstrap's documentation I couldn't find anything related to my issue.
Here are a couple of screenshots to show the issue.
The form right after loading
The form after clicking the 'Name' field
Here's the relevant code for the component.
constructor(props) {
super(props);
this.state = {
name: "",
email: "",
role: "",
phone: "",
errors: {}
}
}
// Initializer: Copy contact's current data to state
componentDidMount() {
axios.get("/api/contacts/get/" + this.props.match.params.id)
.then(res => {
this.setState({ name: res.data.name });
this.setState({ email: res.data.email });
this.setState({ role: res.data.role });
this.setState({ phone: res.data.phone });
})
.catch(err => console.log(err));
this.forceUpdate();
}
// Change handler: Modify values when changed
onChange = e => {
this.setState({ [e.target.id]: e.target.value });
}
// Submit handler: Save changes to database
onSubmit = e => {
e.preventDefault();
const contact = {
name: this.state.name,
email: this.state.email,
role: this.state.role,
phone: stripNumber(this.state.phone)
};
// Post modified contact to database, then navigate back to Manage Contacts Dashboard
axios.post("/api/admin/contacts/update/" + this.props.match.params.id, contact);
window.location = PREVIOUS_URL;
}
render() {
const { errors } = this.state;
return (
<div>
<Link to={PREVIOUS_URL} className="btn-flat waves-effect">
<i className="material-icons left">keyboard_backspace</i> Back to Manage Contacts
</Link>
<h3>Edit contact</h3>
<form noValidate onSubmit={this.onSubmit}>
<div className="input-field col s12">
<input
onChange={this.onChange}
value={this.state.name}
error={errors.name}
id="name"
type="text"
className={classnames("", { invalid: errors.name })}
/>
<label htmlFor="name">Name</label>
<span className="red-text">{errors.name}</span>
</div>
<div className="input-field col s12">
<input
onChange={this.onChange}
value={this.state.email}
error={errors.email}
id="email"
type="email"
className={classnames("", { invalid: errors.email || errors.emailnotfound })}
/>
<label htmlFor="email">Email</label>
<span className="red-text">{errors.email}{errors.emailnotfound}</span>
</div>
<div className="input-field col s12">
<input
onChange={this.onChange}
value={this.state.role}
error={errors.role}
id="role"
type="text"
className={classnames("", { invalid: errors.role })}
/>
<label htmlFor="role">Role</label>
<span className="red-text">{errors.role}</span>
</div>
<div className="input-field col s12">
<input
onChange={this.onChange}
value={this.state.phone}
error={errors.phone}
id="phone"
type="tel"
className={classnames("", { invalid: errors.phone })}
/>
<label htmlFor="phone">Phone Number</label>
<span className="red-text">{errors.phone}</span>
</div>
<div className="form-group">
<input type="submit" value="Submit changes" className="btn btn-primary" />
<Link to={PREVIOUS_URL} className="btn btn-danger"> Cancel </Link>
</div>
</form>
</div>
)
}
}
Have you tried doing the data fetch inside componentWillMount()?

how to login in ReactJs?

how to login in ReactJS?
i am probably new to reactJS, so i have no idea about how to proper login in Reactjs. i tried something like below but that's not proper working.
it would be great if anybody could help me out for what i'm trying to do. thank you so much in advance.
login-api end point: http://localhost:8000/api/login
export default class App extends Component{
constructor(props) {
super(props);
this.state ={
username: "",
password: "",
}
this.onFormSubmit = this.onFormSubmit.bind(this)
}
onFormSubmit(values){
console.log(values);
const formData = new FormData();
formData.append("username", values.username);
formData.append("password", values.password);
const options = {
method: 'POST',
body: formData
};
fetch('http://localhost:8000/api/login', options).then(() => {
this.props.history.replace('/home')
}).catch((error) => {
console.log(this.props.state)
})
};
render(){
return(
<div>
<section class="login_part section_padding ">
<div class="login_part_form">
<Form onFinish={this.onFormSubmit}>
<div class="col-md-12 form-group p_star">
<Form.Item name="username">
<input type="text" class="form-control" placeholder="Username" required />
</Form.Item>
</div>
<div class="col-md-12 form-group p_star">
<Form.Item name="password">
<input type="password" class="form-control"
placeholder="Password" required />
</Form.Item>
</div>
<div class="col-md-12 form-group">
<button type="submit" value="submit" class="btn_3">
log in
</button>
</div>
</Form>
</div>
</section>
</div>
)
}
}
So, looking at your code, i do not really see you changing your state anywhere.
Looks like you lack some simple handlers, that will use setState method to modify the password and username in your state. You want to probably do it onChange of an input.
After that in your onFormSubmit function you want to get the values from your state and send those to the server.

How to write inside input after making it editable?

I Am populating values of my input field from JSON data what am getting from back-end, now there is an edit button on UI by on click on that button I am enabling my input field but not able to type inside as I am setting some value
I want to write inside the input once I have made them editable.
const { register, handleSubmit, errors } = useForm();
const [disabled, setdisabled] = useState(false);
const [editBtn, seteditBtn] = useState(true);
<form onSubmit={handleSubmit(onSubmit)}>
{editBtn === true && (
<div align="right">
<button
className="btn white_color_btn"
type="button"
onClick={edit}
>
Edit
</button>
</div>
)}
{editBtn === false && (
<button className="btn white_color_btn" type="submit">
Save
</button>
)}
<div className="row">
<div className="form-group col-6 col-sm-6 col-md-6 col-lg-4 col-xl-4">
<input
type="text"
disable
id="firstName"
name="firstName"
value={dataItems.firstname}
disabled={disabled ? "" : "disabled"}
ref={register({ required: true })}
/>
{errors.firstname && (
<span className="text-danger">first name required</span>
)}
<br />
<label htmlFor="emp_designation">First name</label>
</div>
<div className="form-group col-6 col-sm-6 col-md-6 col-lg-4 col-xl-4">
<input
type="text"
disabled
id="lastname"
name="lastname"
value={dataItems.lastname}
disabled={disabled ? "" : "disabled"}
ref={register({ required: true })}
/>
{errors.lastname && (
<span className="text-danger">last name required</span>
)}
<br />
<label htmlFor="lastname">Lastname</label>
</div>
</div>
</form>
On click of edit
const edit = () => {
setdisabled(true);
};
Code sandbox
You need to make your input as a controlled component and write onChange handlers which will update the state. This will allow you to edit the input field values. Demo
const [disabled, setdisabled] = useState(false);
const [name, setName] = useState(empData.item.name) // setting default name
const [lastname, setLastname] = useState(empData.item.lastname) // default lastname
const edit = () => {
setdisabled(true);
};
return (<div className="container-fluid">
<div align="right">
<button className="btn" onClick={edit}>
Edit
</button>
</div>
<div className="row">
<div>
<input
type="text"
disable
id="item.value"
value={name}
onChange={(e) => {
setName(e.target.value)
}}
disabled={disabled ? "" : "disabled"}
/>
<br />
<label htmlFor="name">Name</label>
</div>
<div>
<input
type="text"
disabled
id={"lastname"}
value={lastname}
onChange={(e) => {
setLastname(e.target.value)
}}
disabled={disabled ? "" : "disabled"}
/>
<br />
<label htmlFor="lastname">Lastname</label>
</div>
</div>
</div>);
Your input is controlled by the value you are giving to it. ie: Its value is always for example empData.item.name.
And you are not providing a change handler to handle the change.
Try adding something like this:
function myChangeHandler(e){
setEditedValueSomeHow(e.target.value);
}
<input
// ...
onChange={myChangeHandler}
/>
Read more about uncontrolled components
PS: you should have had a warning message in your console like this one:
Edit:
You are using react-hook-form to manage your form but at the same time giving values to your inputs.
Please refer to this link to initialize your form values.
short story:
Remove value form your input.
Pass an object to useForm hook containing initial values.
const { register, handleSubmit, errors } = useForm({
defaultValues: {
firstName: "steve",
lastname: "smith"
}
});
Here is a working fork for your codesandbox
In order to make the input editable, you need to update a local state which controlls the input value. As suggested by you in the comments, you are using graphql to get the data, you can make use of useEffect to set the data in state and then on click of edit, update the localState
export default function App() {
const { register, handleSubmit, errors } = useForm();
const [disabled, setdisabled] = useState(true);
const [editBtn, seteditBtn] = useState(true);
const { loading, data } = useQuery("some qraphql query here"); // getting data from graphql
const [formData, setFormData] = useState({});
useEffect(() => {
setFormData(data);
}, [data]);
const edit = () => {
setdisabled(false);
seteditBtn(false);
};
const onSubmit = () => {
console.log(formData);
// submit data using formData state.
};
const handleChange = e => {
const name = e.target.name;
const value = e.target.value;
console.log(name, value);
setFormData(prev => ({ ...prev, [name]: value }));
};
return (
<div className="container-fluid">
<form onSubmit={handleSubmit(onSubmit)}>
{editBtn === true && (
<div align="right">
<button
className="btn white_color_btn"
type="button"
onClick={edit}
>
Edit
</button>
</div>
)}
{editBtn === false && (
<button className="btn white_color_btn" type="submit">
Save
</button>
)}
<div className="row">
<div className="form-group col-6 col-sm-6 col-md-6 col-lg-4 col-xl-4">
<input
type="text"
id="firstname"
name="firstname"
onChange={handleChange}
value={formData.firstname}
disabled={disabled}
ref={register({ required: true })}
/>
{errors.firstname && (
<span className="text-danger">first name required</span>
)}
<br />
<label htmlFor="emp_designation">First name</label>
</div>
<div className="form-group col-6 col-sm-6 col-md-6 col-lg-4 col-xl-4">
<input
type="text"
id="lastname"
name="lastname"
value={formData.lastname}
onChange={handleChange}
disabled={disabled}
ref={register({ required: true })}
/>
{errors.lastname && (
<span className="text-danger">last name required</span>
)}
<br />
<label htmlFor="lastname">Lastname</label>
</div>
</div>
</form>
</div>
);
}
Working mock demo

How can i stop input elements from switching to from uncontrolled to controlled and vice versa using react hooks?

Hello guys i'm having a bit of an issue validating a form using react hooks. i keep getting an error whenever i click the submit button that says
index.js:1 Warning: A component is changing a controlled input of type email to be uncontrolled. Input elements should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component.
here's my code .
const [formData, setFormData] = useState({
email:'',
password:'',
emailError:'',
passwordError:''
})
const handleEmailChange = e => setFormData({email: e.target.value})
const handlePasswordChange = e => setFormData({password: e.target.value})
//validate
const validate = () => {
let inputError = false
const errors = {
emailError:'',
passwordError:''
}
if(!formData.email) {
inputError = true
errors.emailError = 'Please enter a valid email'
}
else if(!formData.email.match(emailRegex))
{
inputError = true
errors.emailError = (
<span style={{color:'red'}}>Your email address must be valid</span>
)
}
if(formData.password.length < 4){
inputError = true
errors.passwordError = 'Your password must contain more than 4 characters'
}
setFormData({
...errors
})
return inputError
}
const onSubmit = e => {
e.preventDefault();
const err = validate();
if(!err){`
setFormData(formData)
}
}
my JSX
<FormContainer>
<div className="form-container">
<form >
<h1>Sign in</h1>
<div className="input-container">
<input className={formData.emailError ? 'input-error input-empty' : 'input-empty'}
value={formData.email}
type="email"
required
onChange={e => handleEmailChange(e)}
/>
<label>Email or Phone Number</label>
<span style={{color: '#db7302'}}>{formData.emailError}</span>
</div>
<div className="input-container">
<input
className={formData.passwordError ? 'input-error input-empty' : 'input-empty'}
type="password"
value={formData.password}
required
onChange={e => handlePasswordChange(e)}
/>
<label>Password</label>
<span style={{color: '#db7302'}}>{formData.passwordError}</span>
</div>
<div className="input-container">
<Button href="/" onClick={e => onSubmit(e)} type="submit">Sign in</Button>
</div>
<label className="checkbox-container">
Remember me
<input type="checkbox" checked />
<span className="checkmark"></span>
</label>
<Link to="/" className="need-help">Need Help?</Link>
<div className="bottom-form">
<img src={fbLogo} alt="" />
<Link to="/" className="login-fb">
Login with facebook
</Link>
<br/>
<br/>
<span style={{color:'#999'}}>New to netflix?</span>
<Link to="/" className="signup-txt">Sign up now</Link>
</div>
</form>
</div>
</FormContainer>
When you set the formData, you don't include all values, so instead of having email as a empty string, it becomes undefined, and React decides that an input is uncontrolled, if it's value is undefined.
To prevent this, include the previous values of the form, when setting the formData:
setFormData(formData => ({
...formData,
...errors
}))

Categories