Skip to main content

Configurable Products

A "configurable product" is one where aspects can be configured by the customer, and are unrelated to the product's variants. Examples include:

  • Engraving text on an item
  • A gift message inserted with the packaging
  • An uploaded image to be printed on a t-shirt

In Vendure this is done by defining one or more custom fields on the OrderLine entity.

Defining custom fields

Let's take the example of an engraving service. Some products can be engraved, others cannot. We will record this information in a custom field on the ProductVariant entity:

src/vendure-config.ts
import { VendureConfig } from '@vendure/core';

export const config: VendureConfig = {
// ...
customFields: {
ProductVariant: [
{
name: 'engravable',
type: 'boolean',
defaultValue: false,
label: [
{ languageCode: LanguageCode.en, value: 'Engravable' },
],
},
],
},
};

For those variants that are engravable, we need to be able to record the text to be engraved. This is done by defining a custom field on the OrderLine entity:

src/vendure-config.ts
import { VendureConfig } from '@vendure/core';

export const config: VendureConfig = {
// ...
customFields: {
OrderLine: [
{
name: 'engravingText',
type: 'string',
validate: value => {
if (value.length > 100) {
return 'Engraving text must be less than 100 characters';
}
},
label: [
{ languageCode: LanguageCode.en, value: 'Engraving text' },
],
},
]
},
};

Setting the custom field value

Once the custom fields are defined, the addItemToOrder mutation will have a third argument available, which accepts values for the custom field defined above:

mutation {
addItemToOrder(
productVariantId: "42"
quantity: 1
customFields: {
engravingText: "Thanks for all the fish!"
}
) {
...on Order {
id
lines {
id
quantity
customFields {
engravingText
}
}
}
}
}

Your storefront application will need to provide a <textarea> for the customer to enter the engraving text, which would be displayed conditionally depending on the value of the engravable custom field on the ProductVariant.

Modifying the price

The values of these OrderLine custom fields can even be used to modify the price. This is done by defining a custom OrderItemPriceCalculationStrategy.

Let's say that our engraving service costs and extra $10 on top of the regular price of the product variant. Here's a strategy to implement this:

src/engraving-price-calculation-strategy.ts
import {
RequestContext, PriceCalculationResult,
ProductVariant, OrderItemPriceCalculationStrategy
} from '@vendure/core';

export class EngravingPriceStrategy implements OrderItemPriceCalculationStrategy {

calculateUnitPrice(
ctx: RequestContext,
productVariant: ProductVariant,
customFields: { engravingText?: string },
) {
let price = productVariant.listPrice;
if (customFields.engravingText) {
// Add $10 for engraving
price += 1000;
}
return {
price,
priceIncludesTax: productVariant.listPriceIncludesTax,
};
}
}

This is then added to the config:

src/vendure-config.ts
import { VendureConfig } from '@vendure/core';
import { EngravingPriceStrategy } from './engraving-price-calculation-strategy';

export const config: VendureConfig = {
// ...
orderOptions: {
orderItemPriceCalculationStrategy: new EngravingPriceStrategy(),
},
};