|
|
@@ -18,7 +18,7 @@ Some use-cases for custom fields include:
|
|
|
* Adding a longitude and latitude to the `StockLocation` for use in selecting the closest location to a customer.
|
|
|
|
|
|
:::note
|
|
|
-Custom fields are not solely restricted to Vendure's native entities though, it's also possible to add support for custom fields to your own custom entities. See: [Supporting custom fields](/guides/developer-guide/database-entity/#supporting-custom-fields)
|
|
|
+Custom fields are not solely restricted to Vendure's native entities though, it's also possible to add support for custom fields to your own custom entities. See: [Supporting custom fields](/guides/developer-guide/database-entity/#supporting-custom-fields)
|
|
|
:::
|
|
|
|
|
|
## Defining custom fields
|
|
|
@@ -61,15 +61,15 @@ mutation {
|
|
|
id: 1
|
|
|
// highlight-start
|
|
|
customFields: {
|
|
|
- infoUrl: "https://some-url.com",
|
|
|
- downloadable: true,
|
|
|
+ infoUrl: "https://some-url.com",
|
|
|
+ downloadable: true,
|
|
|
}
|
|
|
// highlight-end
|
|
|
translations: [
|
|
|
- // highlight-next-line
|
|
|
- { languageCode: en, customFields: { shortName: "foo" } }
|
|
|
+ // highlight-next-line
|
|
|
+ { languageCode: en, customFields: { shortName: "foo" } }
|
|
|
]
|
|
|
- }) {
|
|
|
+ }) {
|
|
|
id
|
|
|
name
|
|
|
// highlight-start
|
|
|
@@ -88,17 +88,17 @@ mutation {
|
|
|
|
|
|
```json
|
|
|
{
|
|
|
- "data": {
|
|
|
- "product": {
|
|
|
- "id": "1",
|
|
|
- "name": "Laptop",
|
|
|
- "customFields": {
|
|
|
- "infoUrl": "https://some-url.com",
|
|
|
- "downloadable": true,
|
|
|
- "shortName": "foo"
|
|
|
- }
|
|
|
+ "data": {
|
|
|
+ "product": {
|
|
|
+ "id": "1",
|
|
|
+ "name": "Laptop",
|
|
|
+ "customFields": {
|
|
|
+ "infoUrl": "https://some-url.com",
|
|
|
+ "downloadable": true,
|
|
|
+ "shortName": "foo"
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
}
|
|
|
```
|
|
|
|
|
|
@@ -111,15 +111,15 @@ The custom fields will also extend the filter and sort options available to the
|
|
|
query {
|
|
|
products(options: {
|
|
|
// highlight-start
|
|
|
- filter: {
|
|
|
- infoUrl: { contains: "new" },
|
|
|
- downloadable: { eq: true }
|
|
|
+ filter: {
|
|
|
+ infoUrl: { contains: "new" },
|
|
|
+ downloadable: { eq: true }
|
|
|
},
|
|
|
sort: {
|
|
|
infoUrl: ASC
|
|
|
}
|
|
|
// highlight-end
|
|
|
- }) {
|
|
|
+ }) {
|
|
|
items {
|
|
|
id
|
|
|
name
|
|
|
@@ -135,7 +135,6 @@ query {
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-
|
|
|
## Available custom field types
|
|
|
|
|
|
The following types are available for custom fields:
|
|
|
@@ -353,9 +352,9 @@ const config = {
|
|
|
type: 'string',
|
|
|
// highlight-start
|
|
|
label: [
|
|
|
- {languageCode: LanguageCode.en, value: 'Info URL'},
|
|
|
- {languageCode: LanguageCode.de, value: 'Info-URL'},
|
|
|
- {languageCode: LanguageCode.es, value: 'URL de información'},
|
|
|
+ { languageCode: LanguageCode.en, value: 'Info URL' },
|
|
|
+ { languageCode: LanguageCode.de, value: 'Info-URL' },
|
|
|
+ { languageCode: LanguageCode.es, value: 'URL de información' },
|
|
|
],
|
|
|
// highlight-end
|
|
|
},
|
|
|
@@ -382,9 +381,9 @@ const config = {
|
|
|
type: 'string',
|
|
|
// highlight-start
|
|
|
description: [
|
|
|
- {languageCode: LanguageCode.en, value: 'A URL to more information about the product'},
|
|
|
- {languageCode: LanguageCode.de, value: 'Eine URL zu weiteren Informationen über das Produkt'},
|
|
|
- {languageCode: LanguageCode.es, value: 'Una URL con más información sobre el producto'},
|
|
|
+ { languageCode: LanguageCode.en, value: 'A URL to more information about the product' },
|
|
|
+ { languageCode: LanguageCode.de, value: 'Eine URL zu weiteren Informationen über das Produkt' },
|
|
|
+ { languageCode: LanguageCode.es, value: 'Una URL con más información sobre el producto' },
|
|
|
],
|
|
|
// highlight-end
|
|
|
},
|
|
|
@@ -558,9 +557,9 @@ const config = {
|
|
|
|
|
|
// If a localized error message is required, return an array of LocalizedString objects.
|
|
|
return [
|
|
|
- {languageCode: LanguageCode.en, value: 'The URL must start with "http"'},
|
|
|
- {languageCode: LanguageCode.de, value: 'Die URL muss mit "http" beginnen'},
|
|
|
- {languageCode: LanguageCode.es, value: 'La URL debe comenzar con "http"'},
|
|
|
+ { languageCode: LanguageCode.en, value: 'The URL must start with "http"' },
|
|
|
+ { languageCode: LanguageCode.de, value: 'Die URL muss mit "http" beginnen' },
|
|
|
+ { languageCode: LanguageCode.es, value: 'La URL debe comenzar con "http"' },
|
|
|
];
|
|
|
}
|
|
|
},
|
|
|
@@ -606,7 +605,7 @@ to view or update the field.
|
|
|
|
|
|
In the Admin UI, the custom field will not be displayed if the current administrator lacks the required permission.
|
|
|
|
|
|
-In the GraphQL API, if the current user does not have the required permission, then the field will always return `null`.
|
|
|
+In the GraphQL API, if the current user does not have the required permission, then the field will always return `null`.
|
|
|
Attempting to set the value of a field for which the user does not have the required permission will cause the mutation to fail
|
|
|
with an error.
|
|
|
|
|
|
@@ -632,7 +631,7 @@ const config = {
|
|
|
// and the user must have at least one of the permissions
|
|
|
// to access the field.
|
|
|
requiresPermission: [
|
|
|
- Permission.SuperAdmin,
|
|
|
+ Permission.SuperAdmin,
|
|
|
Permission.ReadShippingMethod,
|
|
|
],
|
|
|
// highlight-end
|
|
|
@@ -700,8 +699,8 @@ const config = {
|
|
|
type: 'string',
|
|
|
// highlight-start
|
|
|
options: [
|
|
|
- {value: 'new', label: [{languageCode: LanguageCode.en, value: 'New'}]},
|
|
|
- {value: 'used', label: [{languageCode: LanguageCode.en, value: 'Used'}]},
|
|
|
+ { value: 'new', label: [{ languageCode: LanguageCode.en, value: 'New' }] },
|
|
|
+ { value: 'used', label: [{ languageCode: LanguageCode.en, value: 'Used' }] },
|
|
|
],
|
|
|
// highlight-end
|
|
|
},
|
|
|
@@ -940,7 +939,7 @@ query {
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-Struct fields support many of the same properties as other custom fields, such as `list`, `label`, `description`, `validate`, `ui` and
|
|
|
+Struct fields support many of the same properties as other custom fields, such as `list`, `label`, `description`, `validate`, `ui` and
|
|
|
type-specific properties such as `options` and `pattern` for string types.
|
|
|
|
|
|
:::note
|
|
|
@@ -963,8 +962,8 @@ const config = {
|
|
|
type: 'string',
|
|
|
// highlight-start
|
|
|
options: [
|
|
|
- {value: 'red', label: [{languageCode: LanguageCode.en, value: 'Red'}]},
|
|
|
- {value: 'blue', label: [{languageCode: LanguageCode.en, value: 'Blue'}]},
|
|
|
+ { value: 'red', label: [{ languageCode: LanguageCode.en, value: 'Red' }] },
|
|
|
+ { value: 'blue', label: [{ languageCode: LanguageCode.en, value: 'Blue' }] },
|
|
|
],
|
|
|
// highlight-end
|
|
|
},
|
|
|
@@ -1192,20 +1191,20 @@ const config: VendureConfig = {
|
|
|
customFields: {
|
|
|
Product: [
|
|
|
// Rich text editor
|
|
|
- {name: 'additionalInfo', type: 'text', ui: {component: 'rich-text-form-input'}},
|
|
|
+ { name: 'additionalInfo', type: 'text', ui: { component: 'rich-text-form-input' } },
|
|
|
// JSON editor
|
|
|
- {name: 'specs', type: 'text', ui: {component: 'json-editor-form-input'}},
|
|
|
+ { name: 'specs', type: 'text', ui: { component: 'json-editor-form-input' } },
|
|
|
// Numeric with suffix
|
|
|
{
|
|
|
name: 'weight',
|
|
|
type: 'int',
|
|
|
- ui: {component: 'number-form-input', suffix: 'g'},
|
|
|
+ ui: { component: 'number-form-input', suffix: 'g' },
|
|
|
},
|
|
|
// Currency input
|
|
|
{
|
|
|
name: 'RRP',
|
|
|
type: 'int',
|
|
|
- ui: {component: 'currency-form-input'},
|
|
|
+ ui: { component: 'currency-form-input' },
|
|
|
},
|
|
|
// Select with options
|
|
|
{
|
|
|
@@ -1214,8 +1213,8 @@ const config: VendureConfig = {
|
|
|
ui: {
|
|
|
component: 'select-form-input',
|
|
|
options: [
|
|
|
- {value: 'static', label: [{languageCode: LanguageCode.en, value: 'Static'}]},
|
|
|
- {value: 'dynamic', label: [{languageCode: LanguageCode.en, value: 'Dynamic'}]},
|
|
|
+ { value: 'static', label: [{ languageCode: LanguageCode.en, value: 'Static' }] },
|
|
|
+ { value: 'dynamic', label: [{ languageCode: LanguageCode.en, value: 'Dynamic' }] },
|
|
|
],
|
|
|
},
|
|
|
},
|
|
|
@@ -1247,7 +1246,6 @@ The various configuration options for each of the built-in form input (e.g. `su
|
|
|
|
|
|
If none of the built-in form input components are suitable, you can create your own. This is a more advanced topic which is covered in detail in the [Custom Form Input Components](/guides/extending-the-admin-ui/custom-form-inputs/) guide.
|
|
|
|
|
|
-
|
|
|
## Tabbed custom fields
|
|
|
|
|
|
With a large, complex project, it's common for lots of custom fields to be required. This can get visually noisy in the UI, so Vendure supports tabbed custom fields. Just specify the tab name in the `ui` object, and those fields with the same tab name will be grouped in the UI! The tab name can also be a translation token if you need to support multiple languages.
|
|
|
@@ -1263,19 +1261,17 @@ const config = {
|
|
|
// ...
|
|
|
customFields: {
|
|
|
Product: [
|
|
|
- { name: 'additionalInfo', type: 'text', ui: {component: 'rich-text-form-input'} },
|
|
|
- { name: 'specs', type: 'text', ui: {component: 'json-editor-form-input'} },
|
|
|
- { name: 'width', type: 'int', ui: {tab: 'Shipping'} },
|
|
|
- { name: 'height', type: 'int', ui: {tab: 'Shipping'} },
|
|
|
- { name: 'depth', type: 'int', ui: {tab: 'Shipping'} },
|
|
|
- { name: 'weight', type: 'int', ui: {tab: 'Shipping'} },
|
|
|
+ { name: 'additionalInfo', type: 'text', ui: { component: 'rich-text-form-input' } },
|
|
|
+ { name: 'specs', type: 'text', ui: { component: 'json-editor-form-input' } },
|
|
|
+ { name: 'width', type: 'int', ui: { tab: 'Shipping' } },
|
|
|
+ { name: 'height', type: 'int', ui: { tab: 'Shipping' } },
|
|
|
+ { name: 'depth', type: 'int', ui: { tab: 'Shipping' } },
|
|
|
+ { name: 'weight', type: 'int', ui: { tab: 'Shipping' } },
|
|
|
],
|
|
|
},
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-
|
|
|
-
|
|
|
## TypeScript Typings
|
|
|
|
|
|
Because custom fields are generated at run-time, TypeScript has no way of knowing about them based on your
|
|
|
@@ -1343,3 +1339,44 @@ One way to ensure that your custom field typings always get imported first is to
|
|
|
For a working example of this setup, see the [real-world-vendure repo](https://github.com/vendure-ecommerce/real-world-vendure/blob/master/src/plugins/reviews/types.ts)
|
|
|
:::
|
|
|
|
|
|
+## Special cases
|
|
|
+
|
|
|
+Beyond adding custom fields to the corresponding GraphQL types, and updating paginated list sort & filter options, there are a few special cases where adding custom fields to certain entities will result in further API changes.
|
|
|
+
|
|
|
+### OrderLine custom fields
|
|
|
+
|
|
|
+When you define custom fields on the `OrderLine` entity, the following API changes are also automatically provided by Vendure:
|
|
|
+
|
|
|
+- Shop API: [addItemToOrder](/reference/graphql-api/shop/mutations#additemtoorder) will have a 3rd input argument, `customFields`, which allows custom field values to be set when adding an item to the order.
|
|
|
+- Shop API: [adjustOrderLine](/reference/graphql-api/shop/mutations#additemtoorder) will have a 3rd input argument, `customFields`, which allows custom field values to be updated.
|
|
|
+- Admin API: the equivalent mutations for manipulating draft orders and for modifying and order will also have inputs to allow custom field values to be set.
|
|
|
+
|
|
|
+:::info
|
|
|
+To see an example of this in practice, see the [Configurable Product guide](/guides/how-to/configurable-products/)
|
|
|
+:::
|
|
|
+
|
|
|
+### Order custom fields
|
|
|
+
|
|
|
+When you define custom fields on the `Order` entity, the following API changes are also automatically provided by Vendure:
|
|
|
+
|
|
|
+- Admin API: [modifyOrder](/reference/graphql-api/admin/mutations#modifyorder) will have a `customFields` field on the input object.
|
|
|
+
|
|
|
+### ShippingMethod custom fields
|
|
|
+
|
|
|
+When you define custom fields on the `ShippingMethod` entity, the following API changes are also automatically provided by Vendure:
|
|
|
+
|
|
|
+- Shop API: [eligibleShippingMethods](/reference/graphql-api/shop/queries#eligibleshippingmethods) will have public custom fields available on the result.
|
|
|
+
|
|
|
+### PaymentMethod custom fields
|
|
|
+
|
|
|
+When you define custom fields on the `PaymentMethod` entity, the following API changes are also automatically provided by Vendure:
|
|
|
+
|
|
|
+- Shop API: [eligiblePaymentMethods](/reference/graphql-api/shop/queries#eligiblepaymentmethods) will have public custom fields available on the result.
|
|
|
+
|
|
|
+### Customer custom fields
|
|
|
+
|
|
|
+When you define custom fields on the `Customer` entity, the following API changes are also automatically provided by Vendure:
|
|
|
+
|
|
|
+- Shop API: [registerCustomerAccount](/reference/graphql-api/shop/mutations#registercustomeraccount) will have have a `customFields` field on the input
|
|
|
+ object.
|
|
|
+
|