I'm setting up a form with two fields; start month and end month.
Start month and end month are just represented by integers (0-11) for the corresponding months. I need validation to ensure that end month comes after start month (ie the integer for end month is bigger).
I've looked at other similar issues from a few years back, but yup seems to have updated to render them useless. I've tried the below code with a few variations.
I am also having difficulty validating end month as a number (.number() - I'm assuming I have to maybe to do this within the test function.
let schema = yup.object().shape({
startMonth: yup
.number()
.required()
.positive()
.integer(),
endMonth: Yup.string().test(
"End Month Validation",
"error message",
value => {
return value > startMonth;
}
)
.number()
.required()
.positive()
.integer(),
});
Errors:
Line 102: 'startMonth' is not defined no-undef
Another approach would be to make use of .ref() and .moreThan() to perform this validation logic.
Something like the following should achieve what you require:
let schema = Yup.object().shape({
startMonth: Yup
.number()
.required()
.positive()
.integer(),
endMonth: Yup.number() /* Remove .string() */
.required()
.positive()
/* Reference startMonth field in validating endMonth value */
.moreThan(Yup.ref('startMonth'), "End month must come after start month")
.integer(),
});
schema.validate({ startMonth : 1, endMonth : 2 }) // Okay!
schema.validate({ startMonth : 11, endMonth : 2 }) // Throws exception
Hope that helps!
Related
I'm currenlty working on yup validation for a page in project. I'm stuck on the following:
User chooses date, timezone and specific time of the event (he can choose times from 00:00 to 23:45 every fifteen minutes). Now, I need to validate if chosen time is in the future. I am really confused: should I first convert current moment to users chosen timezone, or convert user's moment to local timezone, or something else.
Here's what I did first when I was careless about the timezone:
[keys.startTime]: yup
.number()
.required(errors.required)
.when(['date'], (date, schema: any) => {
const currentTimeInMinutes = moment().hours() * 60 + moment().minutes()
if (
moment(date).date() === moment().date() &&
moment(date).month() === moment().month() &&
moment(date).year() === moment().year()
)
return schema.min(currentTimeInMinutes, errors.pastTime)
}),
But then I realised that I didn't take into account chosen timezone.
Start time here represents number of minutes from 00:00 to chosen time, for example if user chooses 00:15, startTime will be 15.
Thanks in advance.
You need to compare - the current time (at the point of submission) with the user's selected/entered date and startTime both in the user's selected zone.
// Calculate the offset of the timezone that user selected from UTC
const utcOffset = '+05:30'; // Example of a time zone in India
const currentTime = moment().utcOffset(utcOffset);
const userSelectionTime =
moment(date).utcOffset(utcOffset)
.startOf('day')
.add(startTime, 'minutes');
/*
* Check if the difference between the `userSelectionTime` and the `currentTime`
* is greater than 0 minutes (you can change this as per your requirements)
*/
const selectionIsValid = userSelectionTime.diff(currentTime, 'minutes') > 0;
I want to allow number which should be more than 0 with decimal number
I tried
const schema = yup.object().shape({
amount: yup.number().min(0),
});
But, it allow 0 value which I don't want. So, I tried
const schema = yup.object().shape({
amount: yup.number().min(0.1),
});
But, it not allow 0.001 or 0.0002
How can change which allow more than 0 decimal value. Any help would be really appreciated.
You can use yup.number.positive() instead min(0)
https://github.com/jquense/yup#numberpositivemessage-string--function-schema
I have this schema that validates 2 password fields based on several requirements :
"Password must have 8 or more characters, at least one uppercase letter, and one number."
"Password cannot contain special characters other than _ # . -"
Right now i am showing both validation errors in one string, but i need to show 2 separate errors for these conditions.
The question is, how do i create 2 regex that don't conflict with each other when validating and will show me the necessary error?
const format = /[a-z`!#$%^&*()+=\[\]{};':"\\|,<>\/?~]/;
const passwordFormat = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d_#.-]{8,}$/;
return yup.object().shape({
password: yup
.string()
.required("Password is required")
// validates the password
.matches(passwordFormat, "Password must have 8 or more characters, at least one uppercase letter, and one number.")
//checks if there are special characters
.test('special-chars', "Password cannot contain special characters other than _ # . -", function(value) {
return format.test(value);
})
.strict(true)
});
You can try these two:
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[\S]{8,}$ - "Password must have 8 or more characters, at least one uppercase letter, and one number"
^[-#\.\w]*$ - "Password cannot contain special characters other than _ # . -"
I'm doing a service chat and I'd like to extract days that correspond to Sunday. For exemple:
Watson: Choose a date
user: day 30
Watson: We don't open this day, because it's a Sunday.
The problem is.. the Sundays of this month are not the same as next month.. I tried with an array inside the context with Sundays days of this month(ex: "2","9","16","23","30"), but the Conversation didn't understand that day 30 is a Sunday.. Could anyone help me please?
Tks! :)
In this case, unfortunally, #sys-date does not work equal #sys-number.
In this case with #sys-number, if user type 1, #sys-number recognize and can use #sys-number:1 with condition inside the flow.
Unfortunally, #sys-date doesn't.
In this case, for get the date with javascript you can use:
new Date() //get the date NOW
new Date(milliseconds)
new Date(dateString)
new Date(year, month, day, hours, minutes, seconds, milliseconds)
You can see the now() is the same format to get date:
new Date(year, month, day, hours, minutes, seconds, milliseconds)
And you can convert the #sys-date to the same format, and use this to verify the name of the date.
Get the day with context variable and use code in your application. For example:
var days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
var dateObject = new Date(dateParts[2], dateParts[1] - 1, dateParts[0]);
var dayName = days[dateObject.getDay()];
console.log(dayName);
And make some condition... for example:
if(dayName === 'Sunday'){
data.output.text[0] = "We don't open this day, because it's a Sunday."
}
I code this and works fine, see:
function dayRequest(data, req, res){
console.log('works the true condition context')
var dateString = data.context.day; //context variable with <? #sys-date ?>
var dateParts = dateString.split("/");
var dateObject = new Date(dateParts[2], dateParts[1] - 1, dateParts[0]);
var days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
var dateObject = new Date(dateParts[2], dateParts[1] - 1, dateParts[0]);
var dayName = days[dateObject.getDay()];
console.log(dayName);
if(dayName === 'Sunday'){
data.output.text[0] = "We don't open this day, because it's a Sunday.";
return res.json(data);
}
}
Check my app:
In this case, you can use now to get the date and in your application you'll end a message if the day is Sunday... You can use context variable for this too, but, you need set all dates.. And with this code, you'll check the date and your application will send a message.
Summary: convert your #sys-date to the same format now() and use my code to send a message for your user if the day is Sunday. I created one context variable with to save the date after request and in the next flow I create one context with dayTrue: true inside conversation flow. In my application, I created one condition in my updateMessage() if data.context.date === true, my function dayRequest() will execute.
I have an Event model that I'd like to place the following validation rule on, in a custom def clean(self): method on the Model:
def clean(self):
from django.core.exceptions import ValidationError
if self.end_date is not None and self.start_date is not None:
if self.end_date < self.start_date:
raise ValidationError('Event end date should not occur before start date.')
Which works fine, except that I'd like to highlight the self.end_date field in the admin UI, by somehow nominating it as the field that has errors. Otherwise I only get the error message that occurs at the top of the change form.
From Django 1.7 you can directly add error to the particular field by using add_error method. Django docs
form.add_error('field_name', 'error_msg or ValidationError instance')
If the field_name is None the error will be added to non_field_errors.
def clean(self):
cleaned_data = self.cleaned_data
end_date = cleaned_data.get('end_date')
start_date = cleaned_data.get('start_date')
if end_date and start_date:
if end_date < start_date:
self.add_error('end_date', 'Event end date should not occur before start date.')
# You can use ValidationError as well
# self.add_error('end_date', form.ValidationError('Event end date should not occur before start date.'))
return cleaned_data
The docs explain how to do this at the bottom.
provided example:
class ContactForm(forms.Form):
# Everything as before.
...
def clean(self):
cleaned_data = self.cleaned_data
cc_myself = cleaned_data.get("cc_myself")
subject = cleaned_data.get("subject")
if cc_myself and subject and "help" not in subject:
# We know these are not in self._errors now (see discussion
# below).
msg = u"Must put 'help' in subject when cc'ing yourself."
self._errors["cc_myself"] = self.error_class([msg])
self._errors["subject"] = self.error_class([msg])
# These fields are no longer valid. Remove them from the
# cleaned data.
del cleaned_data["cc_myself"]
del cleaned_data["subject"]
# Always return the full collection of cleaned data.
return cleaned_data
for your code:
class ModelForm(forms.ModelForm):
# ...
def clean(self):
cleaned_data = self.cleaned_data
end_date = cleaned_data.get('end_date')
start_date = cleaned_data.get('start_date')
if end_date and start_date:
if end_date < start_date:
msg = 'Event end date should not occur before start date.'
self._errors['end_date'] = self.error_class([msg])
del cleaned_data['end_date']
return cleaned_data