I'm not sure if I'm wording this correctly, please bear with me.
How to relate a form field inside a type to a parent type?
I have a form with fields to fill-in namely:
name: '',
description: '',
subtotal: '',
tax: ''
and these inputs in the form will be published in a list/table.
In my schema, I have this for the form
export type CartItemInput = {
description?: string
name: string
tax?: number
subtotal?: number
}
export type CartItem = {
id: string
name: string
price: number
tax: number
subTotal: number
description: string
}
export type Cart = {
id: string
customerId: string
total: number
subTotal: number
items: CartItem[]
}
I receive an error saying. "The variables input contain a field name 'subtotal' is not defined for input object type 'CartItemInput'"
Is there anyway to relate 'subtotal' field to the the 'subTotal' in CartItem?
I have tried all of these in my CartItemInput but to no avail.
'subtotal?: Cart'
'subtotal?: CartItem'
'subtotal?: number'
Would really appreciate your inputs here. Thanks
Related
I am building a React form component with TypeScript and want to type the data returned by my form.
My component accepts a prop called "fields" with the following structure:
const fields = [
{
name: "title",
default: "",
data: undefined,
size: 2
},
{
name: "users",
default: [],
data: [{id: 1, ...}]
size: 8
},
]
I would like to find a way to retrieve the type of the data returned by component based on the "field" variable. So, basically, I want to get something like that:
type FormData = {
title: string;
users: Array<{id: number, ...}>
}
The best solution would be to infer a different type depending on the "data" key. If "data" exists, then the field will have the same type as data, otherwise it is the type of the "default" key. All other keys should be ignored.
I believe I should be using generics to achieve this but I am not even sure this is something possible with TS and I have to admit that I can't figure it out...
Has anyone already faced this situation and found a solution to a similar issue ?
Thank you very much!
Based on the given array fields, we can create the type FormData with the following generic type as long as the fields variable was initialized with as const to stop TypeScript from widening the string literals.
const fields = [
{
name: "title",
default: "",
data: undefined,
size: 2
},
{
name: "users",
default: [],
data: [{id: 1}],
size: 8
},
] as const
type FormData<T extends readonly { name: st
[E in T[number] as E["name"]]: E["data"]
? E["default"]
: E["data"]
}
type Result = FormData<typeof fields>
// type Result = {
// title: "";
// users: readonly [{
// readonly id: 1;
// }];
// }
This might or might not work in the context of your component. But you did not show us the component itself. This is a solution based on the information given in your question.
Playground
I am sending a value to yupa via formik. As a result of this value, what can I do to make the necessary checks and return an error message in this style? Since the object has unlimited length, I decided to keep it validated as an object in order not to cause any slowness. I'm solving it with array but the yup part is getting slow.
The body I send:
{
user_id_1: {
name: 'test name', // required
surname: 'test surname', // required
age: 10, // optional
},
user_id_2: {
name: 'test name 2',
surname: 'test surname 2',
},
user_id_3: {
name: 'test name 2',
surname: '',
},
}
The expected error result:
user_id_3: {
surname: 'surname is required',
},
I wrote and tested a code suitable for my question. I want to share the solution with you. The critical point here was that I produced my own method and a custom error message with addMethod. You can check how I did it in the related code example. The inside of the test could be solved with the yup scheme, but I solved it at a simple level with if else. The else part in the test is also important, if I do not delete the object value, it remains in the cache.
code example: codesandbox
Hello guys I need your help,
I am making a simple app where users can create a post about their favorite person so there are different fields to write text, now I've made the functionality for the user to create any new field with a title of their choice like if a person "a" want to add a new field with name age and custom "b" wants to add a new field with name country, so I've made this but how can I get that custom data automatically in my database so if the user will create a new field with any name I want that field and text written in it in my database. Can you help me with that?
and please try to explain to me in a simple manner am just a beginner with mongoDB.
there was a guy who told me to do this with $addFields aggregation but he didn't tell me anything else I saw many documents but am not getting How can I make this done :(
thank you sooooo much in advance. :)
here's my schema for default fields:
const personSchema = new Schema({
firstName: String,
lastName: String,
birthDay: String,
gender: String,
pronouns: String,
relationship: String,
user: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
username: String,
}
});
You simply have to pass the strict option to false while you create your schema!
By default, mongoose will set this option to true so you can't send any unnecessary information to DB!
const personSchema = new Schema({
firstName: String,
lastName: String,
birthDay: String,
gender: String,
pronouns: String,
relationship: String,
user: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
username: String,
}
}, { strict: false });
https://mongoosejs.com/docs/guide.html#strict
I have a custom GraphQL schema for a blogging application for my ReactJS app. The main model type is Post.
Post contains a number of properties that have a custom type eg Gallery: [MediaObject]. The majority of these properties with custom types are missing from the automatically generated CreatePostInput by AWS Amplify CLI. This means that I cannot create a Post object that has these properties with custom type.
The lack of these custom type properties is evident in the AppSync console, under Queries. In the Explorer, go to Mutations, click on CreatePost mutation, and you will see that 6 of the 21 properties for Post are missing. The missing properties are tags, attributes, seo, featuredImage, gallery and createdBy.
They are also missing in the autogenerated graphql schema in api > build > schema.graphql in the react app.
I have made multiple clean projects from scratch, and the problem is reproducible. I have updated the amplify cli to 4.51.2 and still no luck.
I would expect the CreatePostInput to have the associated inputs for all of the fields, not just comments (see the autogenerated CreatePostInput below) eg: attribute: AttributeInput, but these are not generated either. This would allow me to create a Post object that has these custom fields populated. However, only the CommentInput has been generated. What am I doing wrong here, or have I misunderstood something?
Thanks!
Below is my gql schema and both the autogenerated CreatePostInput and CommentInput:
type Post #model {
id: ID
createdBy: User
createdAt: AWSDateTime
updatedAt:AWSDateTime
type: PostType!
title: String!
status: Status
content: String!
excerpt: String
slug: AWSURL
wordpressId: Int
wordpressImageURLs: [AWSURL]
author: String
likes: Int
tags: [Tag]
attributes: Attribute
seo: Seo
featuredImage: MediaObject
gallery: [MediaObject]
comments: [Comment]
numberOfComments: Int
}
type User #model {
id: ID
username: String!
firstName: String
lastName: String
email: AWSEmail!
avatar: MediaObject
location: String
createdAt: AWSDateTime
updatedAt: AWSDateTime
Posts: [Post]
}
type Tag #model {
id: ID
postIds: [ID]
name: String!
}
type Attribute #model {
id: ID
postId: ID
link: String
imgUrl: AWSURL
ogImage: AWSURL
ogDescription: String
canonicalLink: AWSURL
}
type Seo #model {
id: ID
postId: ID
metaRobotsNoIndex: String
metaRobotsNoFollow: String
canonical: AWSURL
metaDesc: String
opengraphDescription: String
opengraphModifiedTime: AWSDateTime
opengraphPublishedTime: AWSDateTime
opengraphTitle: String
opengraphUrl: AWSURL
opengraphImage: AWSURL
twitterDescription: String
twitterImage: String
twitterTitle: String
schemaSeo: String
}
type Comment
{
id: ID
postId: ID!
createdBy: ID
author: String
createdAt: AWSDateTime
text: String!
likes: Int
}
type MediaObject #model {
id: ID
linkedId: ID
createdBy: ID
mediaItemUrl: AWSURL
srcSet: String
medium: AWSURL
thumb: AWSURL
sourceURL: AWSURL
description: String
bucket: String
region: String
key: String
type: MediaObjectType
}
type Like #model {
id: ID!
objectVotedOnID: ID!
createdBy: ID
createdAt: AWSDateTime
likeOn: LikeOnType
}
enum PostType {
TOOLS
BLOGS
INSPIRATIONS
NEWS
POSTS
NEWSLETTERS
}
enum LikeOnType {
POST
COMMENT
}
enum Status {
PUBLISH
DRAFT
}
enum MediaObjectType {
IMAGE
VIDEO
AUDIO
}
Autogenerated (only CreatePostInput and CommentInput have been included for brevity), found in amplify > backend > api > build > schema.graphql:
input CreatePostInput {
id: ID
createdAt: AWSDateTime
updatedAt: AWSDateTime
type: PostType!
title: String!
status: Status
content: String!
excerpt: String
slug: AWSURL
wordpressId: Int
wordpressImageURLs: [AWSURL]
author: String
likes: Int
comments: [CommentInput]
numberOfComments: Int
}
input CommentInput {
id: ID
postId: ID!
createdBy: ID
author: String
createdAt: AWSDateTime
text: String!
likes: Int
}
At least for the example, you cited, Post and MediaObject have a one-to-many relationship. That is, a single Post has many MediaObjects. You won't see the many relations of a one-to-many generated on the parent object for mutations.
When creating a parent object that has children, you'll need to do this in 2 steps.
Create the parent object, and return the id.
Using the parentId, create the N child objects.
Here is some documentation from Amplify on how to do this: https://docs.amplify.aws/cli/graphql-transformer/connection#has-many
To anyone else that notices this strange behaviour: The reason why CommentInput is included in the CreatePostInput, whilst the other custom types are not, is because Comment was the only type that I had forgot to label with an #model directive. I assume that this means that AppSync then views this type on the comments field as a set of nested fields, rather than an object with its own DynamoDB table. I have asked the AWS Amplify team and will update this answer when I hear more from them.
I am using Formik to create a form of a book library where each item in the list would look like:
author: {
name: 'string',
titles: ['string']
}
I am having trouble trying to make a schema with Yup to validate those fields. I have:
schema = Yup.object().shape({
author: Yup.object().shape({
name: Yup.string().min().max().required('...')
}),
author: Yup.array().of(
Yup.object().shape({
titles: Yup.string().min().max().required('...')
})
)
});
The initial values are also:
{
author: {name: ''},
author: [{ titles: '' }]
}
My validation works for the array but not the name. I am assuming the issue is that I cannot have the same name for both of the elements in the object, however I do not know how to combine the two fields in both the initial values as well as the schema. I looked through Yup API and I noticed they had mixed() but I didn't understand how to implement with what I need. Is this way possible or would having validation for both of these possible?
Author is not an array, it's an object which contains an array and a string. Also, you're defining it twice:
schema = Yup.object().shape({
author: Yup.object().shape({
name: Yup.string().min().max().required('...'),
titles: Yup.arrayOf(Yup.string())
}),
});
Confused about why you have 2 author keys. The schema above corresponds to:
{
author: {
name: "hehyryg",
titles: ["title", "title2"]
}
}