Да, использовать другую схему, основанную на родном брате родителя (parent.parent) - PullRequest
0 голосов
/ 03 апреля 2020

В схеме я хотел бы настроить схему на основе родителя родителя .

Если, например: если toggleMonday - true, то в будние дни -> понедельник должно быть указано Speci c схема проверки.

Теперь работает следующий пример. Однако это довольно многословно.

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(). Тем не менее, кажется, что вы можете ориентироваться только на одноуровневые или дочерние дочерние поля.

Вложение его под каждый день соответственно не работает, поскольку дни вложены в «будни».

Что-то в строках:

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.
});

Любой совет?

Ответы [ 2 ]

0 голосов
/ 03 апреля 2020

Да, у вас есть декларативный 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 }
    , {}
    )
0 голосов
/ 03 апреля 2020

После некоторого копания я нашел этот PR: https://github.com/jquense/yup/pull/201

Кажется, что обходной путь ( источник ) должен использовать контекст:

// 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 для своих входных значений. Это поддерживает только контекст через HO C withFormik ( source )

Я буду придерживаться многословного метода, так как реализация будет иным образом так конкретна c, что его нелегко повторно использовать во всем приложении из-за деталей реализации.

...