Why is OnChange not working when used in Formik? - html

I am trying to use Formik in React for a dummy app. I am not being able to type anything in either of the input boxes if I give value as a prop. On the other hand, if I skip the value props, then I can type in the boxes but the same is not reflected as the value while submitting.
Here's the code:
export default class DashboardPage extends React.Component {
render() {
return (
<Formik
initialValues={{ fname: "", lname: "" }}
onSubmit={(values) => {
alert(values.fname);
}}
render={({ values, handleChange, handleSubmit }) => (
<form onSubmit={handleSubmit}>
<input type="text" placeholder="First Name" name="fname" onChange={handleChange} value={values.fname} />
<input type="text" placeholder="Last Name" name="lname" onChange={handleChange} value={values.lname} />
<button type="submit>ADD<button/>
</form>
)}
/>
);
}
}
I may be very wrong here and might be over-looking a minor error, but any help/suggestion is appreciated!

export default class DashboardPage extends React.Component {
render() {
return (
<Formik
initialValues={{ fname: "", lname: "" }}
onSubmit={ (values) => alert(values.fname) }
>
{ props => (
<React.Fragment>
<form onSubmit={handleSubmit}>
<input type="text" placeholder="First Name" name="fname" onChangeText={props.handleChange('fname')} />
<input type="text" placeholder="Last Name" name="lname" onChangeText={props.handleChange('lname')} />
<button type="submit>ADD<button/>
</form>
</React.Fragment>
)}
</Formik>
)
}
}
Hi mate can you please try this?

Another possibility for this weird behavior is putting your component inside a function and sending the props as function parameters instead of using a functional component with props as parameters.
When a component is inside a function you lose react component lifecycle and the parameters will not refresh even when its values change.
Make sure your form elements are properly configured as react elements.

Mine was also not working, I gave id prop in my TextField and now it works
const formik = useFormik({
initialValues: {
username: "",
password: "",
},
onSubmit: (values) => {
console.log(values);
// onLogin(values.username, values.password);
},
});
<form onSubmit={formik.handleSubmit}>
<TextField
value={formik.values.username}
onChange={formik.handleChange}
id="username"
name="username"
variant="outlined"
style={TextField1style}
placeholder="Enter username"
fullWidth
required
//.
// .
// .
// other code
enter image description here

Related

Input text no longer editable when using register with react-hook-form

I'm trying to set up react-fook-form to validate my forms, but when I use the register function on a text input (in my case the username input), this input is no longer editable, I can't type anything inside.
const {register, handleSubmit, formState: { errors }} = useForm();
const [username, setUsername] = useState('');
.....
<form onSubmit={handleSubmit(onSubmit)}>
<label htmlFor="username">Username : </label>
<input type="text" value={username}
onChange={e => setUsername(e.target.value)}
{...register('username', { required: 'Please, type in your username' })}
/>
{errors.username && <span style={{color: 'red'}}><br/>{errors.username.message}</span>}
<br/>
<label htmlFor="password">Password : </label>
<input type="password" value={password} onChange={e => setPassword(e.target.value)}/>
<br/>
<button type="submit">Login</button>
</form>
Ok I finally found the solution myself.
Since the version 7 of react-hook-form library, we have to place "onChange" inside the register function like so :
<input type="text" value={username} {...register('username', {
required: 'Please, type in your username',
onChange: e => setUsername(e.target.value)
})}/>

oninvalid attribute not rendering in React js

I am trying to add oninvalid attribute in HTML element under React js code. (using react hooks not class based)
const openEndedAnswer = answer => {
return (<>
<input type="text" className="form-control"
required="required"
oninvalid="this.setCustomValidity('Enter User Name Here')"
oninput="this.setCustomValidity('')"
maxLength="255"
id={`answer_${question.id}`}
name={`answer_${question.id}`}
onChange={e => updatePostForm(e)}
pattern=".*[^ ].*"
title=" No white spaces"
/>
</>)
}
But it never renders in the browser. all other attributes can be seen in F12 source view.
The attribute names should onInvalid instead of oninvalid and onInput instead of oninput. Additionally, you need to call the setCustomValidity function on the input field as follow (because the input field is the target of the event):
onInvalid={e => e.target.setCustomValidity('Enter User Name Here')}
onInput={e => e.target.setCustomValidity('')}
If you are using React with javascript this should work:
onInvalid={e => e.target.setCustomValidity('Your custom message')}
onInput={e => e.target.setCustomValidity('')}
But if you are working with React with typescript you also need to add this:
onInvalid={e => (e.target as HTMLInputElement).setCustomValidity('Enter User Name Here')}
onInput={e => (e.target as HTMLInputElement).setCustomValidity('')}
Try onInvalid instead:
export default function App() {
return (
<form>
Name:{" "}
<input
type="text"
onInvalid={() => console.log("working!")}
name="fname"
required
/>
<input type="submit" value="Submit" />
</form>
);
}

When I click the submit button, it doesn't store to the database, but it keeps redirecting back to the form page

I'm using Reactjs and Material UI and then Formik for the form validation. Whenever I finish completing the form and then hit the submit button, it looks as if it's making the request to post the data to the back-end, but then it reload back to the same form page.
const initialValues = {
from: "",
to: "",
purpose: "",
date: "",
kilometer: "",
amount: "",
claimType: "",
fullname:"",
vehicleNo: "",
bank: "",
email: "",
department: "",
status:"",
};
useEffect(() => {
if(!localStorage.getItem("accessToken")){
history.push("/");
}
}, [])
const validationSchema = Yup.object().shape({
from: Yup.string().required(),
to: Yup.string().required() ,
purpose:Yup.string().required(),
date:Yup.date().required(),
kilometer:Yup.number().required(),
amount: Yup.number().required(),
claimType: Yup.string().required(),
fullname: Yup.string().required(),
vehicleNo: Yup.string().required(),
department: Yup.string().required(),
bank: Yup.string().required(),
email: Yup.string().email(),
status: Yup.string(),
});
const onSubmit = (data)=> {
axios
.post("http://localhost:5001/dutyMileage", data, {
headers:
{ accessToken: localStorage.getItem("accessToken")},
})
.then((response) => {
console.log("it worked");
history.push('/Home');
})
}
return (
<div>
<Formik
initialValues={initialValues}
onSubmit={onSubmit}
validationSchema={validationSchema} >
<form className={classes.root} onSubmit={() => { alert("Claim Submitted"); }}>
<div className="formstep1">
<div>
<TextField
label="Full Name"
required
autoComplete="off"
variant="outlined"
name="fullname"
placeholder="Enter your Full name"
/>
<TextField
label="Department"
required
autoComplete="off"
variant="outlined"
name="department"
placeholder="Enter your department"
/>
</div>
<div>
<TextField
label="Bank"
required
autoComplete="off"
variant="outlined"
name="bank"
placeholder="Enter your bank name"
/>
<TextField
label="Date"
name="date"
variant="outlined"
/>
</div>
<div>
<TextField
disabled
variant="outlined"
label="status"
name="status"
value="PENDING"
/>
<TextField
label="Email"
required
autoComplete="off"
variant="outlined"
name="email"
placeholder="Enter your Email "
/>
</div>
<div className="select">
<InputLabel id="demo-simple-select-outlined-label">Claim Type</InputLabel>
<Select
required
name="claimType"
variant="outlined"
label="Claim Type"
value={claimType}
onChange={handleChange}
>
<MenuItem value="Duty Mileage">Duty Mileage</MenuItem>
<MenuItem value="Travelling Allowances">Travelling Allowances</MenuItem>
<MenuItem value="Approved Purchases">Approved Purchases</MenuItem>
<MenuItem value="Guest Of University">Guest Of University </MenuItem>
<MenuItem value="Other Claims">Other Claims</MenuItem>
</Select>
</div>
<div>
<TextField
label="Kilometer"
name="kilometer"
className={classes.root, classes.textField}
InputProps={{
endAdornment: <InputAdornment position="end">Km</InputAdornment>,
}}
variant="outlined"
onChange={ (event) => {
setKilometer(event.target.value);
}}
placeholder="Number of Kilometers"
/>
<TextField
label="Amount"
onChange={handleChangee}
name="amount"
InputProps={{
inputComponent: NumberFormatCustom,
}}
variant="outlined"
placeholder="Enter Amount In Naira"
/>
</div>
<div>
<TextField
label="From"
required
autoComplete="off"
variant="outlined"
placeholder="Journey From"
name="from" />
<TextField
label="To"
required
autoComplete="off"
variant="outlined"
name="to"
placeholder="journey To"
/>
</div>
<div>
<TextField
label="Vehicle Number"
required
autoComplete="off"
variant="outlined"
name="vehicleNo"
placeholder="Enter your Vehicle Number"
/>
<TextField
label="Purpose"
required
autoComplete="off"
variant="outlined"
name="purpose"
placeholder="purpose"
/>
</div>
</div>
<button type="submit"> Submit Claim</button>
</form>
</Formik>
</Paper>
</div>
);
}
And the back end goes like this
The router request:
const express = require("express");
const router = express.Router();
const { DutyMileage } = require("../models");
const { validateToken } = require("../middlewares/AuthMiddleware");
router.post("/", validateToken, async(req, res) => {
const post = req.body;
post.userId = req.username.userId;
post.StaffId = req.username.id;
await DutyMileage.create(post);
res.json(post);
});
Anytime I make request to submit the data to the database, it keeps reloading and it's stuck on the form page.
First, you must have errors in console, check inspection in browser and your node(npm console) errors
Second, here is code from formik official lib, try to remake you template for this to test:
<Formik
initialValues={{yourInitialValues}}
validationSchema={yourYupValidation}
onSubmit={(values, {setSubmitting, resetForm}) => {
// When button submits form and form is in the process of submitting, submit button is disabled
setSubmitting(true);
// Simulate submitting to database, shows us values submitted, resets form
setTimeout(() => {
//your code to send to API
//you can debug and test values here
alert(JSON.stringify(values, null, 2))
setSubmitting(false);
}, 1);
}}
>
{( {values,
errors,
touched,
handleChange,
handleBlur,
handleReset,
setFieldValue,
handleSubmit,
setFieldTouched,
isSubmitting }) => (
//use only formik functions to test
<form onSubmit={handleSubmit}>
</form>
)}
</Formik>
And last one: you have onSubmit={() => { alert("Claim Submitted"); }}, just check this line, you just console log onSubmit. Also your onSubmit const is outside Formik component, it may affect formik behaviour.

ReactJs - onClick doesn't seem to work on a button HTML tag

I have this simple piece of code in my ReactJs app:
import React from 'react'
import '../../../assets/styles/authentication/login.css'
import '../../../assets/bootstrap/css/bootstrap.min.css'
import { login } from './login_form_actions.js'
export default class LoginForm extends React.Component {
constructor(props) {
super(props)
this.state = {
email : { email: "" },
password : { password: "" }
}
this.handle_sign_in_click = this.handle_sign_in_click.bind(this)
}
handle_sign_in_click(e) {
console.log(e, this.state.email, this.state.password)
login(this.state.email, this.state.password)
}
render() {
return (
<div className="col-sm-6 col-sm-offset-3 form-box">
<div className="form-auth">
<form className="login-form">
<div className="form-group">
<label className="sr-only" htmlFor="form-username">Email</label>
<input type="text" name="form-username" placeholder="Email..."
className="form-username form-control" id="form-username"
onChange={(event) => this.setState({email:event.target.value})}/>
</div>
<div className="form-group">
<label className="sr-only" htmlFor="form-password">Password</label>
<input type="password" name="form-password" placeholder="Password..."
className="form-password form-control" id="form-password"
onChange={(event) => this.setState({password:event.target.value})}/>
</div>
<button className="btn" onClick={this.handle_sign_in_click}>Sign in!</button>
</form>
</div>
</div>
)
}
}
When I click the Sign In button, nothing happens for some reason.
I tried to bind the handle_sign_in_click as proposed in some other reactjs question (from StackOverflow) but still nothing.. What am I missing here? (next step is to use redux to store the result of the auth on success)
Thanks for any help
Edit1: Console and proposition
console:
react-dom.development.js:22287 Download the React DevTools for a better development experience: react-devtools
authentication:1 [DOM] Input elements should have autocomplete attributes (suggested: "current-password"): ​
However, when I use an <a/> instead of <button/>, it does work but my design is broken (it's the same at all as when it's a button)
Here is how to properly handle basic forms in React (without libs like Formik etc...):
import React from 'react';
export default class Form extends React.Component {
state = { email: '', password: '' };
handleChange = event => {
this.setState({ [event.target.name]: event.target.value });
};
handleSubmit = event => {
event.preventDefault();
// login logic here ususally passed down as props from the parent (if not using redux...) so it will be something like this.props.login(...)
this.setState({ email: '', password: '' });
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<input
name="email"
type="text"
onChange={this.handleChange}
placeholder="email"
value={this.state.email}
/>
<input
name="password"
type="text"
onChange={this.handleChange}
placeholder="password"
value={this.state.password}
/>
<input type="submit" />
</form>
);
}
}
You are missing a e.preventDefault in your signin handler, check this working sample

React - Deselecting the checkbox doesn't make div to dissapear

I'm currently messing around with Reactjs and don't know where exactly my problem lays. I wan't to render an input field if a certain chekbox is selected (requiredRoleResponsible in this case). If i check it first time to true it works fine, but if I deselect it, it won't disappear. Maybe i missing something?
class ProccessForm extends React.Component {
constructor(props) {
super(props)
this.state = { name: '', description: '', requireSupervisor: false, requireRoleResponsible: false, roleResponsible: '' }
this.handleNameChange = this.handleNameChange.bind(this);
this.handleDescriptionChange = this.handleDescriptionChange.bind(this);
this.handleSupervisorCheckbox = this.handleSupervisorCheckbox.bind(this);
this.handleRoleResponsibleCheckbox = this.handleRoleResponsibleCheckbox.bind(this);
this.handleRoleResponsibleChange = this.handleRoleResponsibleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(e, data) {
e.preventDefault();
const name = this.state.name.trim();
const description = this.state.description.trim();
if (!name || !description)
return;
this.props.onProcessSubmit({ name: name, description: description });
this.setState({ name: '', description: '' });
}
handleSupervisorCheckbox(e) {
this.setState({requireSupervisor: Boolean(e.target.value)});
}
handleRoleResponsibleCheckbox(e) {
this.setState({requireRoleResponsible: Boolean(e.target.value)});
}
handleRoleResponsibleChange(e) {
this.setState({roleResponsible: e.target.value});
}
handleNameChange(e) {
this.setState({ name: e.target.value })
}
handleDescriptionChange(e) {
this.setState({ description: e.target.value })
}
render() {
return (
<div className="panel-body">
<form className="processForm" onSubmit={this.handleSubmit}>
<div className="form-group">
<label htmlFor="inputName">Name</label>
<input className="form-control" id="inputName" type="text" placeholder="Prozessname" value={this.state.name} onChange={this.handleNameChange} />
</div>
<div className="form-group">
<label htmlFor="inputDescription">Beschreibung</label>
<textarea className="form-control" id="inputDescription" type="text" placeholder="Prozessbeschreibung" value={this.state.description} onChange={this.handleDescriptionChange} />
</div>
<span>Welche Genehmigungen werden benötigt?</span>
<div className="checkbox">
<label><input type="checkbox" value={this.state.requireSupervisor} onChange={this.handleRoleResponsibleCheckbox}/>Vorgesetzer</label>
</div>
<div className="checkbox">
<label><input type="checkbox" value={this.state.requireRoleResponsible} onChange={this.handleRoleResponsibleCheckbox}/>Rollenverantwortlicher</label>
</div>
{this.state.requireRoleResponsible ?
<div className="form-group">
<label htmlFor="inputRoleResp">Name</label>
<input className="form-control" id="inputRoleResp" type="text" placeholder="Rollenverantwortlicher" value={this.state.roleResponsible} onChange={this.handleRoleResponsibleChange} />
</div> : null}
<div>
<input type="submit" value="erstellen" />
</div>
</form>
</div>
);
}
}
I tried different approaches I seen online so far. Making the second part of the if to null like currently in my code. Just to use this.state.requireRoleResponsible && the to render part and in the handler to make explicitely a boolean out of the value
Thanks for your help
For checkbox you need to use checked instead of value.
Checked will determined if the checkbox is checked or not. Value is just a property to hold.
In this case you need to change:
<input type="checkbox" value={this.state.requireRoleResponsible}
onChange={this.handleRoleResponsibleCheckbox}/>Rollenverantwortlicher</label>
To:
<input type="checkbox" checked={this.state.requireRoleResponsible}
onChange={this.handleRoleResponsibleCheckbox}/>Rollenverantwortlicher</label>
And change the handler to:
handleRoleResponsibleCheckbox(e) {
this.setState({requireRoleResponsible: e.target.checked});
}
With checkbox you should use checked instead of value ( should use value attr for type: text , select , ... )
And in 2 function handler for your checkbox , i think you can use like this :
handleRoleResponsibleCheckbox(e) {
//this.setState({requireRoleResponsible: Boolean(e.target.value)});
this.setState((prevState)=>{
return {
requireRoleResponsible: !prevState.requireRoleResponsible
}
})
}
with prevState is current state before you update