getFieldDecorator rules for password reset? - reactjs

I'm trying to do a "field 2 does not match field 1" thing here (i.e. "passwords do not match).
There isn't much documentation on the available rules for the antd forms. They point at this project here.
Below is my current form:
const ResetPasswordForm = Form.create()(React.createClass({
getInitialState () {
return {
loading: false
};
},
handleSubmit(e) {
e.preventDefault();
this.props.form.validateFields((err, values) => {
if (err) {
failure();
}
if (!err) {
let newPassword = values.newPassword;
let repeatNewPassword = values.repeatNewPassword;
handleResetPassword(newPassword, repeatNewPassword, this.props.token);
}
});
},
render() {
const { getFieldDecorator } = this.props.form;
const newPasswordRules = [
{ required: true, message: 'Please input a new password!' }
];
const repeatNewPassword = [
{ required: true, message: 'Please repeat the new password!' }
];
return (
<Form onSubmit={this.handleSubmit} className="login-form">
<FormItem>
{getFieldDecorator('newPassword', { rules: newPasswordRules })(
<Input addonBefore={<Icon type="lock" />} type="password" placeholder="New password" />
)}
</FormItem>
<FormItem>
{getFieldDecorator('repeatNewPassword', { rules: repeatNewPassword })(
<Input addonBefore={<Icon type="lock" />} type="password" placeholder="Repeat new password" />
)}
</FormItem>
<FormItem>
<Button loading={this.state.loading} type="primary" htmlType="submit" className={css(styles.loginButton)}>
Reset Password
</Button>
</FormItem>
</Form>
);
}
}));
If anyone can point me in the right direction for creating a rule that checks that the first field value matches the second, that'd be awesome!

You can find it in this register form demo: https://ant.design/components/form/#components-form-demo-register

Please, follow these lines:
<Form.Item
name="password"
label="Password"
rules={[
{
required: true,
message: 'Please input your password!',
},
]}
hasFeedback
>
<Input.Password />
</Form.Item>
<Form.Item
name="confirm"
label="Confirm Password"
dependencies={['password']}
hasFeedback
rules={[
{
required: true,
message: 'Please confirm your password!',
},
({ getFieldValue }) => ({
validator(rule, value) {
if (!value || getFieldValue('password') === value) {
return Promise.resolve();
}
return Promise.reject('The two passwords that you entered do not match!');
},
}),
]}
>
<Input.Password />
</Form.Item>

Related

How to Trim White Spaces from input field in ant-design form?

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;

Change date format in antd <DatePicker />

I'm submitting a form to send data to my API that receives date in the format of YYYY-MM-DD but by default the DatePicker component keeps adding extra characters of time to the end of the date, for example when I enter a date for my date of birth field the value is stored in the format below
{
"date_of_birth":"2003-02-03T13:32:49.543Z"
}
I would prefer it to be just
{
"date_of_birth":"2003-02-03"
}
below is the code for the form and its submit function
const Demo = () => {
const [visible, setVisible] = useState(false);
const [form] = Form.useForm();
const showUserModal = () => {
setVisible(true);
};
const hideUserModal = () => {
setVisible(false);
};
const onFinish = values => {
console.log(JSON.stringify(values))
const userToken = localStorage.getItem(AUTH_TOKEN)
IndividualService.setToken(userToken)
IndividualService.postIndividual(values).then(resp => {
console.log(resp)
message.success('successfully added details for Individual plan')
}).catch(error => {
message.error('Error occured, plase try again', error.message)
})
};
const customFormat = value => `custom format: ${value.format("YYYY-MM-DD")}`;
return (
<Card title='Enter Customer details for individual plan'>
<Row justify='center'>
<Col span={20}>
<Form.Provider
onFormFinish={(name, { values, forms }) => {
if (name === 'userForm') {
const { basicForm } = forms;
const dependants = basicForm.getFieldValue('dependants') || [];
basicForm.setFieldsValue({
dependants: [...dependants],
...values
});
setVisible(false);
}
}}
>
<Form {...layout} name="basicForm" onFinish={onFinish} size='small'>
<Form.Item
name="first_name"
label="First Name"
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item
name="other_names"
label="Other Names"
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item
name="gender"
label="Gender"
rules={[
{
required: true,
},
]}
>
<Select>
<Option value="MALE">male</Option>
<Option value="FEMALE">female</Option>
</Select>
</Form.Item>
<Form.Item
name="date_of_birth"
label="Date of Birth"
rules={[
{
required: true,
},
]}
>
<DatePicker format={customFormat} />
</Form.Item>
<Form.Item
name="blood_group"
label="Blood Group"
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item
name="residential_address"
label="Residential address"
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item
name="workplace_address"
label="Workplace address"
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item
name="additional_telephone_no"
label="Additional phone no."
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item
name="NIN"
label="NIN"
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item
name="next_of_kin_name"
label="Next of kin name"
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item
name="next_of_kin_telephone"
label="next of kin phone."
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item
name="next_of_kin_email"
label="next of kin email."
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item
name="dependants"
label="Dependants List"
shouldUpdate={(prevValues, curValues) => prevValues.dependants !== curValues.dependants}
>
{({ getFieldValue }) => {
const dependants = getFieldValue('dependants') || [];
return dependants.length ? (
<ul>
{dependants.map((d, index) => (
<li key={index} className="user">
<Avatar icon={<UserOutlined />} />
<p>{d.first_name} - {d.relationship}</p>
</li>
))}
</ul>
) : (
<Typography.Text className="ant-form-text" type="secondary">
( <SmileOutlined /> No dependant yet. )
</Typography.Text>
);
}}
</Form.Item>
<Form.Item {...tailLayout}>
<Button htmlType="submit" type="primary">
Submit
</Button>
<Button
htmlType="button"
style={{
marginLeft: 8,
}}
onClick={showUserModal}
>
Add User
</Button>
</Form.Item>
</Form>
<ModalForm visible={visible} onCancel={hideUserModal} />
</Form.Provider>
</Col>
</Row>
</Card>
);
};
You can add the prop format to get the input in custom format, as
<DatePicker
format="YYYY-MM-DD"
/>
This will display the date in the format YYYY-MM-DD in the date picker.
To convert this to the required format you may need to format it in the onFinish , as:
const onFinish = values => {
console.log(JSON.stringify(values))
const userToken = localStorage.getItem(AUTH_TOKEN)
IndividualService.setToken(userToken)
values["date_of_birth"] = moment(values.date_of_birth).format("YYYY-MM-DD")
IndividualService.postIndividual(values).then(resp => {
console.log(resp)
message.success('successfully added details for Individual plan')
}).catch(error => {
message.error('Error occured, plase try again', error.message)
})
};

Ant Design v4. How to show the error message from custom validator in form

How to get the error message from the validator and show it in the form? I have 2 types of errors: "Please enter password" - if the field is empty and "Incorrect password" - when the password does not match. How to realize this?
export const LoginPage = ({ startLogin }) => (
<div>
<Form
name="normal_login"
initialValues={{ remember: true }}
onFinish={startLogin}
validateTrigger='onSubmit'
>
///////////////////////////////////THE CORE PART////////////////////////////////////////
<Form.Item
name="password"
rules={[{ required: true, message: 'Please enter password!' }, ({ getFieldValue }) => ({
//WHY THE MESSAGE ABOVE IS NOT SHOWN AT ALL?
validator(_, value) {
axios.get('users.json').then(({ data }) => {
if (condition) //do smth.
else if (condition) {
throw new Error("Incorrect password"); //<-- HOW TO SHOW THIS
}
});
}).catch(e => {console.log(e); return e});
},
}),]}
>
/////////////////////////////////////////////////////////////////////////////////////////
<Input.Password
className="input"
iconRender={visible => (visible ? <EyeTwoTone /> : <EyeInvisibleOutlined />)}
prefix={<LockOutlined className="site-form-item-icon" />}
type="password"
placeholder="Password"
/>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit" className="login-form-button">
Log in
</Button>
</Form.Item>
</Form>
</div>
);```

form.isFieldValidating not working in ant Design

i'm using next js
const [form] = Form.useForm();
const onFinishFailed = ({ values }) => {
console.log("email-status",form.isFieldValidating('email'),form.getFieldsError())
console.log("failed",values);
};
<Form
{...layout}
layout="vertical"
name="basic"
form = {form}
initialValues={{ email: "",password: "",remember: true,}}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
>
<Form.Item
name="email"
label="E-mail"
rules={[
{
type: 'email',
message: 'The input is not valid E-mail!',
},
{
required: true,
message: 'Please input your E-mail!',
},
]}
>
<Input />
</Form.Item>
<Form.Item
name="password"
label="Password"
rules={[
{
required: true,
message: 'Please input your password!',
},
]}
>
<Input.Password />
</Form.Item>
<Form.Item >
<Button type="primary" htmlType="submit">
Register
</Button>
</Form.Item>
Now when I type a valid email and doesn't enter a password and click on Register button
a) I'm getting 'Please input your password!',and not getting any error displayed under email input box // which is expected
b) Since i haven't entered any password on clicking the registered button
"onFinishFailed " function is being executed // so far so good
c) But in console I'm getting the output as
email-status, false, []
It should be email-status , true, [ ] right...

Unexpected token (8:8) while parsing file

I'm using antd and I wanna use its registration Form in my project.
Note: Before adding this component my project (registration.js) was working correctly and I've just copied and pasted the antd component.
Here is my registration.js file:
import { Form, Input, Tooltip, Icon, Cascader, Select, Row, Col, Checkbox, Button, AutoComplete } from 'antd';
const FormItem = Form.Item;
const Option = Select.Option;
const AutoCompleteOption = AutoComplete.Option;
class RegistrationForm extends React.Component {
state = {
confirmDirty: false,
autoCompleteResult: [],
};
handleSubmit = (e) => {
e.preventDefault();
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
}
});
}
handleConfirmBlur = (e) => {
const value = e.target.value;
this.setState({ confirmDirty: this.state.confirmDirty || !!value });
}
compareToFirstPassword = (rule, value, callback) => {
const form = this.props.form;
if (value && value !== form.getFieldValue('password')) {
callback('Two passwords that you enter is inconsistent!');
} else {
callback();
}
}
validateToNextPassword = (rule, value, callback) => {
const form = this.props.form;
if (value && this.state.confirmDirty) {
form.validateFields(['confirm'], { force: true });
}
callback();
}
handleWebsiteChange = (value) => {
let autoCompleteResult;
if (!value) {
autoCompleteResult = [];
} else {
autoCompleteResult = ['.com', '.org', '.net'].map(domain => `${value}${domain}`);
}
this.setState({ autoCompleteResult });
}
render() {
const { getFieldDecorator } = this.props.form;
const { autoCompleteResult } = this.state;
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 8 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
};
const tailFormItemLayout = {
wrapperCol: {
xs: {
span: 24,
offset: 0,
},
sm: {
span: 16,
offset: 8,
},
},
};
const prefixSelector = getFieldDecorator('prefix', {
initialValue: '86',
})(
<Select style={{ width: 70 }}>
<Option value="86">+86</Option>
<Option value="87">+87</Option>
</Select>
);
const websiteOptions = autoCompleteResult.map(website => (
<AutoCompleteOption key={website}>{website}</AutoCompleteOption>
));
return (
<Form onSubmit={this.handleSubmit}>
<FormItem
{...formItemLayout}
label="E-mail"
>
{getFieldDecorator('email', {
rules: [{
type: 'email', message: 'The input is not valid E-mail!',
}, {
required: true, message: 'Please input your E-mail!',
}],
})(
<Input />
)}
</FormItem>
<FormItem
{...formItemLayout}
label="Password"
>
{getFieldDecorator('password', {
rules: [{
required: true, message: 'Please input your password!',
}, {
validator: this.validateToNextPassword,
}],
})(
<Input type="password" />
)}
</FormItem>
<FormItem
{...formItemLayout}
label="Confirm Password"
>
{getFieldDecorator('confirm', {
rules: [{
required: true, message: 'Please confirm your password!',
}, {
validator: this.compareToFirstPassword,
}],
})(
<Input type="password" onBlur={this.handleConfirmBlur} />
)}
</FormItem>
<FormItem
{...formItemLayout}
label={(
<span>
Nickname
<Tooltip title="What do you want others to call you?">
<Icon type="question-circle-o" />
</Tooltip>
</span>
)}
>
{getFieldDecorator('nickname', {
rules: [{ required: true, message: 'Please input your nickname!', whitespace: true }],
})(
<Input />
)}
</FormItem>
<FormItem
{...formItemLayout}
label="Habitual Residence"
>
{getFieldDecorator('residence', {
initialValue: ['zhejiang', 'hangzhou', 'xihu'],
rules: [{ type: 'array', required: true, message: 'Please select your habitual residence!' }],
})(
<Cascader options={residences} />
)}
</FormItem>
<FormItem
{...formItemLayout}
label="Phone Number"
>
{getFieldDecorator('phone', {
rules: [{ required: true, message: 'Please input your phone number!' }],
})(
<Input addonBefore={prefixSelector} style={{ width: '100%' }} />
)}
</FormItem>
<FormItem
{...formItemLayout}
label="Website"
>
{getFieldDecorator('website', {
rules: [{ required: true, message: 'Please input website!' }],
})(
<AutoComplete
dataSource={websiteOptions}
onChange={this.handleWebsiteChange}
placeholder="website"
>
<Input />
</AutoComplete>
)}
</FormItem>
<FormItem
{...formItemLayout}
label="Captcha"
extra="We must make sure that your are a human."
>
<Row gutter={8}>
<Col span={12}>
{getFieldDecorator('captcha', {
rules: [{ required: true, message: 'Please input the captcha you got!' }],
})(
<Input />
)}
</Col>
<Col span={12}>
<Button>Get captcha</Button>
</Col>
</Row>
</FormItem>
<FormItem {...tailFormItemLayout}>
{getFieldDecorator('agreement', {
valuePropName: 'checked',
})(
<Checkbox>I have read the agreement</Checkbox>
)}
</FormItem>
<FormItem {...tailFormItemLayout}>
<Button type="primary" htmlType="submit">Register</Button>
</FormItem>
</Form>
);
}
}
const WrappedRegistrationForm = Form.create()(RegistrationForm);
ReactDOM.render(<WrappedRegistrationForm />, document.getElementById('main'));
And this is my index.html file:
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>React Project</title>
</head>
<body>
<div id="main"></div>
<script src="/build/bundle.js"></script>
</body>
</html>
I face with this error in my registration.js file:
Unexpected token (8:8) while parsing file
Line 8 refers to where we have state = {, how can I solve this problem?
Probably you are not using the right transpilers.
Declaring global variables in classes like your state = { ... } is only possible with ES7 (I believe). You are probably using a ES6 transpiler.
One fix would be changing your syntax to ES6. So you would have to declare you state like this:
class RegistrationForm extends React.Component {
constructor(props) {
super(props);
this.state = { ... };
}
// ...
}
ES6 also doesn't support declaring class methods with arrow syntax (myMethod = () => { ... }). You would have to change all of your methods to myMethod() { ... }
Another fix would be to download the right presets so babel (I'm guessing you are using babel) can transpile your ES7 syntax.

Resources