
[英]Always get undefined when using Yup.array().when() with two arrays
[英]How to test for uniqueness of value in Yup.array?
我有动态输入量的表格(管理员电子邮件)但是检查唯一性失败:
validationSchema={Yup.object().shape({
adminEmails: Yup.array()
.of(
Yup.string()
.notOneOf(Yup.ref('adminEmails'), 'E-mail is already used')
这里最好的方法是什么? 仅供参考,作为表单助手,我使用Formik
。
尝试这个:
Yup.addMethod(Yup.array, 'unique', function(message, mapper = a => a) {
return this.test('unique', message, function(list) {
return list.length === new Set(list.map(mapper)).size;
});
});
然后像这样使用它:
const headersSchema = Yup.object().shape({
adminEmails: Yup.array().of(
Yup.string()
)
.unique('email must be unique')
})
如果你想在每个字段中都有错误而不是在数组中
Yup.addMethod(Yup.mixed, 'uniqueIn', function (array = [], message) {
return this.test('uniqueIn', message, function (value) {
return array.filter(item => item === value).length < 2;
});
});
这是一个简单的内联解决方案,用于验证字符串数组是否仅包含唯一元素:
Yup.array().of(Yup.string())
.test(
'unique',
'Only unique values allowed.',
(value) => value ? value.length === new Set(value)?.size : true
)
可能来不及回应,但无论如何,你应该使用this.createError({path, message});
见示例:
yup.addMethod(yup.array, 'growing', function(message) { return this.test('growing', message, function(values) { const len = values.length; for (let i = 0; i < len; i++) { if (i === 0) continue; if (values[i - 1].intervalTime > values[i].intervalTime) return this.createError({ path: `intervals[${i}].intervalTime`, message: 'Should be greater than previous interval', }); } return true; }); });
为了提高亚历克斯回答的性能,使用类似这样的东西来预先计算查找(使用 lodash)。
yup.addMethod(yup.mixed, 'uniqueIn', function (array = [], message) {
return this.test('uniqueIn', message, function (value) {
const cacheKey = 'groups';
if (!this.options.context[cacheKey]) {
this.options.context[cacheKey] = _.groupBy(array, x => x);
}
const groups = this.options.context[cacheKey];
return _.size(groups[value]) < 2;
});
});
然后使用上下文对象调用验证,以便我们可以在验证调用期间存储我们计算出的组
schema.validate(data, {context: {}}).then(...);
简单地做这对我有用
首先在你的反应组件中定义这个函数
Yup.addMethod(Yup.array, "unique", function (message, mapper = (a) => a) {
return this.test("unique", message, function (list) {
return list.length === new Set(list.map(mapper)).size
})
})
只需将此架构放在您的Formik标签中
<Formik
initialValues={{
hotelName: "",
hotelEmail: [""],
}}
validationSchema={Yup.object().shape({
hotelName: Yup.string().required("Please enter hotel name"),
hotelEmail: Yup.array()
.of(
Yup.object().shape({
email: Yup.string()
.email("Invalid email")
.required("Please enter email"),
}),
)
.unique("duplicate email", (a) => a.email),
})}
onSubmit={(values, { validate }) => {
getFormPostData(values)
}}
render={({ values, errors, touched }) => (
<Form>
<FieldArray
name="hotelEmail"
render={(arrayHelpers) => (
<>
{values.hotelEmail.map((hotel, index) => (
<div class="row" key={index}>
<div className="col-md-8 mt-3">
<div className="user-title-info user-details">
<div className="form-group d-flex align-items-center mb-md-4 mb-3">
<label className="mb-0" htmlFor="hotelName">
{lang("Hotelmanagement.hotelsystemadmin")}
<sup className="text-danger">*</sup>
</label>
<div className="w-100">
<Field
name={`hotelEmail.${index}.email`}
className="form-control"
id="hotelEmail"
placeholder={lang(
"Hotelmanagement.hotelsystemadmin",
)}
/>
<span className="text-danger d-block">
{errors &&
errors.hotelEmail &&
errors.hotelEmail[index] &&
errors.hotelEmail[index].email && (
<span className="text-danger d-block">
{errors.hotelEmail[index].email}
</span>
)}
{errors &&
errors.hotelEmail &&(
<span className="text-danger d-block">
{errors.hotelEmail}
</span>
)}
</span>
</div>
</div>
</div>
</div>
<div className="col-md-2 mt-3">
{index > 0 && (
<i
className="bx bx-minus addnewBtn "
onClick={() => arrayHelpers.remove(index)}
/>
)}
{index === values.hotelEmail.length - 1 && (
<i
className="bx bx-plus addnewBtn ml-5"
onClick={() => arrayHelpers.push("")}
/>
)}
</div>
</div>
))}
</>
)}
/>
为了不显示错误,请执行以下操作
{errors &&
errors.hotelEmail &&(
<span className="text-danger d-block">
{errors.hotelEmail}
</span>
)}
)} />
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.