'Password matching validation using the Joi schema in React not working
I want to create a password change form in React. Here is the code of my component :
import React, { Component } from "react";
import Joi from "joi-browser";
import "./Login/Login.css";
import { UAA } from "../../Actions/Types";
class ChangePassword extends Component {
state = {
account: {
currentPassword: "",
newPassword: "",
newPasswordRepeated: "",
},
errors: {},
auth: UAA,
};
schema = {
currentPassword: Joi.string().required().label("Password"),
newPassword: Joi.string().min(12).max(64).required().label("Password"),
newPasswordRepeated: Joi.any().valid(Joi.ref("newPassword")).required(),
};
validate = () => {
const options = { abortEarly: false };
const { error } = Joi.validate(this.state.account, this.schema, options);
if (!error) return null;
const errors = {};
for (let item of error.details) {
errors[item.path[0]] = item.message;
}
return errors;
};
validateProperty = ({ name, value }) => {
const obj = { [name]: value };
console.log(obj);
const schema = { [name]: this.schema[name] };
console.log(schema);
const { error } = Joi.validate(obj, schema);
console.log(JSON.stringify(error));
return error ? error.details[0].message : null;
};
handleSubmit = (e) => {
e.preventDefault();
const errors = this.validate();
this.setState({ errors: errors || {} });
if (errors) return;
//todo : call server
};
handleChange = ({ currentTarget: input }) => {
const errors = { ...this.state.errors };
const errorMessage = this.validateProperty(input);
if (errorMessage) errors[input.name] = errorMessage;
else delete errors[input.name];
const account = { ...this.state.account };
account[input.name] = input.value;
this.setState({
account: account,
errors: errors,
});
};
render() {
const { errors, account } = this.state;
return (
<div className="container">
<div className="col-md-5 offset-md-3">
<form
className="login-form"
onSubmit={(event) => this.handleSubmit(event)}
>
<p />
<p className="form-label">Current password</p>
<input
type="password"
id="currentPassword"
name="currentPassword"
value={account.currentPassword}
onChange={this.handleChange}
/>
{errors.currentPassword && (
<div className="alert alert-danger">{errors.currentPassword}</div>
)}
<p className="form-label">New password</p>
<input
type="password"
name="newPassword"
onChange={this.handleChange}
value={account.newPassword}
/>
{errors.newPassword && (
<div className="alert alert-danger">{errors.newPassword}</div>
)}
<p className="form-label">Confirm password</p>
<input
type="password"
name="newPasswordRepeated"
value={account.newPasswordRepeated}
onChange={this.handleChange}
/>
{errors.newPasswordRepeated && (
<div className="alert alert-danger">
{errors.newPasswordRepeated}
</div>
)}
<div className="submit-login-form">
<input
type="submit"
value="Submit"
disabled={this.validate()}
></input>
</div>
</form>
</div>
</div>
);
}
}
export default ChangePassword;
When the user enters a repeated password, I want to validate whether that repeated password matches the new password already entered. This is done within the validateProperty
method.The problem is that Joi returns validation error even if both passwords match. I appreciate any help with this.
Solution 1:[1]
After some researching, I was able to figure out what was the problem.
The problem lies in method validateProperty
specifically in Joi schema used when validating the field newPasswordRepeated
. In this schema, it is necessary to add a validation rule for newPassword
. Therefore I changed my validateProperty
method like below:
validateProperty = ({ name, value }) => {
if (name === "newPasswordRepeated") {
const { account } = this.state;
const obj = { newPassword: account.newPassword, [name]: value };
const schema = {
[name]: this.schema[name],
newPassword: this.schema["newPassword"],
};
const { error } = Joi.validate(obj, schema);
return error ? error.details[0].message : null;
} else {
const obj = { [name]: value };
const schema = { [name]: this.schema[name] };
const { error } = Joi.validate(obj, schema);
return error ? error.details[0].message : null;
}
};
Hope someone finds this useful.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |