是的,根据 parent (parent.parent) 的兄弟使用不同的模式
Yup use different schema based on sibling of a parent (parent.parent)
在架构中,我想根据 parent 的 兄弟调整架构。
例如:如果 toggleMonday 为真,则工作日 -> 星期一应该有特定的验证模式。
现在下面的例子可以工作了。但是,它非常冗长。
const schema = yup.object().shape({
toggleMonday: yup.bool().required(),
toggleTuesday: yup.bool().required(),
toggleWednesday: yup.bool().required(),
toggleThursday: yup.bool().required(),
toggleFriday: yup.bool().required(),
toggleSaturday: yup.bool().required(),
toggleSunday: yup.bool().required(),
weekdays: yup.object()
// works, toggleMonday is a sibling of weekdays
.when('toggleMonday', {
is: true,
then: yup.object().shape({
monday: yup.array().of(yup.object().shape(daySchema)).daySchemaFirstTimeslotRequired(),
tuesday: yup.array().of(yup.object().shape(daySchema)),
wednesday: yup.array().of(yup.object().shape(daySchema)),
thursday: yup.array().of(yup.object().shape(daySchema)),
friday: yup.array().of(yup.object().shape(daySchema)),
saturday: yup.array().of(yup.object().shape(daySchema)),
sunday: yup.array().of(yup.object().shape(daySchema)),
}),
})
.when('toggleTuesday', {
is: true,
then: yup.object().shape({
monday: yup.array().of(yup.object().shape(daySchema)),
tuesday: yup.array().of(yup.object().shape(daySchema)).daySchemaFirstTimeslotRequired(),
wednesday: yup.array().of(yup.object().shape(daySchema)),
thursday: yup.array().of(yup.object().shape(daySchema)),
friday: yup.array().of(yup.object().shape(daySchema)),
saturday: yup.array().of(yup.object().shape(daySchema)),
sunday: yup.array().of(yup.object().shape(daySchema)),
}),
})
// etc.
});
如您所见,它非常重复。
本例中使用了mixed.when()
方法。但是,您似乎只能定位同级或同级 children 字段。
将它分别嵌套在每一天下是行不通的,因为这些天嵌套在 'weekdays'.
行中的内容:
const schema = yup.object().shape({
toggleMonday: yup.bool().required(),
toggleTuesday: yup.bool().required(),
toggleWednesday: yup.bool().required(),
toggleThursday: yup.bool().required(),
toggleFriday: yup.bool().required(),
toggleSaturday: yup.bool().required(),
toggleSunday: yup.bool().required(),
weekdays: yup.object()
// does not work, toggleMonday is not a sibling of 'monday'
monday: yup.array().when('toggleMonday', {
is: true,
then: yup.array().of(yup.object().shape(daySchema)).daySchemaFirstTimeslotRequired(),
otherwise: yup.array().of(yup.object().shape(daySchema)),
}),
tuesday: yup.array().when('toggleMonday', {
is: true,
then: yup.array().of(yup.object().shape(daySchema)).daySchemaFirstTimeslotRequired(),
otherwise: yup.array().of(yup.object().shape(daySchema)),
}),
// etc.
});
有什么建议吗?
经过一番挖掘,我发现了这个 PR:https://github.com/jquense/yup/pull/201
似乎解决方法 (source) 是使用上下文:
// Pass the root data to context
schema.validateSync(data, {context: {data: data}})
// In your test, you can just access the root data
.test('myValidator', 'my validation message', function (value) {
const data = this.options.context.data;
// Do what you need to do with the root data
})
所以这意味着我应该使用上下文通过道具获取切换项,并在模式中使用它们。
与这个问题有点无关:我也在使用 formik 作为我的输入值。这仅通过 HOC withFormik
(source)
支持上下文
我会坚持使用冗长的方法,因为实现会非常具体,由于实现细节的缘故,它不容易在我的应用程序中重复使用。
是的,给了你一个声明式 api,但你不限于像那样编写巨大的对象字面量。您的架构相当复杂,但如果没有其他方法可以更改它,请考虑以编程方式编写它 -
const weekdays =
[ 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday' ]
const schema = yup.object().shape({
toggleMonday: yup.bool().required(),
toggleTuesday: yup.bool().required(),
toggleWednesday: yup.bool().required(),
toggleThursday: yup.bool().required(),
toggleFriday: yup.bool().required(),
toggleSaturday: yup.bool().required(),
toggleSunday: yup.bool().required(),
weekdays: weekdays.reduce(whenToggle, yup.object())
})
现在我们只需要执行 whenToggle
-
const day =
yup.object().shape(daySchema)
const title = (str = "") =>
str.substr(0,1).toUpperCase() + str.substr(1)
const whenToggle = (y = {}, day = "") =>
y.when
( `toggle${title(day)}`
, { is: true, then: yup.object().shape(firstTimeslot(day)) }
)
最后执行 firstTimeslot
-
const dayList =
yup.array().of(day)
const firstTimeslot = (day = "") =>
weekdays.reduce
( (r, d) =>
d === day
? { ...r, [d]: dayList.daySchemaFirstTimeslotRequired() }
: { ...r, [d]: dayList }
, {}
)
在架构中,我想根据 parent 的 兄弟调整架构。
例如:如果 toggleMonday 为真,则工作日 -> 星期一应该有特定的验证模式。
现在下面的例子可以工作了。但是,它非常冗长。
const schema = yup.object().shape({
toggleMonday: yup.bool().required(),
toggleTuesday: yup.bool().required(),
toggleWednesday: yup.bool().required(),
toggleThursday: yup.bool().required(),
toggleFriday: yup.bool().required(),
toggleSaturday: yup.bool().required(),
toggleSunday: yup.bool().required(),
weekdays: yup.object()
// works, toggleMonday is a sibling of weekdays
.when('toggleMonday', {
is: true,
then: yup.object().shape({
monday: yup.array().of(yup.object().shape(daySchema)).daySchemaFirstTimeslotRequired(),
tuesday: yup.array().of(yup.object().shape(daySchema)),
wednesday: yup.array().of(yup.object().shape(daySchema)),
thursday: yup.array().of(yup.object().shape(daySchema)),
friday: yup.array().of(yup.object().shape(daySchema)),
saturday: yup.array().of(yup.object().shape(daySchema)),
sunday: yup.array().of(yup.object().shape(daySchema)),
}),
})
.when('toggleTuesday', {
is: true,
then: yup.object().shape({
monday: yup.array().of(yup.object().shape(daySchema)),
tuesday: yup.array().of(yup.object().shape(daySchema)).daySchemaFirstTimeslotRequired(),
wednesday: yup.array().of(yup.object().shape(daySchema)),
thursday: yup.array().of(yup.object().shape(daySchema)),
friday: yup.array().of(yup.object().shape(daySchema)),
saturday: yup.array().of(yup.object().shape(daySchema)),
sunday: yup.array().of(yup.object().shape(daySchema)),
}),
})
// etc.
});
如您所见,它非常重复。
本例中使用了mixed.when()
方法。但是,您似乎只能定位同级或同级 children 字段。
将它分别嵌套在每一天下是行不通的,因为这些天嵌套在 'weekdays'.
行中的内容:
const schema = yup.object().shape({
toggleMonday: yup.bool().required(),
toggleTuesday: yup.bool().required(),
toggleWednesday: yup.bool().required(),
toggleThursday: yup.bool().required(),
toggleFriday: yup.bool().required(),
toggleSaturday: yup.bool().required(),
toggleSunday: yup.bool().required(),
weekdays: yup.object()
// does not work, toggleMonday is not a sibling of 'monday'
monday: yup.array().when('toggleMonday', {
is: true,
then: yup.array().of(yup.object().shape(daySchema)).daySchemaFirstTimeslotRequired(),
otherwise: yup.array().of(yup.object().shape(daySchema)),
}),
tuesday: yup.array().when('toggleMonday', {
is: true,
then: yup.array().of(yup.object().shape(daySchema)).daySchemaFirstTimeslotRequired(),
otherwise: yup.array().of(yup.object().shape(daySchema)),
}),
// etc.
});
有什么建议吗?
经过一番挖掘,我发现了这个 PR:https://github.com/jquense/yup/pull/201
似乎解决方法 (source) 是使用上下文:
// Pass the root data to context
schema.validateSync(data, {context: {data: data}})
// In your test, you can just access the root data
.test('myValidator', 'my validation message', function (value) {
const data = this.options.context.data;
// Do what you need to do with the root data
})
所以这意味着我应该使用上下文通过道具获取切换项,并在模式中使用它们。
与这个问题有点无关:我也在使用 formik 作为我的输入值。这仅通过 HOC withFormik
(source)
我会坚持使用冗长的方法,因为实现会非常具体,由于实现细节的缘故,它不容易在我的应用程序中重复使用。
是的,给了你一个声明式 api,但你不限于像那样编写巨大的对象字面量。您的架构相当复杂,但如果没有其他方法可以更改它,请考虑以编程方式编写它 -
const weekdays =
[ 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday' ]
const schema = yup.object().shape({
toggleMonday: yup.bool().required(),
toggleTuesday: yup.bool().required(),
toggleWednesday: yup.bool().required(),
toggleThursday: yup.bool().required(),
toggleFriday: yup.bool().required(),
toggleSaturday: yup.bool().required(),
toggleSunday: yup.bool().required(),
weekdays: weekdays.reduce(whenToggle, yup.object())
})
现在我们只需要执行 whenToggle
-
const day =
yup.object().shape(daySchema)
const title = (str = "") =>
str.substr(0,1).toUpperCase() + str.substr(1)
const whenToggle = (y = {}, day = "") =>
y.when
( `toggle${title(day)}`
, { is: true, then: yup.object().shape(firstTimeslot(day)) }
)
最后执行 firstTimeslot
-
const dayList =
yup.array().of(day)
const firstTimeslot = (day = "") =>
weekdays.reduce
( (r, d) =>
d === day
? { ...r, [d]: dayList.daySchemaFirstTimeslotRequired() }
: { ...r, [d]: dayList }
, {}
)