diff --git a/examples/virtual-fields/README.md b/examples/virtual-fields/README.md index f400c8326e..2aacaaa1da 100644 --- a/examples/virtual-fields/README.md +++ b/examples/virtual-fields/README.md @@ -29,7 +29,7 @@ In the locations collection, you have separate text fields to input a city, stat Everything else here are virtual fields: -`location`: Text field providing a formatted location name by concatenating `city + state + country` which is then used as the document title +`location`: Text field providing a formatted location name by concatenating `city + state + country` which is then used as the document title. `events`: Relationship field containing all events associated with the location. @@ -53,9 +53,9 @@ Similarly to Events, you will assign a location to the staff member from the opt This collection uses the following virtual field to format the staff name fields: -`fullTitle`: Text field providing a formatted name by concatenating `title + firstName + lastName` which is then used as the document title +`fullTitle`: Text field providing a formatted name by concatenating `title + firstName + lastName` which is then used as the document title. -In the code, navigate to `src/collections` to see how these fields are functioning and read more about `afterRead` hooks [here](https://payloadcms.com/docs/hooks/fields). +In the code, navigate to `src/collections` to see how these fields are populated and read more about `afterRead` hooks [here](https://payloadcms.com/docs/hooks). ## Questions diff --git a/examples/virtual-fields/src/collections/Events.ts b/examples/virtual-fields/src/collections/Events.ts index 66b20ee040..3fbc064785 100644 --- a/examples/virtual-fields/src/collections/Events.ts +++ b/examples/virtual-fields/src/collections/Events.ts @@ -73,11 +73,20 @@ const Events: CollectionConfig = { { name: 'totalPrice', type: 'number', + access: { + create: () => false, + update: () => false, + }, admin: { description: 'USD', readOnly: true, }, hooks: { + beforeChange: [({ siblingData }) => { + // Mutate the sibling data to prevent DB storage + // eslint-disable-next-line no-param-reassign + siblingData.totalPrice = undefined; + }], afterRead: [getTotalPrice], }, }, diff --git a/examples/virtual-fields/src/collections/Location.ts b/examples/virtual-fields/src/collections/Location.ts index c3c4f9049e..d8bf538281 100644 --- a/examples/virtual-fields/src/collections/Location.ts +++ b/examples/virtual-fields/src/collections/Location.ts @@ -1,10 +1,10 @@ -/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ +/* eslint-disable import/no-extraneous-dependencies */ import payload from 'payload'; import { CollectionConfig, FieldHook } from 'payload/types'; -const formatLocation: FieldHook = async ({ data }) => ( - `${data.city}${data.state ? `, ${data.state},` : ','} ${data.country}` -); +const formatLocation: FieldHook = async ({ data }) => { + return `${data.city}${data.state ? `, ${data.state},` : ','} ${data.country}`; +}; const getLocationStaff: FieldHook = async ({ data }) => { const staff = await payload.find({ @@ -67,10 +67,19 @@ const Locations: CollectionConfig = { label: false, type: 'text', hooks: { + beforeChange: [({ siblingData }) => { + // Mutate the sibling data to prevent DB storage + // eslint-disable-next-line no-param-reassign + siblingData.location = undefined; + }], afterRead: [ formatLocation, ], }, + access: { + create: () => false, + update: () => false, + }, admin: { hidden: true, }, @@ -100,10 +109,19 @@ const Locations: CollectionConfig = { type: 'relationship', relationTo: 'events', hasMany: true, + access: { + create: () => false, + update: () => false, + }, admin: { readOnly: true, }, hooks: { + beforeChange: [({ siblingData }) => { + // Mutate the sibling data to prevent DB storage + // eslint-disable-next-line no-param-reassign + siblingData.events = undefined; + }], afterRead: [getAllEvents], }, }, @@ -113,10 +131,19 @@ const Locations: CollectionConfig = { relationTo: 'staff', hasMany: true, maxDepth: 0, + access: { + create: () => false, + update: () => false, + }, admin: { readOnly: true, }, hooks: { + beforeChange: [({ siblingData }) => { + // Mutate the sibling data to prevent DB storage + // eslint-disable-next-line no-param-reassign + siblingData.staff = undefined; + }], afterRead: [getLocationStaff], }, }, @@ -128,7 +155,16 @@ const Locations: CollectionConfig = { position: 'sidebar', readOnly: true, }, + access: { + create: () => false, + update: () => false, + }, hooks: { + beforeChange: [({ siblingData }) => { + // Mutate the sibling data to prevent DB storage + // eslint-disable-next-line no-param-reassign + siblingData.nextEvent = undefined; + }], afterRead: [getNextEvent], }, }, diff --git a/examples/virtual-fields/src/collections/Staff.ts b/examples/virtual-fields/src/collections/Staff.ts index d06b602991..8cc9535113 100644 --- a/examples/virtual-fields/src/collections/Staff.ts +++ b/examples/virtual-fields/src/collections/Staff.ts @@ -14,7 +14,16 @@ const Staff: CollectionConfig = { { name: 'fullTitle', type: 'text', + access: { + create: () => false, + update: () => false, + }, hooks: { + beforeChange: [({ siblingData }) => { + // Mutate the sibling data to prevent DB storage + // eslint-disable-next-line no-param-reassign + siblingData.fullTitle = undefined; + }], afterRead: [ populateFullTitle, ],