#javascript #node.js #validation #momentjs #yup
#javascript #node.js #проверка #momentjs #ага
Вопрос:
Так что это довольно странно, и я не могу понять, откуда это берется.
У меня есть регистрация WS (в Node.js используя Sales.js ) если минимальный требуемый возраст равен 18 годам, проверка выполняется Yup.
Это моя схема yup:
const yup = require('yup');
const moment = require('moment');
const birthdate = yup.date()
.typeError('INVALID_DATE')
.min(moment().subtract(115, 'years'), 'MIN_AGE')
.max(moment().endOf('day').subtract(18, 'years'), 'MAX_AGE');
module.exports = {
birthdate
};
Как вы можете видеть из примера ниже, когда я указываю сегодняшнюю дату, она сравнивает ее с 2002-07-31
в то время как она должна сравниваться с moment().endOf('day').subtract(18, 'years')
, которая была бы 2002-08-12
Обратите внимание, что 2002-07-31
это дата, в которую я создал проект. Так что, если я перекомпилирую его сейчас, у меня больше не будет этой проблемы на сегодняшний день. Если я завтра проведу повторное тестирование, оно сравнит его с сегодняшней датой! Я понятия не имею, как это возможно или как это исправить.
Это ошибка от yup:
"errors": [{
"field": "birthdate",
"code": "E_MAX_AGE_BIRTHDATE",
"params": {
"path": "birthdate",
"value": "2002-08-12T10:00:00.000Z",
"originalValue": "2002-08-12T10:00:00.000Z",
"max": "2002-07-31T21:59:59.999Z"
}
}]
Есть идеи?
Используемые версии: moment 2.24.0
; yup 0.29.2
Ответ №1:
Для тех, кто хочет более простой способ получить динамическую дату (например, сейчас), которая вычисляется в момент проверки (например, не время на дату сборки): используйте yup.lazy().
В приведенном ниже примере будет проверяться, что минимальная дата позже максимальной даты (и наоборот), с динамической максимальной датой, которая генерируется заново при каждой попытке проверки.
import { date, lazy, object, ref } from 'yup'
function getMinDate() {
return new Date(2000, 1, 1)
}
function getMaxDate() {
return new Date()
}
const schema = object({
minDate: date()
.min(getMinDate(), `Min start date is ${getMinDate()}`)
.max(ref('maxDate'), 'Min date must be earlier than the max date'),
maxDate: lazy(() => date()
.min(ref('minDate'), 'Max date must be later than min date')
.max(getMaxDate(), `Max start date is ${getMaxDate()}`)
)
})
Ответ №2:
Хорошо, я нашел решение.
На самом деле, Yup сохранит дату, которую вы изначально указали, и скомпилирует ее. Он больше не будет выполняться moment().endOf('day').subtract(18, 'years')
каждый раз, когда вы подтверждаете дату.
Для этого вы должны использовать метод тестирования, а не min
nor max
.
Я создал метод расширения для yup.date
следующим образом:
/**
* This function is used to format the error like date.min does
*/
function customValidationError(errorMessage, value, path, extraData) {
const error = new yup.ValidationError(errorMessage,
value,
path);
error.params = {
path: path,
value: value,
originalValue: value,
...extraData
};
return error;
}
/**
* Extension method to yup.date
* You should pass a function that will be executed each time you want to check again the current date.
* @name yup.dynamicMaxDate
* @global yup.dynamicMaxDate
*/
yup.addMethod(yup.date, 'dynamicMaxDate', function(path, errorMessage = 'MAX_DATE', maxDateFunction) {
return this.test(path, errorMessage,
(value) => {
const maxDate = maxDateFunction();
return new Promise((resolve, reject) => {
const error = customValidationError(errorMessage, value, path, {
max: maxDate
});
value amp;amp; moment(value).isAfter(maxDate) ?
reject(error) :
resolve(true);
});
});
});
/**
* Extension method to yup.date to check if date is before a given date
* You should pass a function that will be executed each time you want to check again the current date.
* @name yup.dynamicMinDate
* @global yup.dynamicMinDate
*/
yup.addMethod(yup.date, 'dynamicMinDate', function(path, errorMessage = 'MIN_DATE', minDateFunction) {
return this.test(path, errorMessage,
(value) => {
const minDate = minDateFunction();
return new Promise((resolve, reject) => {
const error = customValidationError(errorMessage, value, path, {
min: minDate
});
value amp;amp; moment(value).isBefore(minDate) ?
reject(error) :
resolve(true);
});
});
});
И использовать эти методы:
const birthdate = yup.date()
.typeError('INVALID_DATE')
// Note tham I'm passing a function to be executed when validating date
.dynamicMinDate('birthdate', 'MIN_AGE', () => {
return moment().startOf('day').subtract(115, 'years').toDate();
})
.dynamicMaxDate('birthdate', 'MAX_AGE', () => {
return moment().endOf('day').subtract(18, 'years').toDate();
});