DEV Community

prasanna malla
prasanna malla

Posted on

2

Adding fields to existing types in Vendure

Custom fields allow you to add your own custom data properties to many of the Vendure entities. The entities which may have custom fields defined are listed in the CustomFields documentation. While this approach is flexible it becomes quite cumbersome when dealing with a huge number of fields, for example, ingredients for food products. Rather than adding each ingredient as a custom field on the product, we can create an Ingredient entity and have ProductVariant extend it.

import { DeepPartial, ProductVariant, VendureEntity } from '@vendure/core';
import { Entity, Column, ManyToMany, JoinTable } from 'typeorm';

@Entity()
export class Ingredient extends VendureEntity {
    constructor(input?: DeepPartial<Ingredient>) {
        super(input);
    }

    @Column({ nullable: false })
    name!: string;

    @ManyToMany(type => ProductVariant, { nullable: false })
    @JoinTable()
    productVariants!: ProductVariant[];
}
Enter fullscreen mode Exit fullscreen mode

Add the entity, types and resolver to VendureConfig

@VendurePlugin({
    imports: [PluginCommonModule],
    entities: [Ingredient],
    adminApiExtensions: {
        schema: gql`
            type Ingredient implements Node {
                id: ID!
                name: String!
                productVariants: [ProductVariant!]!
            }

            extend type ProductVariant {
                ingredients: [Ingredient!]
            }
        `,
        resolvers: [ProductVariantEntityResolver],
    },
})
Enter fullscreen mode Exit fullscreen mode

Add the field resolver for the ingredients field in ProductVariant entity

import { Parent, ResolveField, Resolver } from '@nestjs/graphql';
import { Ctx, RequestContext, ProductVariant, TransactionalConnection } from '@vendure/core';
import { Ingredient } from '../entity/ingredient.entity';

@Resolver('ProductVariant')
export class ProductVariantEntityResolver {
    constructor(private connection: TransactionalConnection) {}

    @ResolveField()
    ingredients(@Ctx() ctx: RequestContext, @Parent() variant: ProductVariant) {
        return this.connection
            .getRepository(ctx, Ingredient)
            .createQueryBuilder('ing')
            .leftJoin('ing.productVariants', 'variant')
            .where('variant.id = :id', { id: variant.id })
            .getMany();
    }
}
Enter fullscreen mode Exit fullscreen mode

Since Ingredient entity owns the relation, ProductVariant entity does not know about it directly so we are using the above field resolver. Finally, you can query productVariants with ingredients sub-selection.

Vendure v2.0 is coming out soon! come share the excitement on slack.

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (0)

nextjs tutorial video

Youtube Tutorial Series 📺

So you built a Next.js app, but you need a clear view of the entire operation flow to be able to identify performance bottlenecks before you launch. But how do you get started? Get the essentials on tracing for Next.js from @nikolovlazar in this video series 👀

Watch the Youtube series

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay