Joi validation - dynamic control on 3 fields - reactjs

I'm dealing with 3 form fields in order to validate them. Here are the basic schema :
schema = {
firstName: JoiExtend.string().allow(''),
lastName: JoiExtend.string().allow(''),
birthDate: JoiExtend
.date().format("DD/MM/YYYY").utc()
.allow(null).allow('')
};
So the validation rules are :
If firstName is set with value, lastName must have a value
If lastName is set with value, firstName must have a value
If birthDate is set with value, firstName and lastName must have a value
I'm really struggling for doing this, I've started to work with this approach :
schema = {
firstName: JoiExtend.when('lastName', {
is: JoiExtend.string(),
then: JoiExtend.string().required(),
otherwise: JoiExtend.string().allow('')
}),
lastName: JoiExtend.when('firstName', {
is: JoiExtend.string(),
then: JoiExtend.string().required(),
otherwise: JoiExtend.string().allow('')
}),
dateNaissance: JoiExtend
.date().format("DD/MM/YYYY").utc()
.label("La Date de naissance")
.allow(null).allow('')
.messages(this.getErrorMessage())
};
But I have the following error : Uncaught Error: item added into group lastName created a dependencies error
Moreover, this code does not take into account the rule with birthDate
Any help ?

Related

mongoose update only not nulled fields?

If I want to update already created collection, I want only save not null fields.
Example- Suppose I create a collection Here User-
name: "Siam Ahnaf"
password: "12345678"
role: "user"
This is created collection. Then I want to update it. For updating I get this object from frontend application like this-
{name: "",
password: "98765432"
role: "Admin"}
Here I can see name is empty that I get from frontend application. When I update it with
User.findByIdAndUpdate(req.user._id, {...input})
It update the collection with this empty name. After updating my collection is like this-
name: ""
password: "98765432"
role: "Admin"
But I want when name is empty then it will not save this empty valuse. It remain previous value. How can I do that?
You can remove empty string properties from the object before save it.
const obj = {
name: "",
password: "98765432",
role: "Admin"
}
Object.keys(obj).forEach((k) => obj[k] == '' && delete obj[k]);
User.findByIdAndUpdate(req.user._id, obj)
The remove empty string properties function is taken from https://stackoverflow.com/a/38340730/9095807
or use the .pre('save') method of mongoose like this: https://stackoverflow.com/a/59916058/9095807

Typescript type with get function

I'm looking for a way to define a getter for a type object in React.
type User= {
firstName?: string
lastName: string
age: number
}
In my React components I want to display firstName primarily and lastName if firstName is undefined. This logic also covers assignment e.g. author= u.firstName ?? u.lastName.
How can I define a getter than makes sure the logic is used consistently throughout the application? Like:
author = u.getName()
in code and:
{{u.getName()}
in templates.
From my research it seems like I should replace the type with class to be able to declare member functions. Do you know if type support member functions?
You can easily define a type that has a function/method:
type User = {
firstName: string;
lastName: string;
age: number;
getFullName(): string;
};
But it's just is what it name implies: a type. It doesn't do anything. The tricky part is setting the value:
const u: User = {
firstName: "John",
lastName: "Doe",
age: 30,
getFullName() {
return this.firstName + " " + this.lastName;
}
}
If you don't want to define the getFullName method every time, you should probably use a class.

Object or String type conditional with yup validation

I am using yup in combination with Formik in my React application to validate a TypeScript model/interface.
We previously had a yup.object for the follwing schema:
export const InputSchema = yup.object({
id: yup.string(),
name: yup.string().required().min(MIN_DESC_LENGTH).max(_MAX_NAME_LENGTH),
description: yup.string().required().matches(/(?!^\d+$)^[\s\S]+$/, 'Please enter a valid description').min(MIN_DESC_LENGTH).max(_MAX_DESC_LENGTH),
contact: yup.string().required()
});
As we changed our interface now, name and description fields can either be a string or an object.
I still want to validate my form with yup, so I tried to use name: yup.mixed() and description: yup.mixed() but now I get obviously problems with the min.() and .matches() functions.
Is it possible to have a string OR object condition? So if it is a yup.string() then, min/max will be used, otherwise just yup.object().
I looked for a way to do this in a simple way but couldn't find any, but the solution they give is to use yup.lazy.
For your case it would be
Yup.object({
...
name: Yup.lazy(value => {
switch (typeof value) {
case 'object':
return Yup.object(); // schema for object
case 'string':
return Yup.string().min(MIN_DESC_LENGTH).max(_MAX_NAME_LENGTH); // schema for string
default:
return Yup.mixed(); // here you can decide what is the default
}
}),
...
})
Another way you can do is like this gist.
It creates a custom method with .addMethod that receives schemas and validates all. Pretty good approach

How can I update a graphql entry?

I have a schema as follows:
type User #model {
id: ID!
firstName: String!
lastName: String!
locations: [Location]
}
type Location #model {
id: ID!
listOfPictures: [String]
address: String!
owner: User
}
Currently I have entries to both Locations and Users. The entries for my Locations are all null.
I want to update one of my Locations, of ID '1234' to have the field 'owner' set to the User of ID '5678'.
What is the correct syntax for this? What do I have to enter into he Appsync console?
Additionally, how could I update the 'locations' field of my User of id 'abc' model to add a Location, to the array of Locations, of Location with id 'def' ?
Thanks.
You can update your data by using mutations: https://docs.aws.amazon.com/appsync/latest/devguide/quickstart-write-queries.html

Formik + yup: how to validate a location schema where the fields(country, state, city) are not mandatory, but if one is filled, each should be filled?

I am having the below schema
validationSchema={yup.object().shape({
firstName: yup
.string()
.required("Name cannot be empty")
.matches(NAME_REGEX, "Name can only contain english characters"),
lastName: yup
.string()
.required("Name cannot be empty")
.matches(NAME_REGEX, "Name can only contain english characters"),
location: yup
.object()
.nullable()
.shape({
country: yup.string().required(),
state: yup.string().required(),
city: yup.string().required()
})
})}
The validation for firstName and lastName is working fine but I don't know how to validate the location.
Requirement: location is not at all required to be filled. But if any(country/state,city) of the field is filled, then all three must be filled. Either all or none.
Though I tried to validate it as above but it's not working.
Another validation requirement is: These values are being selected from the select html element, of which the first <option> is <option key={0}>-select-</option>. So, I don't want my users to select this option as well. As of now, I am handling it in the onSubmit by checking the values and if they contain -select- then these values will not be considered and will be replaced by the existing ones.
update:
location can never be null. If the user has not set any of the location field then also location would be:
location: {
country: null,
state: null,
city: null
}
location can never be null, only its properties can be.
How should I do these validations?
You must set the default of location to null using mixed.default(value) like this:
location: yup
.object()
.default(null)
.nullable()
.shape({
country: yup.string().required(),
state: yup.string().required(),
city: yup.string().required()
})
Update:
location can never be null, only its properties can be.
You can do it like this:
location: object()
.shape({
country: string().default(null).nullable().test(
value => value === null || value,
),
state: string().default(null).nullable().test(
value => value === null || value,
),
city: string().default(null).nullable().test(
value => value === null || value,
)
})

Resources