I have a antd form where I get those values with useForm. But I not able to set my state with values from the form.
Code:
const [form] = Form.useForm();
const [userDetails, setUserDetails] = useState({});
const onFinish = () => {
console.log("form", form.getFieldValue());
setUserDetails(form.getFieldValue());
};
<Form
form={form}
name="payment"
initialValues={
{
// remember: true,
}
}
layout="vertical"
onFinish={onFinish}
onFinishFailed={onFinishFailed}
autoComplete="off"
>
<div>
<Form.Item
label="Email"
name="email"
rules={[
{
required: true,
message: "Please input your email!",
},
{
type: "email",
},
]}
>
<Input placeholder="Enter Your Email" className="text-left" />
</Form.Item>
</Form>
Console logging form.getFieldValue() is returning correct data, but couldn't set the same data to state ( setUserDetails(form.getFieldValue()); )
Related
I have a form with ant design. I want to add a rule for each input field that the user can't enter spaces to fill the input. (spaces forbidden)
I try this method { transform: (value) => value.trim() }but it doesn't work.
I appreciate your help.
<>
<Form.Item
label={t("forms.inputs.Name.label")}
rules={[
{
required: true,
message: t("forms.inputs.Name.rules.required"),
},
{
min: 3,
message: t("forms.inputs.Name.rules.minLength"),
},
]}>
<Input />
</Form.Item>
<Form.Item
label={t("forms.inputs.job.label")}
rules={[
{
required: true,
message: t("forms.inputs.job.rules.required"),
},
]}>
<Input />
</Form.Item>
<Form.Item
label={t("forms.inputs.Company.label")}
rules={[
{
required: true,
message: t("forms.inputs.Company.rules.required"),
},
]}>
<Input placeholder={t("forms.inputs.currentCompany.placeholder")} />
</Form.Item>
</>
Just write a custom validation rule:
<Form.Item
label="Username"
name="username"
rules={[
{
required: true,
message: "Required"
},
{
validator: (_, value) =>
!value.includes(" ")
? Promise.resolve()
: Promise.reject(new Error("No spaces allowed"))
}
]}
>
<Input />
</Form.Item>
For email validation, you can use the following regex pattern:
<Form.Item
label="Email"
name="email"
rules={[
{
required: true,
message: "Required"
},
{
pattern: /([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|\"([]!#-[^-~ \t]|(\\[\t -~]))+\")#([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|\[[\t -Z^-~]*])/,
message: "Invalid email"
}
]}
normalize={(value, prevVal, prevVals) => value.trim()}
>
<Input />
</Form.Item>
DEMO
Instead of trimming onChange, do that in an onBlur callback:
formatInput = (event) => { const attribute = event.target.getAttribute('name') this.setState({ [attribute]: event.target.value.trim() }) }
or when you click enter
onKeyPress={(e) => {if (e.key === "Enter") {setValue(e.target.value.trim())} }}
you can do like this instead of using trim()
import React, { useState } from 'react';
import 'antd/dist/antd.css';
import { Form, Input } from 'antd';
const App = () => {
const [inputValue, setValue] = useState({input1: '', input2: '', input3: ''});
const onFinish = (values) => {
console.log('Success:', values);
};
const onFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo);
};
const handleOnChange = (e) => {
let {value} = e.target;
let data = {...inputValue};
if (value.length && value[0] === ' ') {
data[e.target.name] = '';
setValue(data);
return;
}
data[e.target.name] = value;
setValue(data);
}
return (
<Form
name="basic"
labelCol={{
span: 8,
}}
wrapperCol={{
span: 16,
}}
initialValues={{
remember: true,
}}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
autoComplete="off"
>
<>
<Form.Item
label={t("forms.inputs.Name.label")}
rules={[
{
required: true,
message: t("forms.inputs.Name.rules.required"),
},
{
min: 3,
message: t("forms.inputs.Name.rules.minLength"),
},
]}>
<Input name="input1" value={inputValue.input1} onChange={handleOnChange} />
</Form.Item>
<Form.Item
label={t("forms.inputs.job.label")}
rules={[
{
required: true,
message: t("forms.inputs.job.rules.required"),
},
]}>
<Input name="input2" value={inputValue.input2} onChange={handleOnChange} />
</Form.Item>
<Form.Item
label={t("forms.inputs.Company.label")}
rules={[
{
required: true,
message: t("forms.inputs.Company.rules.required"),
},
]}>
<Input name="input3" value={inputValue.input3} onChange={handleOnChange} placeholder={t("forms.inputs.currentCompany.placeholder")} />
</Form.Item>
</>
</Form>
);
};
export default App;
So I have a form, and I need users to fill this form and when they send a message, it should come to my gmail. I use EmailJS service for this.
So my form looks like this:
So as you see, users can send me messages, and my code looks like this:
Usestate for sending data:
const [toSend, setToSend] = useState({
from_name: '',
to_name: '',
message: '',
reply_to: '',
subject: ''
});
onSubmit function:
const onSubmit = (e) => {
e.preventDefault();
send(
'service_id',
'template_id',
toSend,
'user_id'
)
.then((response) => {
console.log('SUCCESS!', response.status, response.text);
})
.catch((err) => {
console.log('FAILED...', err);
});
reset();
};
handleChange function:
const handleChange = (e) => {
setToSend({ ...toSend, [e.target.name]: e.target.value });
};
useform hook:
const {register, handleSubmit, formState: { errors }, reset, trigger} = useForm();
Whole form:
<form onSubmit={handleSubmit(onSubmit)}>
<input type="text"
placeholder="Name"
name="from_name"
value={toSend.from_name}
onChange={handleChange}
id="name" {...register('name', { required: "Name is required" })}
onKeyUp={() => {
trigger("name");
}}/>
{errors.name && (<span className="danger_text">{errors.name.message}</span>)}
<input type="text"
placeholder="Email"
name="reply_to"
value={toSend.reply_to}
onChange={handleChange}
id="email" {...register("email", { required: "Email is Required" ,
pattern: {
value: /^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: "Invalid email address",
}})}
onKeyUp={() => {
trigger("email");
}}
/>
{errors.email && (
<small className="danger_text">{errors.email.message}</small>
)}
<input type="text"
placeholder=
"Subject"
id="subj"
name="subject"
value={toSend.subject}
onChange={handleChange}/>
<input type="text"
placeholder="Message"
id="msg"
name="message"
value={toSend.message}
onChange={handleChange}
{...register('msg', { required: true })}/>
{errors.msg && (<small className="danger_text">Enter your message</small>)}
<input type="submit" className="btn_red" value="Send a message"></input>
</form>
So my problem is that I can't fill anything in inputs. When I try to type something it just doesn't type in, I'm guessing it has something to do with "value=.." in all inputs, but I'm not sure what's exactly the problem here.
You don't need to define onChnage, value, onKeyUp on your inputs, when you call register on input, it returns onChange,onBlur,ref, then react-hook-forms will control the values by ref. so below example should solve your problem:
import { useForm } from 'react-hook-form';
...
function MyComp() {
const {
register,
handleSubmit,
formState: { errors },
reset,
} = useForm();
const onSubmit = (toSend) => {
send(
'service_id',
'template_id',
toSend,
'user_id'
)
.then((response) => {
console.log('SUCCESS!', response.status, response.text);
})
.catch((err) => {
console.log('FAILED...', err);
});
reset();
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input
type="text"
placeholder="Name"
name="from_name"
id="name"
{...register('from_name', { required: 'Name is required' })}
/>
{errors.from_name && (
<span className="danger_text">{errors.from_name.message}</span>
)}
<input
type="text"
placeholder="Email"
name="reply_to"
id="email"
{...register('reply_to', {
required: 'Email is Required',
pattern: {
value: /^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: 'Invalid email address',
},
})}
/>
{errors.reply_to && (
<small className="danger_text">{errors.reply_to.message}</small>
)}
<input
type="text"
placeholder="Subject"
id="subj"
name="subject"
{...register('subject')}
/>
<input
type="text"
placeholder="Message"
id="msg"
name="message"
{...register('message', { required: true })}
/>
{errors.message && <small className="danger_text">Enter your message</small>}
<input type="submit" className="btn_red" value="Send a message"></input>
</form>
);
}
BTW, consider that register works with input's name, not id.
I have a antd form that consists of input and checkboxes.
antd : 4.16.0
react : 17.0.2
After using,
this.formRef.current.resetFields();
the input fields are getting reset but not the checkboxes.
Sample Code:
<Form
layout="vertical"
hideRequiredMark
initialValues={{
sunH: [
moment("00:00", "HH:mm"),
moment("00:00", "HH:mm"),
],
monH: [
moment("00:00", "HH:mm"),
moment("00:00", "HH:mm"),
],
}}
ref={this.props.formRef}
>
<Row gutter={16}>
<Col span={12}>
<Form.Item
name="pName"
label="Name"
rules={[
{
required: true,
message: "Please enter Name",
},
]}
>
<Input placeholder="Enter name" />
</Form.Item>
<Form.Item name="Mon" label="" valuePropName="checked">
<Text>Mon</Text>
</Form.Item>
</Col>
</Row>
</Form>
the form takes in a onCancel props, so onCancel,
this.formRef.current.resetFields();
log of this.formRef.current:
you can manually set radio fields value null in that function ...
all you have to do is ...
formRef.setFieldsValue(['label_name(Mon)'] : undefined)
try formRef.current.setFieldsValue if you cant't change using upper code.
for functional component you have to take the form reference that is binding using useForm() and you have to call setfield method same.
form.setFieldsValue(['label_name(Mon)'] : undefined )
ant.design/components/form/#components-form-demo-nest-messages Check the second example, they have well explained everything you need there
https://codesandbox.io/s/form-methods-antd-4-17-0-alpha-7-forked-ff1uf?file=/index.js:0-2953
Check this working example with checkbox
import React from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import "./index.css";
import { Form, Input, Button, Select, Checkbox } from "antd";
const { Option } = Select;
const layout = {
labelCol: {
span: 8
},
wrapperCol: {
span: 16
}
};
const tailLayout = {
wrapperCol: {
offset: 8,
span: 16
}
};
const Demo = () => {
const [form] = Form.useForm();
const onGenderChange = (value) => {
switch (value) {
case "male":
form.setFieldsValue({
note: "Hi, man!"
});
return;
case "female":
form.setFieldsValue({
note: "Hi, lady!"
});
return;
case "other":
form.setFieldsValue({
note: "Hi there!"
});
}
};
const onFinish = (values) => {
console.log(values);
};
const onReset = () => {
form.resetFields();
};
const onFill = () => {
form.setFieldsValue({
note: "Hello world!",
gender: "male"
});
};
return (
<Form {...layout} form={form} name="control-hooks" onFinish={onFinish}>
<Form.Item
name="note"
label="Note"
rules={[
{
required: true
}
]}
>
<Input />
</Form.Item>
<Form.Item
name="gender"
label="Gender"
rules={[
{
required: true
}
]}
>
<Select
placeholder="Select a option and change input text above"
onChange={onGenderChange}
allowClear
>
<Option value="male">male</Option>
<Option value="female">female</Option>
<Option value="other">other</Option>
</Select>
</Form.Item>
<Form.Item
noStyle
shouldUpdate={(prevValues, currentValues) =>
prevValues.gender !== currentValues.gender
}
>
{({ getFieldValue }) =>
getFieldValue("gender") === "other" ? (
<Form.Item
name="customizeGender"
label="Customize Gender"
rules={[
{
required: true
}
]}
>
<Input />
</Form.Item>
) : null
}
</Form.Item>
<Form.Item
name="remember"
valuePropName="checked"
wrapperCol={{
offset: 8,
span: 16
}}
>
<Checkbox>Remember me</Checkbox>
</Form.Item>
<Form.Item {...tailLayout}>
<Button type="primary" htmlType="submit">
Submit
</Button>
<Button htmlType="button" onClick={onReset}>
Reset
</Button>
<Button type="link" htmlType="button" onClick={onFill}>
Fill form
</Button>
</Form.Item>
</Form>
);
};
I have created my react form with antd. I have added antd validation for the form. But my form doesn't know whether I have filled the form or not. Whenever I filled the form and submitted it, it doesn't call onFinish method. Instead it fails and calls onFinishFailed method and gives me validation error messages.
I have created it in correct way according to my knowledge. But there is something missing I think. Here's my code.
const [name, setName] = useState('');
const [description, setDescription] = useState('');
const history = useHistory();
const [form] = Form.useForm();
const layout = {
labelCol: { span: 4 },
wrapperCol: { span: 8 },
};
const onChangeName = (e) => {
setName(e.target.value);
console.log(name);
}
const onAddCategory = (values) => {
let req = {
"name": values.name,
"description": values.description
}
postCategory(req).then((response) => {
if (response.status === 201) {
message.success('Category created successfully');
history.push('/categorylist');
}
}).catch((error) => {
console.log(error);
message.error('Oops, error occured while adding category. Please try again');
});
}
const onFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo);
console.log('State:', name, description);
};
return (
<React.Fragment>
<Form
form={form}
name="control-hooks"
onFinish={onAddCategory}
onFinishFailed={onFinishFailed}
{...layout}
size="large"
>
<Form.Item
name="name"
rules={[
{
required: true,
message: 'You can’t keep this as empty'
}, {
max: 100,
message: 'The category name is too lengthy.',
}
]}
>
<label>Category name</label>
<Input
placeholder="Category name"
className="form-control"
value={name}
onChange={onChangeName}
/>
</Form.Item>
<Form.Item
name="description"
rules={[
{
required: true,
message: 'You can’t keep this as empty'
}, {
max: 250,
message: 'The description is too lengthy',
}
]}
>
<label>Description</label>
<Input.TextArea
placeholder="Description"
className="form-control"
value={description}
onChange={(e) => setDescription(e.target.value)}
/>
</Form.Item>
<Form.Item shouldUpdate={true}>
<Button
type="primary"
htmlType="submit"
className="btn btn-primary"
>
Add category
</Button>
</Form.Item>
</Form>
</React.Fragment>
)
In this form I have managed state using hooks. In onFinishFailed method I have logged my input values with state and they have values. But form doesn't identify it.
How do I resolve this. Please help.
I found the issue. Here I had added label inside form item. It was the reason for the unexpected behavior. Once I took the label outside the form item problem was solved.
<label>Category name</label>
<Form.Item
name="name"
rules={[
{
required: true,
message: 'You can’t keep this as empty'
}, {
max: 100,
message: 'The category name is too lengthy.',
}
]}
>
<Input
placeholder="Category name"
className="form-control"
value={name}
onChange={onChangeName}
/>
</Form.Item>
I'm new to react JS, I'm trying to get the values from a form, and send it to a node JS middleware.
I set up two values in the state, one for the email and another one for the password. I set the state for both values in the set state method.
class LoginForm extends Component {
constructor(props){
super(props)
this.state = {
email : '',
password : '',
}
}
handleChange = (e) => {
this.setState({ email : e.target.value, password : e.target.value})
}
handleSubmit = (e) => {
console.log('state', this.state)
};
render () {
return (
<div style = {styles.form} >
<Fragment>
<Form
{...layout}
name="basic"
initialValues={{
remember: true,
}}
onFinish={this.handleSubmit}
>
<Form.Item
name="email"
rules={[
{
type: 'email',
message: 'The input is not valid E-mail!',
},
{
required: true,
message: 'Please input your E-mail!',
},
]}
hasFeedback
>
<Input
placeholder={t`Email`}
value={this.state.email}
onChange={this.handleChange} />
</Form.Item>
<Form.Item
name="password"
rules={[{ required: true }]} hasFeedback
>
<Input.Password
placeholder={t`Password`}
value={this.state.password}
onChange={this.handleChange}
/>
</Form.Item>
<Button
type="primary"
htmlType="submit"
>
<span style = {styles.button} >Sign in</span>
</Button>
</Form>
</Fragment>
</div>
)
}
}
}
I created the handle submit function and linked it to the onsubmit method inside the form and tried console logging the current state of my values inside the handle submit function. To my surprise the value from the password gets console logged for the value email too. Like this
state {email: "123", password: "123"}
I cannot figure out what am I doing wrong.
I think if you change your handleChange function to this, it should work.
handleChange = (e) => {
this.setState({ [e.target.id] : e.target.value})
}
And add id to the input fields like this
<Input id="email" placeholder={t`Email`} value={this.state.email} onChange {this.handleChange} />
<Input.Password id="password" placeholder={t`Password`} value {this.state.password} onChange={this.handleChange} />
Here is the solution:
handleChange = (e) => {
let email = ''
let password = ''
if (e.target.name === 'email') {
email = e.taget.value
} else {
password = e.taget.value
}
this.setState({ email, password})
}