I have recently started using yup for validation. However I am stuck on rewriting the login page, as it has multiple loginname and password fields depending on the user having more than one.
The current validation was working properly, however we want to use yup with this. I wrote this simple validation schema with yup, but could not get it to work. Could someone please help me understand how to get this to work? (If you need any additional information, please let me know)
What I would like:
1. Have another validation object created in yup when another inputfield is added.
2. Validate each field in an object of the array. At the moment below is what happens:
const invalid_example = [
{
login_name: ''
login_password: 'value'
},
{
login_name: 'value'
login_password: 'value'
}
]; // all will validate false, I only want login_name for the first object to validate false
Example of the code:
state:
const [validation, setValidation] = useState({
users: [{ login_name: "notActive", login_password: "notActive" }]
});
const [login, setLogin] = useState({
users: [{ login_name: "", login_password: "" }],
});
input fields:
{login.users.map((item, i) => (
<Grid container direction="row" key={i} spacing={1}>
<Grid item xs={5} sm={5} md={5} lg={5} xl={5}>
<TextField
{...register(`users.${i}.login_name`, { shouldUnregister: true })}
id={i}
variant="outlined"
type="text"
name={`users${[i]}.login_name`}
value={login.users.login_name}
onChange={(e) => handleChange(e, i)}
label={props.t("login:Your Login Name")}
error={
Object.keys(errors).length > 0
? errors.users[i].login_name.message !== undefined
: validation.users[i].login_name === false
}
helperText={
Object.keys(errors).length > 0
? props.t(`register:${errors.users[i].login_name.message}`)
: validation.users[i].login_name === false &&
props.t("login:LoginName")
}
fullWidth
required
/>
</Grid>
<Grid item xs={5} sm={5} md={5} lg={5} xl={5}>
<TextField
{...register(`users.${i}.login_password`, { shouldUnregister: true })}
id={i}
variant="outlined"
type="password"
name={`users${[i]}.login_password`}
value={login.users.login_password}
onChange={(e) => handleChange(e, i)}
label={props.t("login:Your Password")}
error={
Object.keys(errors).length > 0
? errors.users[i].login_password.message !== undefined
: validation.users[i].login_password === false
}
helperText={
Object.keys(errors).length > 0
? props.t(`register:${errors.users[i].login_password.message}`)
: validation.users[i].login_password === false &&
props.t("login:Password")
}
fullWidth
required
/>
</Grid>
</Grid>
))}
handleChange function:
const handleChange = (e, i) => {
const { name, value} = e.target;
const username = name.split('.', 3)[1]
let users = [...login.users];
users[i] = { ...users[i], [username]: value };
setLogin({ users: users });
if (username === "login_name" || username === "login_password") {
let val = [...validation.users];
let newName = username === "login_password" ? "login_name" : "login_password";
let newValue = username === "login_password" ? val[i].login_name : val[i].login_password;
if (value === "") {
val[i] = { ...users[i], [username]: false, [newName]: newValue };
setValidation({ users: val });
} else {
val[i] = { ...users[i], [username]: true, [newName]: newValue };
setValidation({ users: val });
}
}
}
yup validation schema
const LoginSchema = yup.object().shape({
users: yup.array().ensure().of(
yup.object().shape({
login_name: yup.string().required(empty_field),
login_password: yup.string().required(empty_field),
})).required(empty_field)
});
The issues with the current code:
1. I can get it to validate the entire login field, when one of the fields is empty, however I want to validate each field value seperately.
2. When both fields have a value, it won't validate to true.
3. Adding another login field after validation returns an error. It looks for that newly created object, but yup only reads the ones before validation.
