chore: bump prettier, re-enable prettier for docs (#11695)
## Introducing Prettier for docs
Prettier [was originally disabled for our docs as it didn't support MDX
2.0](1fa636417f),
outputting invalid MDX syntax.
This has since been fixed - prettier now supports MDX 2.0.
## Reducing print width
This also reduces the print width for the docs folder from 100 to 70.
Our docs code field are very narrow - this should help make code more
readable.
**Before**

**After**

**Before**

**After**

This commit is contained in:
@@ -8,7 +8,6 @@
|
|||||||
**/dist/**
|
**/dist/**
|
||||||
**/node_modules
|
**/node_modules
|
||||||
**/temp
|
**/temp
|
||||||
**/docs/**
|
|
||||||
tsconfig.json
|
tsconfig.json
|
||||||
packages/payload/*.js
|
packages/payload/*.js
|
||||||
packages/payload/*.d.ts
|
packages/payload/*.d.ts
|
||||||
|
|||||||
6
docs/.prettierrc.json
Normal file
6
docs/.prettierrc.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "all",
|
||||||
|
"printWidth": 80,
|
||||||
|
"semi": false
|
||||||
|
}
|
||||||
@@ -11,11 +11,12 @@ Collection Access Control is [Access Control](../access-control/overview) used t
|
|||||||
To add Access Control to a Collection, use the `access` property in your [Collection Config](../configuration/collections):
|
To add Access Control to a Collection, use the `access` property in your [Collection Config](../configuration/collections):
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import type { CollectionConfig } from 'payload';
|
import type { CollectionConfig } from 'payload'
|
||||||
|
|
||||||
export const CollectionWithAccessControl: CollectionConfig = {
|
export const CollectionWithAccessControl: CollectionConfig = {
|
||||||
// ...
|
// ...
|
||||||
access: { // highlight-line
|
access: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -53,7 +54,7 @@ export const CollectionWithAccessControl: CollectionConfig = {
|
|||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Function | Allows/Denies Access |
|
| Function | Allows/Denies Access |
|
||||||
| ----------------------- | -------------------------------------------- |
|
| ------------ | -------------------------------------------------------------------- |
|
||||||
| **`create`** | Used in the `create` operation. [More details](#create). |
|
| **`create`** | Used in the `create` operation. [More details](#create). |
|
||||||
| **`read`** | Used in the `find` and `findByID` operations. [More details](#read). |
|
| **`read`** | Used in the `find` and `findByID` operations. [More details](#read). |
|
||||||
| **`update`** | Used in the `update` operation. [More details](#update). |
|
| **`update`** | Used in the `update` operation. [More details](#update). |
|
||||||
@@ -62,14 +63,14 @@ The following options are available:
|
|||||||
If a Collection supports [`Authentication`](../authentication/overview), the following additional options are available:
|
If a Collection supports [`Authentication`](../authentication/overview), the following additional options are available:
|
||||||
|
|
||||||
| Function | Allows/Denies Access |
|
| Function | Allows/Denies Access |
|
||||||
| ----------------------- | -------------------------------------------------------------- |
|
| ------------ | ---------------------------------------------------------------------------------------- |
|
||||||
| **`admin`** | Used to restrict access to the [Admin Panel](../admin/overview). [More details](#admin). |
|
| **`admin`** | Used to restrict access to the [Admin Panel](../admin/overview). [More details](#admin). |
|
||||||
| **`unlock`** | Used to restrict which users can access the `unlock` operation. [More details](#unlock). |
|
| **`unlock`** | Used to restrict which users can access the `unlock` operation. [More details](#unlock). |
|
||||||
|
|
||||||
If a Collection supports [Versions](../versions/overview), the following additional options are available:
|
If a Collection supports [Versions](../versions/overview), the following additional options are available:
|
||||||
|
|
||||||
| Function | Allows/Denies Access |
|
| Function | Allows/Denies Access |
|
||||||
| ------------------ | ---------------------------------------------------------------------------------------------------------------------- |
|
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| **`readVersions`** | Used to control who can read versions, and who can't. Will automatically restrict the Admin UI version viewing access. [More details](#read-versions). |
|
| **`readVersions`** | Used to control who can read versions, and who can't. Will automatically restrict the Admin UI version viewing access. [More details](#read-versions). |
|
||||||
|
|
||||||
### Create
|
### Create
|
||||||
@@ -96,7 +97,7 @@ export const CollectionWithCreateAccess: CollectionConfig = {
|
|||||||
The following arguments are provided to the `create` function:
|
The following arguments are provided to the `create` function:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ---------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
| ---------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`req`** | The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object containing the currently authenticated `user`. |
|
| **`req`** | The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object containing the currently authenticated `user`. |
|
||||||
| **`data`** | The data passed to create the document with. |
|
| **`data`** | The data passed to create the document with. |
|
||||||
|
|
||||||
@@ -122,8 +123,9 @@ export const CollectionWithReadAccess: CollectionConfig = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Tip:**
|
**Tip:** Return a [Query](../queries/overview) to limit the Documents to only
|
||||||
Return a [Query](../queries/overview) to limit the Documents to only those that match the constraint. This can be helpful to restrict users' access to specific Documents. [More details](../queries/overview).
|
those that match the constraint. This can be helpful to restrict users' access
|
||||||
|
to specific Documents. [More details](../queries/overview).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
As your application becomes more complex, you may want to define your function in a separate file and import them into your Collection Config:
|
As your application becomes more complex, you may want to define your function in a separate file and import them into your Collection Config:
|
||||||
@@ -150,7 +152,7 @@ export const canReadPage: Access = ({ req: { user } }) => {
|
|||||||
The following arguments are provided to the `read` function:
|
The following arguments are provided to the `read` function:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| --------- | -------------------------------------------------------------------------- |
|
| --------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`req`** | The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object containing the currently authenticated `user`. |
|
| **`req`** | The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object containing the currently authenticated `user`. |
|
||||||
| **`id`** | `id` of document requested, if within `findByID`. |
|
| **`id`** | `id` of document requested, if within `findByID`. |
|
||||||
|
|
||||||
@@ -167,7 +169,7 @@ export const CollectionWithUpdateAccess: CollectionConfig = {
|
|||||||
// ...
|
// ...
|
||||||
access: {
|
access: {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
update: ({ req: { user }}) => {
|
update: ({ req: { user } }) => {
|
||||||
return Boolean(user)
|
return Boolean(user)
|
||||||
},
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
@@ -176,8 +178,9 @@ export const CollectionWithUpdateAccess: CollectionConfig = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Tip:**
|
**Tip:** Return a [Query](../queries/overview) to limit the Documents to only
|
||||||
Return a [Query](../queries/overview) to limit the Documents to only those that match the constraint. This can be helpful to restrict users' access to specific Documents. [More details](../queries/overview).
|
those that match the constraint. This can be helpful to restrict users' access
|
||||||
|
to specific Documents. [More details](../queries/overview).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
As your application becomes more complex, you may want to define your function in a separate file and import them into your Collection Config:
|
As your application becomes more complex, you may want to define your function in a separate file and import them into your Collection Config:
|
||||||
@@ -199,7 +202,7 @@ export const canUpdateUser: Access = ({ req: { user }, id }) => {
|
|||||||
The following arguments are provided to the `update` function:
|
The following arguments are provided to the `update` function:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ---------- | -------------------------------------------------------------------------- |
|
| ---------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`req`** | The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object containing the currently authenticated `user`. |
|
| **`req`** | The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object containing the currently authenticated `user`. |
|
||||||
| **`id`** | `id` of document requested to update. |
|
| **`id`** | `id` of document requested to update. |
|
||||||
| **`data`** | The data passed to update the document with. |
|
| **`data`** | The data passed to update the document with. |
|
||||||
@@ -217,7 +220,7 @@ export const CollectionWithDeleteAccess: CollectionConfig = {
|
|||||||
// ...
|
// ...
|
||||||
access: {
|
access: {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
delete: ({ req: { user }}) => {
|
delete: ({ req: { user } }) => {
|
||||||
return Boolean(user)
|
return Boolean(user)
|
||||||
},
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
@@ -270,7 +273,7 @@ export const CollectionWithAdminAccess: CollectionConfig = {
|
|||||||
// ...
|
// ...
|
||||||
access: {
|
access: {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
admin: ({ req: { user }}) => {
|
admin: ({ req: { user } }) => {
|
||||||
return Boolean(user)
|
return Boolean(user)
|
||||||
},
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
@@ -281,7 +284,7 @@ export const CollectionWithAdminAccess: CollectionConfig = {
|
|||||||
The following arguments are provided to the `admin` function:
|
The following arguments are provided to the `admin` function:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| --------- | -------------------------------------------------------------------------- |
|
| --------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`req`** | The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object containing the currently authenticated `user`. |
|
| **`req`** | The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object containing the currently authenticated `user`. |
|
||||||
|
|
||||||
### Unlock
|
### Unlock
|
||||||
@@ -297,7 +300,7 @@ export const CollectionWithUnlockAccess: CollectionConfig = {
|
|||||||
// ...
|
// ...
|
||||||
access: {
|
access: {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
unlock: ({ req: { user }}) => {
|
unlock: ({ req: { user } }) => {
|
||||||
return Boolean(user)
|
return Boolean(user)
|
||||||
},
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
@@ -308,7 +311,7 @@ export const CollectionWithUnlockAccess: CollectionConfig = {
|
|||||||
The following arguments are provided to the `unlock` function:
|
The following arguments are provided to the `unlock` function:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| --------- | -------------------------------------------------------------------------- |
|
| --------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`req`** | The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object containing the currently authenticated `user`. |
|
| **`req`** | The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object containing the currently authenticated `user`. |
|
||||||
|
|
||||||
### Read Versions
|
### Read Versions
|
||||||
@@ -324,7 +327,7 @@ export const CollectionWithVersionsAccess: CollectionConfig = {
|
|||||||
// ...
|
// ...
|
||||||
access: {
|
access: {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
readVersions: ({ req: { user }}) => {
|
readVersions: ({ req: { user } }) => {
|
||||||
return Boolean(user)
|
return Boolean(user)
|
||||||
},
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
@@ -335,5 +338,5 @@ export const CollectionWithVersionsAccess: CollectionConfig = {
|
|||||||
The following arguments are provided to the `readVersions` function:
|
The following arguments are provided to the `readVersions` function:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| --------- | -------------------------------------------------------------------------- |
|
| --------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`req`** | The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object containing the currently authenticated `user`. |
|
| **`req`** | The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object containing the currently authenticated `user`. |
|
||||||
|
|||||||
@@ -11,19 +11,21 @@ Field Access Control is [Access Control](../access-control/overview) used to res
|
|||||||
To add Access Control to a Field, use the `access` property in your [Field Config](../fields/overview):
|
To add Access Control to a Field, use the `access` property in your [Field Config](../fields/overview):
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import type { Field } from 'payload';
|
import type { Field } from 'payload'
|
||||||
|
|
||||||
export const FieldWithAccessControl: Field = {
|
export const FieldWithAccessControl: Field = {
|
||||||
// ...
|
// ...
|
||||||
access: { // highlight-line
|
access: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Note:**
|
**Note:** Field Access Controls does not support returning
|
||||||
Field Access Controls does not support returning [Query](../queries/overview) constraints like [Collection Access Control](./collections) does.
|
[Query](../queries/overview) constraints like [Collection Access
|
||||||
|
Control](./collections) does.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Config Options
|
## Config Options
|
||||||
@@ -56,7 +58,7 @@ export const Posts: CollectionConfig = {
|
|||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Function | Purpose |
|
| Function | Purpose |
|
||||||
| ----------------------- | -------------------------------------------------------------------------------- |
|
| ------------ | ---------------------------------------------------------------------------------------------------------- |
|
||||||
| **`create`** | Allows or denies the ability to set a field's value when creating a new document. [More details](#create). |
|
| **`create`** | Allows or denies the ability to set a field's value when creating a new document. [More details](#create). |
|
||||||
| **`read`** | Allows or denies the ability to read a field's value. [More details](#read). |
|
| **`read`** | Allows or denies the ability to read a field's value. [More details](#read). |
|
||||||
| **`update`** | Allows or denies the ability to update a field's value [More details](#update). |
|
| **`update`** | Allows or denies the ability to update a field's value [More details](#update). |
|
||||||
@@ -68,7 +70,7 @@ Returns a boolean which allows or denies the ability to set a field's value when
|
|||||||
**Available argument properties:**
|
**Available argument properties:**
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ----------------- | -------------------------------------------------------------------------- |
|
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`req`** | The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object containing the currently authenticated `user` |
|
| **`req`** | The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object containing the currently authenticated `user` |
|
||||||
| **`data`** | The full data passed to create the document. |
|
| **`data`** | The full data passed to create the document. |
|
||||||
| **`siblingData`** | Immediately adjacent field data passed to create the document. |
|
| **`siblingData`** | Immediately adjacent field data passed to create the document. |
|
||||||
@@ -80,7 +82,7 @@ Returns a boolean which allows or denies the ability to read a field's value. If
|
|||||||
**Available argument properties:**
|
**Available argument properties:**
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ----------------- | -------------------------------------------------------------------------- |
|
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`req`** | The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object containing the currently authenticated `user` |
|
| **`req`** | The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object containing the currently authenticated `user` |
|
||||||
| **`id`** | `id` of the document being read |
|
| **`id`** | `id` of the document being read |
|
||||||
| **`doc`** | The full document data. |
|
| **`doc`** | The full document data. |
|
||||||
@@ -95,7 +97,7 @@ If `false` is returned and you attempt to update the field's value, the operatio
|
|||||||
**Available argument properties:**
|
**Available argument properties:**
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ----------------- | -------------------------------------------------------------------------- |
|
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`req`** | The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object containing the currently authenticated `user` |
|
| **`req`** | The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object containing the currently authenticated `user` |
|
||||||
| **`id`** | `id` of the document being updated |
|
| **`id`** | `id` of the document being updated |
|
||||||
| **`data`** | The full data passed to update the document. |
|
| **`data`** | The full data passed to update the document. |
|
||||||
|
|||||||
@@ -11,11 +11,12 @@ Global Access Control is [Access Control](../access-control/overview) used to re
|
|||||||
To add Access Control to a Global, use the `access` property in your [Global Config](../configuration/globals):
|
To add Access Control to a Global, use the `access` property in your [Global Config](../configuration/globals):
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import type { GlobalConfig } from 'payload';
|
import type { GlobalConfig } from 'payload'
|
||||||
|
|
||||||
export const GlobalWithAccessControl: GlobalConfig = {
|
export const GlobalWithAccessControl: GlobalConfig = {
|
||||||
// ...
|
// ...
|
||||||
access: { // highlight-line
|
access: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -49,14 +50,14 @@ export default Header
|
|||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Function | Allows/Denies Access |
|
| Function | Allows/Denies Access |
|
||||||
| ----------------------- | -------------------------------------- |
|
| ------------ | --------------------------------------------------------------- |
|
||||||
| **`read`** | Used in the `findOne` Global operation. [More details](#read). |
|
| **`read`** | Used in the `findOne` Global operation. [More details](#read). |
|
||||||
| **`update`** | Used in the `update` Global operation. [More details](#update). |
|
| **`update`** | Used in the `update` Global operation. [More details](#update). |
|
||||||
|
|
||||||
If a Global supports [Versions](../versions/overview), the following additional options are available:
|
If a Global supports [Versions](../versions/overview), the following additional options are available:
|
||||||
|
|
||||||
| Function | Allows/Denies Access |
|
| Function | Allows/Denies Access |
|
||||||
| ------------------ | ---------------------------------------------------------------------------------------------------------------------- |
|
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| **`readVersions`** | Used to control who can read versions, and who can't. Will automatically restrict the Admin UI version viewing access. [More details](#read-versions). |
|
| **`readVersions`** | Used to control who can read versions, and who can't. Will automatically restrict the Admin UI version viewing access. [More details](#read-versions). |
|
||||||
|
|
||||||
### Read
|
### Read
|
||||||
@@ -75,7 +76,7 @@ const Header: GlobalConfig = {
|
|||||||
read: ({ req: { user } }) => {
|
read: ({ req: { user } }) => {
|
||||||
return Boolean(user)
|
return Boolean(user)
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -83,7 +84,7 @@ const Header: GlobalConfig = {
|
|||||||
The following arguments are provided to the `read` function:
|
The following arguments are provided to the `read` function:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| --------- | -------------------------------------------------------------------------- |
|
| --------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`req`** | The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object containing the currently authenticated `user`. |
|
| **`req`** | The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object containing the currently authenticated `user`. |
|
||||||
|
|
||||||
### Update
|
### Update
|
||||||
@@ -102,7 +103,7 @@ const Header: GlobalConfig = {
|
|||||||
update: ({ req: { user }, data }) => {
|
update: ({ req: { user }, data }) => {
|
||||||
return Boolean(user)
|
return Boolean(user)
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -110,7 +111,7 @@ const Header: GlobalConfig = {
|
|||||||
The following arguments are provided to the `update` function:
|
The following arguments are provided to the `update` function:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ---------- | -------------------------------------------------------------------------- |
|
| ---------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`req`** | The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object containing the currently authenticated `user`. |
|
| **`req`** | The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object containing the currently authenticated `user`. |
|
||||||
| **`data`** | The data passed to update the global with. |
|
| **`data`** | The data passed to update the global with. |
|
||||||
|
|
||||||
@@ -127,7 +128,7 @@ export const GlobalWithVersionsAccess: GlobalConfig = {
|
|||||||
// ...
|
// ...
|
||||||
access: {
|
access: {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
readVersions: ({ req: { user }}) => {
|
readVersions: ({ req: { user } }) => {
|
||||||
return Boolean(user)
|
return Boolean(user)
|
||||||
},
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
@@ -138,5 +139,5 @@ export const GlobalWithVersionsAccess: GlobalConfig = {
|
|||||||
The following arguments are provided to the `readVersions` function:
|
The following arguments are provided to the `readVersions` function:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| --------- | -------------------------------------------------------------------------- |
|
| --------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`req`** | The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object containing the currently authenticated `user`. |
|
| **`req`** | The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object containing the currently authenticated `user`. |
|
||||||
|
|||||||
@@ -42,8 +42,10 @@ const defaultPayloadAccess = ({ req: { user } }) => {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Important:**
|
**Important:** In the [Local API](../local-api/overview), all Access Control
|
||||||
In the [Local API](../local-api/overview), all Access Control is _skipped_ by default. This allows your server to have full control over your application. To opt back in, you can set the `overrideAccess` option to `false` in your requests.
|
is _skipped_ by default. This allows your server to have full control over
|
||||||
|
your application. To opt back in, you can set the `overrideAccess` option to
|
||||||
|
`false` in your requests.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## The Access Operation
|
## The Access Operation
|
||||||
@@ -53,13 +55,14 @@ The Admin Panel responds dynamically to your changes to Access Control. For exam
|
|||||||
To accomplish this, Payload exposes the [Access Operation](../authentication/operations#access). Upon login, Payload executes each Access Control function at the top level, across all Collections, Globals, and Fields, and returns a response that contains a reflection of what the currently authenticated user can do within your application.
|
To accomplish this, Payload exposes the [Access Operation](../authentication/operations#access). Upon login, Payload executes each Access Control function at the top level, across all Collections, Globals, and Fields, and returns a response that contains a reflection of what the currently authenticated user can do within your application.
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Important:**
|
**Important:** When your access control functions are executed via the [Access
|
||||||
When your access control functions are executed via the [Access Operation](../authentication/operations#access), the `id` and `data` arguments will be `undefined`. This is because Payload is executing your functions without referencing a specific Document.
|
Operation](../authentication/operations#access), the `id` and `data` arguments
|
||||||
|
will be `undefined`. This is because Payload is executing your functions
|
||||||
|
without referencing a specific Document.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
If you use `id` or `data` within your access control functions, make sure to check that they are defined first. If they are not, then you can assume that your Access Control is being executed via the Access Operation to determine solely what the user can do within the Admin Panel.
|
If you use `id` or `data` within your access control functions, make sure to check that they are defined first. If they are not, then you can assume that your Access Control is being executed via the Access Operation to determine solely what the user can do within the Admin Panel.
|
||||||
|
|
||||||
|
|
||||||
## Locale Specific Access Control
|
## Locale Specific Access Control
|
||||||
|
|
||||||
To implement locale-specific access control, you can use the `req.locale` argument in your access control functions. This argument allows you to evaluate the current locale of the request and determine access permissions accordingly.
|
To implement locale-specific access control, you can use the `req.locale` argument in your access control functions. This argument allows you to evaluate the current locale of the request and determine access permissions accordingly.
|
||||||
@@ -70,10 +73,10 @@ Here is an example:
|
|||||||
const access = ({ req }) => {
|
const access = ({ req }) => {
|
||||||
// Grant access if the locale is 'en'
|
// Grant access if the locale is 'en'
|
||||||
if (req.locale === 'en') {
|
if (req.locale === 'en') {
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deny access for all other locales
|
// Deny access for all other locales
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -29,8 +29,10 @@ Here is an example of how you might target the Dashboard View and change the bac
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Note:**
|
**Note:** If you are building [Custom
|
||||||
If you are building [Custom Components](../custom-components/overview), it is best to import your own stylesheets directly into your components, rather than using the global stylesheet. You can continue to use the [CSS library](#css-library) as needed.
|
Components](../custom-components/overview), it is best to import your own
|
||||||
|
stylesheets directly into your components, rather than using the global
|
||||||
|
stylesheet. You can continue to use the [CSS library](#css-library) as needed.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### Specificity rules
|
### Specificity rules
|
||||||
@@ -40,6 +42,7 @@ All Payload CSS is encapsulated inside CSS layers under `@layer payload-default`
|
|||||||
We have also provided a layer `@layer payload` if you want to use layers and ensure that your styles are applied after payload.
|
We have also provided a layer `@layer payload` if you want to use layers and ensure that your styles are applied after payload.
|
||||||
|
|
||||||
To override existing styles in a way that the previous rules of specificity would be respected you can use the default layer like so
|
To override existing styles in a way that the previous rules of specificity would be respected you can use the default layer like so
|
||||||
|
|
||||||
```css
|
```css
|
||||||
@layer payload-default {
|
@layer payload-default {
|
||||||
// my styles within the payload specificity
|
// my styles within the payload specificity
|
||||||
@@ -77,8 +80,8 @@ The following variables are defined and can be overridden:
|
|||||||
For an up-to-date, comprehensive list of all available variables, please refer to the [Source Code](https://github.com/payloadcms/payload/blob/main/packages/ui/src/scss).
|
For an up-to-date, comprehensive list of all available variables, please refer to the [Source Code](https://github.com/payloadcms/payload/blob/main/packages/ui/src/scss).
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Warning:**
|
**Warning:** If you're overriding colors or theme elevations, make sure to
|
||||||
If you're overriding colors or theme elevations, make sure to consider how [your changes will affect dark mode](#dark-mode).
|
consider how [your changes will affect dark mode](#dark-mode).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
#### Dark Mode
|
#### Dark Mode
|
||||||
|
|||||||
@@ -20,7 +20,12 @@ When a user starts editing a document, Payload locks it for that user. If anothe
|
|||||||
|
|
||||||
The lock will automatically expire after a set period of inactivity, configurable using the `duration` property in the `lockDocuments` configuration, after which others can resume editing.
|
The lock will automatically expire after a set period of inactivity, configurable using the `duration` property in the `lockDocuments` configuration, after which others can resume editing.
|
||||||
|
|
||||||
<Banner type="info"> **Note:** If your application does not require document locking, you can disable this feature for any collection or global by setting the `lockDocuments` property to `false`. </Banner>
|
<Banner type="info">
|
||||||
|
{' '}
|
||||||
|
**Note:** If your application does not require document locking, you can
|
||||||
|
disable this feature for any collection or global by setting the
|
||||||
|
`lockDocuments` property to `false`.{' '}
|
||||||
|
</Banner>
|
||||||
|
|
||||||
### Config Options
|
### Config Options
|
||||||
|
|
||||||
|
|||||||
@@ -51,14 +51,16 @@ To customize Root Metadata, use the `admin.meta` key in your Payload Config:
|
|||||||
The following options are available for Root Metadata:
|
The following options are available for Root Metadata:
|
||||||
|
|
||||||
| Key | Type | Description |
|
| Key | Type | Description |
|
||||||
| --- | --- | --- |
|
| -------------------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `defaultOGImageType` | `dynamic` (default), `static`, or `off` | The type of default OG image to use. If set to `dynamic`, Payload will use Next.js image generation to create an image with the title of the page. If set to `static`, Payload will use the `defaultOGImage` URL. If set to `off`, Payload will not generate an OG image. |
|
| `defaultOGImageType` | `dynamic` (default), `static`, or `off` | The type of default OG image to use. If set to `dynamic`, Payload will use Next.js image generation to create an image with the title of the page. If set to `static`, Payload will use the `defaultOGImage` URL. If set to `off`, Payload will not generate an OG image. |
|
||||||
| `titleSuffix` | `string` | A suffix to append to the end of the title of every page. Defaults to "- Payload". |
|
| `titleSuffix` | `string` | A suffix to append to the end of the title of every page. Defaults to "- Payload". |
|
||||||
| `[keyof Metadata]` | `unknown` | Any other properties that Next.js supports within the `generateMetadata` function. [More details](https://nextjs.org/docs/app/api-reference/functions/generate-metadata). |
|
| `[keyof Metadata]` | `unknown` | Any other properties that Next.js supports within the `generateMetadata` function. [More details](https://nextjs.org/docs/app/api-reference/functions/generate-metadata). |
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Reminder:**
|
**Reminder:** These are the _root-level_ options for the Admin Panel. You can
|
||||||
These are the _root-level_ options for the Admin Panel. You can also customize metadata on the [Collection](../configuration/collections), [Global](../configuration/globals), and Document levels through their respective configs.
|
also customize metadata on the [Collection](../configuration/collections),
|
||||||
|
[Global](../configuration/globals), and Document levels through their
|
||||||
|
respective configs.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### Icons
|
### Icons
|
||||||
@@ -162,8 +164,9 @@ Disallow: /admin/
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
**Note:**
|
**Note:** If you've customized the path to your Admin Panel via
|
||||||
If you've customized the path to your Admin Panel via `config.routes`, be sure to update the `Disallow` directive to match your custom path.
|
`config.routes`, be sure to update the `Disallow` directive to match your
|
||||||
|
custom path.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Collection Metadata
|
## Collection Metadata
|
||||||
@@ -236,3 +239,4 @@ To customize View Metadata, use the `meta` key within your View Config:
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ The Admin Panel is designed to [white-label your brand](https://payloadcms.com/b
|
|||||||
The Admin Panel is written in [TypeScript](https://www.typescriptlang.org) and built with [React](https://react.dev) using the [Next.js App Router](https://nextjs.org/docs/app). It supports [React Server Components](https://react.dev/reference/rsc/server-components), enabling the use of the [Local API](/docs/local-api/overview) on the front-end. You can install Payload into any [existing Next.js app in just one line](../getting-started/installation) and [deploy it anywhere](../production/deployment).
|
The Admin Panel is written in [TypeScript](https://www.typescriptlang.org) and built with [React](https://react.dev) using the [Next.js App Router](https://nextjs.org/docs/app). It supports [React Server Components](https://react.dev/reference/rsc/server-components), enabling the use of the [Local API](/docs/local-api/overview) on the front-end. You can install Payload into any [existing Next.js app in just one line](../getting-started/installation) and [deploy it anywhere](../production/deployment).
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
The Payload Admin Panel is designed to be as minimal and straightforward as possible to allow easy customization and control. [Learn more](../custom-components/overview).
|
The Payload Admin Panel is designed to be as minimal and straightforward as
|
||||||
|
possible to allow easy customization and control. [Learn
|
||||||
|
more](../custom-components/overview).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
<LightDarkImage
|
<LightDarkImage
|
||||||
@@ -48,7 +50,8 @@ app/
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
If you are not familiar with Next.js project structure, you can [learn more about it here](https://nextjs.org/docs/getting-started/project-structure).
|
If you are not familiar with Next.js project structure, you can [learn more
|
||||||
|
about it here](https://nextjs.org/docs/getting-started/project-structure).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
As shown above, all Payload routes are nested within the `(payload)` route group. This creates a boundary between the Admin Panel and the rest of your application by scoping all layouts and styles. The `layout.tsx` file within this directory, for example, is where Payload manages the `html` tag of the document to set proper [`lang`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang) and [`dir`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir) attributes, etc.
|
As shown above, all Payload routes are nested within the `(payload)` route group. This creates a boundary between the Admin Panel and the rest of your application by scoping all layouts and styles. The `layout.tsx` file within this directory, for example, is where Payload manages the `html` tag of the document to set proper [`lang`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang) and [`dir`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir) attributes, etc.
|
||||||
@@ -56,8 +59,11 @@ As shown above, all Payload routes are nested within the `(payload)` route group
|
|||||||
The `admin` directory contains all the _pages_ related to the interface itself, whereas the `api` and `graphql` directories contains all the _routes_ related to the [REST API](../rest-api/overview) and [GraphQL API](../graphql/overview). All admin routes are [easily configurable](#customizing-routes) to meet your application's exact requirements.
|
The `admin` directory contains all the _pages_ related to the interface itself, whereas the `api` and `graphql` directories contains all the _routes_ related to the [REST API](../rest-api/overview) and [GraphQL API](../graphql/overview). All admin routes are [easily configurable](#customizing-routes) to meet your application's exact requirements.
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Note:**
|
**Note:** If you don't intend to use the Admin Panel, [REST
|
||||||
If you don't intend to use the Admin Panel, [REST API](../rest-api/overview), or [GraphQL API](../graphql/overview), you can opt-out by simply deleting their corresponding directories within your Next.js app. The overhead, however, is completely constrained to these routes, and will not slow down or affect Payload outside when not in use.
|
API](../rest-api/overview), or [GraphQL API](../graphql/overview), you can
|
||||||
|
opt-out by simply deleting their corresponding directories within your Next.js
|
||||||
|
app. The overhead, however, is completely constrained to these routes, and
|
||||||
|
will not slow down or affect Payload outside when not in use.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
Finally, the `custom.scss` file is where you can add or override globally-oriented styles in the Admin Panel, such as modify the color palette. Customizing the look and feel through CSS alone is a powerful feature of the Admin Panel, [more on that here](./customizing-css).
|
Finally, the `custom.scss` file is where you can add or override globally-oriented styles in the Admin Panel, such as modify the color palette. Customizing the look and feel through CSS alone is a powerful feature of the Admin Panel, [more on that here](./customizing-css).
|
||||||
@@ -78,7 +84,8 @@ import { buildConfig } from 'payload'
|
|||||||
|
|
||||||
const config = buildConfig({
|
const config = buildConfig({
|
||||||
// ...
|
// ...
|
||||||
admin: { // highlight-line
|
admin: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -87,7 +94,7 @@ const config = buildConfig({
|
|||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
|--------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`avatar`** | Set account profile picture. Options: `gravatar`, `default` or a custom React component. |
|
| **`avatar`** | Set account profile picture. Options: `gravatar`, `default` or a custom React component. |
|
||||||
| **`autoLogin`** | Used to automate log-in for dev and demonstration convenience. [More details](../authentication/overview). |
|
| **`autoLogin`** | Used to automate log-in for dev and demonstration convenience. [More details](../authentication/overview). |
|
||||||
| **`buildPath`** | Specify an absolute path for where to store the built Admin bundle used in production. Defaults to `path.resolve(process.cwd(), 'build')`. |
|
| **`buildPath`** | Specify an absolute path for where to store the built Admin bundle used in production. Defaults to `path.resolve(process.cwd(), 'build')`. |
|
||||||
@@ -103,8 +110,11 @@ The following options are available:
|
|||||||
| **`user`** | The `slug` of the Collection that you want to allow to login to the Admin Panel. [More details](#the-admin-user-collection). |
|
| **`user`** | The `slug` of the Collection that you want to allow to login to the Admin Panel. [More details](#the-admin-user-collection). |
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Reminder:**
|
**Reminder:** These are the _root-level_ options for the Admin Panel. You can
|
||||||
These are the _root-level_ options for the Admin Panel. You can also customize [Collection Admin Options](../configuration/collections#admin-options) and [Global Admin Options](../configuration/globals#admin-options) through their respective `admin` keys.
|
also customize [Collection Admin
|
||||||
|
Options](../configuration/collections#admin-options) and [Global Admin
|
||||||
|
Options](../configuration/globals#admin-options) through their respective
|
||||||
|
`admin` keys.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### The Admin User Collection
|
### The Admin User Collection
|
||||||
@@ -125,7 +135,8 @@ const config = buildConfig({
|
|||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Important:**
|
**Important:**
|
||||||
|
|
||||||
The Admin Panel can only be used by a single auth-enabled Collection. To enable authentication for a Collection, simply set `auth: true` in the Collection's configuration. See [Authentication](../authentication/overview) for more information.
|
The Admin Panel can only be used by a single auth-enabled Collection. To enable authentication for a Collection, simply set `auth: true` in the Collection's configuration. See [Authentication](../authentication/overview) for more information.
|
||||||
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
By default, if you have not specified a Collection, Payload will automatically provide a `User` Collection with access to the Admin Panel. You can customize or override the fields and settings of the default `User` Collection by adding your own Collection with `slug: 'users'`. Doing this will force Payload to use your provided `User` Collection instead of its default version.
|
By default, if you have not specified a Collection, Payload will automatically provide a `User` Collection with access to the Admin Panel. You can customize or override the fields and settings of the default `User` Collection by adding your own Collection with `slug: 'users'`. Doing this will force Payload to use your provided `User` Collection instead of its default version.
|
||||||
@@ -162,23 +173,24 @@ import { buildConfig } from 'payload'
|
|||||||
const config = buildConfig({
|
const config = buildConfig({
|
||||||
// ...
|
// ...
|
||||||
routes: {
|
routes: {
|
||||||
admin: '/custom-admin-route' // highlight-line
|
admin: '/custom-admin-route', // highlight-line
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Option | Default route | Description |
|
| Option | Default route | Description |
|
||||||
|---------------------|-----------------------|---------------------------------------------------|
|
| ------------------- | --------------------- | ------------------------------------------------- |
|
||||||
| `admin` | `/admin` | The Admin Panel itself. |
|
| `admin` | `/admin` | The Admin Panel itself. |
|
||||||
| `api` | `/api` | The [REST API](../rest-api/overview) base path. |
|
| `api` | `/api` | The [REST API](../rest-api/overview) base path. |
|
||||||
| `graphQL` | `/graphql` | The [GraphQL API](../graphql/overview) base path. |
|
| `graphQL` | `/graphql` | The [GraphQL API](../graphql/overview) base path. |
|
||||||
| `graphQLPlayground` | `/graphql-playground` | The GraphQL Playground. |
|
| `graphQLPlayground` | `/graphql-playground` | The GraphQL Playground. |
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Tip:**
|
**Tip:** You can easily add _new_ routes to the Admin Panel through [Custom
|
||||||
You can easily add _new_ routes to the Admin Panel through [Custom Endpoints](../rest-api/overview#custom-endpoints) and [Custom Views](../custom-components/custom-views).
|
Endpoints](../rest-api/overview#custom-endpoints) and [Custom
|
||||||
|
Views](../custom-components/custom-views).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
#### Customizing Root-level Routes
|
#### Customizing Root-level Routes
|
||||||
@@ -195,8 +207,9 @@ app/
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Note:**
|
**Note:** If you set Root-level Routes _before_ auto-generating the Admin
|
||||||
If you set Root-level Routes _before_ auto-generating the Admin Panel via `create-payload-app`, your [Project Structure](#project-structure) will already be set up correctly.
|
Panel via `create-payload-app`, your [Project Structure](#project-structure)
|
||||||
|
will already be set up correctly.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### Admin-level Routes
|
### Admin-level Routes
|
||||||
@@ -212,8 +225,8 @@ const config = buildConfig({
|
|||||||
// ...
|
// ...
|
||||||
admin: {
|
admin: {
|
||||||
routes: {
|
routes: {
|
||||||
account: '/my-account' // highlight-line
|
account: '/my-account', // highlight-line
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
@@ -221,7 +234,7 @@ const config = buildConfig({
|
|||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Option | Default route | Description |
|
| Option | Default route | Description |
|
||||||
| ----------------- | ----------------------- | ----------------------------------------------- |
|
| ----------------- | -------------------- | ----------------------------------------- |
|
||||||
| `account` | `/account` | The user's account page. |
|
| `account` | `/account` | The user's account page. |
|
||||||
| `createFirstUser` | `/create-first-user` | The page to create the first user. |
|
| `createFirstUser` | `/create-first-user` | The page to create the first user. |
|
||||||
| `forgot` | `/forgot` | The password reset page. |
|
| `forgot` | `/forgot` | The password reset page. |
|
||||||
@@ -232,8 +245,9 @@ The following options are available:
|
|||||||
| `unauthorized` | `/unauthorized` | The unauthorized page. |
|
| `unauthorized` | `/unauthorized` | The unauthorized page. |
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Note:**
|
**Note:** You can also swap out entire _views_ out for your own, using the
|
||||||
You can also swap out entire _views_ out for your own, using the `admin.views` property of the Payload Config. See [Custom Views](../custom-components/custom-views) for more information.
|
`admin.views` property of the Payload Config. See [Custom
|
||||||
|
Views](../custom-components/custom-views) for more information.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## I18n
|
## I18n
|
||||||
@@ -251,13 +265,14 @@ The `admin.timezones` configuration allows you to configure timezone settings fo
|
|||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ----------------- | ----------------------------------------------- |
|
| -------------------- | --------------------------------------------------------------------------------------------------------------- |
|
||||||
| `supportedTimezones` | An array of label/value options for selectable timezones where the value is the IANA name eg. `America/Detroit` |
|
| `supportedTimezones` | An array of label/value options for selectable timezones where the value is the IANA name eg. `America/Detroit` |
|
||||||
| `defaultTimezone` | The `value` of the default selected timezone. eg. `America/Los_Angeles` |
|
| `defaultTimezone` | The `value` of the default selected timezone. eg. `America/Los_Angeles` |
|
||||||
|
|
||||||
We validate the supported timezones array by checking the value against the list of IANA timezones supported via the Intl API, specifically `Intl.supportedValuesOf('timeZone')`.
|
We validate the supported timezones array by checking the value against the list of IANA timezones supported via the Intl API, specifically `Intl.supportedValuesOf('timeZone')`.
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
**Important**
|
**Important** You must enable timezones on each individual date field via
|
||||||
You must enable timezones on each individual date field via `timezone: true`. See [Date Fields](../fields/overview#date) for more information.
|
`timezone: true`. See [Date Fields](../fields/overview#date) for more
|
||||||
|
information.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|||||||
@@ -18,8 +18,9 @@ Out of the box, Payload handles the persistence of your users' preferences in a
|
|||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Important:**
|
**Important:**
|
||||||
|
|
||||||
All preferences are stored on an individual user basis. Payload automatically recognizes the user
|
All preferences are stored on an individual user basis. Payload automatically recognizes the user
|
||||||
that is reading or setting a preference via all provided authentication methods.
|
that is reading or setting a preference via all provided authentication methods.
|
||||||
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Use Cases
|
## Use Cases
|
||||||
@@ -76,80 +77,66 @@ Here is an example for how you can utilize `usePreferences` within your custom A
|
|||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
'use client'
|
'use client'
|
||||||
import React, { Fragment, useState, useEffect, useCallback } from 'react';
|
import React, { Fragment, useState, useEffect, useCallback } from 'react'
|
||||||
import { usePreferences } from '@payloadcms/ui'
|
import { usePreferences } from '@payloadcms/ui'
|
||||||
|
|
||||||
const lastUsedColorsPreferenceKey = 'last-used-colors';
|
const lastUsedColorsPreferenceKey = 'last-used-colors'
|
||||||
|
|
||||||
export function CustomComponent() {
|
export function CustomComponent() {
|
||||||
const { getPreference, setPreference } = usePreferences();
|
const { getPreference, setPreference } = usePreferences()
|
||||||
|
|
||||||
// Store the last used colors in local state
|
// Store the last used colors in local state
|
||||||
const [lastUsedColors, setLastUsedColors] = useState([]);
|
const [lastUsedColors, setLastUsedColors] = useState([])
|
||||||
|
|
||||||
// Callback to add a color to the last used colors
|
// Callback to add a color to the last used colors
|
||||||
const updateLastUsedColors = useCallback((color) => {
|
const updateLastUsedColors = useCallback(
|
||||||
|
(color) => {
|
||||||
// First, check if color already exists in last used colors.
|
// First, check if color already exists in last used colors.
|
||||||
// If it already exists, there is no need to update preferences
|
// If it already exists, there is no need to update preferences
|
||||||
const colorAlreadyExists = lastUsedColors.indexOf(color) > -1;
|
const colorAlreadyExists = lastUsedColors.indexOf(color) > -1
|
||||||
|
|
||||||
if (!colorAlreadyExists) {
|
if (!colorAlreadyExists) {
|
||||||
const newLastUsedColors = [
|
const newLastUsedColors = [...lastUsedColors, color]
|
||||||
...lastUsedColors,
|
|
||||||
color,
|
|
||||||
];
|
|
||||||
|
|
||||||
setLastUsedColors(newLastUsedColors);
|
setLastUsedColors(newLastUsedColors)
|
||||||
setPreference(lastUsedColorsPreferenceKey, newLastUsedColors);
|
setPreference(lastUsedColorsPreferenceKey, newLastUsedColors)
|
||||||
}
|
}
|
||||||
}, [lastUsedColors, setPreference]);
|
},
|
||||||
|
[lastUsedColors, setPreference],
|
||||||
|
)
|
||||||
|
|
||||||
// Retrieve preferences on component mount
|
// Retrieve preferences on component mount
|
||||||
// This will only be run one time, because the `getPreference` method never changes
|
// This will only be run one time, because the `getPreference` method never changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const asyncGetPreference = async () => {
|
const asyncGetPreference = async () => {
|
||||||
const lastUsedColorsFromPreferences = await getPreference(lastUsedColorsPreferenceKey);
|
const lastUsedColorsFromPreferences = await getPreference(
|
||||||
setLastUsedColors(lastUsedColorsFromPreferences);
|
lastUsedColorsPreferenceKey,
|
||||||
};
|
)
|
||||||
|
setLastUsedColors(lastUsedColorsFromPreferences)
|
||||||
|
}
|
||||||
|
|
||||||
asyncGetPreference();
|
asyncGetPreference()
|
||||||
}, [getPreference]);
|
}, [getPreference])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button type="button" onClick={() => updateLastUsedColors('red')}>
|
||||||
type="button"
|
|
||||||
onClick={() => updateLastUsedColors('red')}
|
|
||||||
>
|
|
||||||
Use red
|
Use red
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button type="button" onClick={() => updateLastUsedColors('blue')}>
|
||||||
type="button"
|
|
||||||
onClick={() => updateLastUsedColors('blue')}
|
|
||||||
>
|
|
||||||
Use blue
|
Use blue
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button type="button" onClick={() => updateLastUsedColors('purple')}>
|
||||||
type="button"
|
|
||||||
onClick={() => updateLastUsedColors('purple')}
|
|
||||||
>
|
|
||||||
Use purple
|
Use purple
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button type="button" onClick={() => updateLastUsedColors('yellow')}>
|
||||||
type="button"
|
|
||||||
onClick={() => updateLastUsedColors('yellow')}
|
|
||||||
>
|
|
||||||
Use yellow
|
Use yellow
|
||||||
</button>
|
</button>
|
||||||
{lastUsedColors && (
|
{lastUsedColors && (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<h5>Last used colors:</h5>
|
<h5>Last used colors:</h5>
|
||||||
<ul>
|
<ul>
|
||||||
{lastUsedColors?.map((color) => (
|
{lastUsedColors?.map((color) => <li key={color}>{color}</li>)}
|
||||||
<li key={color}>
|
|
||||||
{color}
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
</ul>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -11,8 +11,10 @@ Preview is a feature that allows you to generate a direct link to your front-end
|
|||||||
The Preview feature can also be used to achieve something known as "Draft Preview". With Draft Preview, you can navigate to your front-end application and enter "draft mode", where your queries are modified to fetch draft content instead of published content. This is useful for seeing how your content will look before being published. [More details](#draft-preview).
|
The Preview feature can also be used to achieve something known as "Draft Preview". With Draft Preview, you can navigate to your front-end application and enter "draft mode", where your queries are modified to fetch draft content instead of published content. This is useful for seeing how your content will look before being published. [More details](#draft-preview).
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Note:**
|
**Note:** Preview is different than [Live Preview](../live-preview/overview).
|
||||||
Preview is different than [Live Preview](../live-preview/overview). Live Preview loads your app within an iframe and renders it in the Admin Panel allowing you to see changes in real-time. Preview, on the other hand, allows you to generate a direct link to your front-end application.
|
Live Preview loads your app within an iframe and renders it in the Admin Panel
|
||||||
|
allowing you to see changes in real-time. Preview, on the other hand, allows
|
||||||
|
you to generate a direct link to your front-end application.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
To add Preview, pass a function to the `admin.preview` property in any [Collection Config](../configuration/collections#admin-options) or [Global Config](../configuration/globals#admin-options):
|
To add Preview, pass a function to the `admin.preview` property in any [Collection Config](../configuration/collections#admin-options) or [Global Config](../configuration/globals#admin-options):
|
||||||
@@ -29,7 +31,7 @@ export const Pages: CollectionConfig = {
|
|||||||
{
|
{
|
||||||
name: 'slug',
|
name: 'slug',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -41,14 +43,14 @@ The `preview` function resolves to a string that points to your front-end applic
|
|||||||
The following arguments are provided to the `preview` function:
|
The following arguments are provided to the `preview` function:
|
||||||
|
|
||||||
| Path | Description |
|
| Path | Description |
|
||||||
| ------------------ | ----------------------------------------------------------------------------------------------------------------- |
|
| ------------- | ------------------------------------------------------------------------------------------ |
|
||||||
| **`doc`** | The data of the Document being edited. This includes changes that have not yet been saved. |
|
| **`doc`** | The data of the Document being edited. This includes changes that have not yet been saved. |
|
||||||
| **`options`** | An object with additional properties. |
|
| **`options`** | An object with additional properties. |
|
||||||
|
|
||||||
The `options` object contains the following properties:
|
The `options` object contains the following properties:
|
||||||
|
|
||||||
| Path | Description |
|
| Path | Description |
|
||||||
| ------------------ | ----------------------------------------------------------------------------------------------------------------- |
|
| ------------ | ----------------------------------------------------- |
|
||||||
| **`locale`** | The current locale of the Document being edited. |
|
| **`locale`** | The current locale of the Document being edited. |
|
||||||
| **`req`** | The Payload Request object. |
|
| **`req`** | The Payload Request object. |
|
||||||
| **`token`** | The JWT token of the currently authenticated in user. |
|
| **`token`** | The JWT token of the currently authenticated in user. |
|
||||||
@@ -84,17 +86,17 @@ export const Pages: CollectionConfig = {
|
|||||||
slug,
|
slug,
|
||||||
collection,
|
collection,
|
||||||
path: `/${slug}`,
|
path: `/${slug}`,
|
||||||
previewSecret: process.env.PREVIEW_SECRET || ''
|
previewSecret: process.env.PREVIEW_SECRET || '',
|
||||||
})
|
})
|
||||||
|
|
||||||
return `/preview?${encodedParams.toString()}` // highlight-line
|
return `/preview?${encodedParams.toString()}` // highlight-line
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: 'slug',
|
name: 'slug',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -133,7 +135,9 @@ export async function GET(
|
|||||||
const previewSecret = searchParams.get('previewSecret')
|
const previewSecret = searchParams.get('previewSecret')
|
||||||
|
|
||||||
if (previewSecret !== process.env.PREVIEW_SECRET) {
|
if (previewSecret !== process.env.PREVIEW_SECRET) {
|
||||||
return new Response('You are not allowed to preview this page', { status: 403 })
|
return new Response('You are not allowed to preview this page', {
|
||||||
|
status: 403,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!path || !collection || !slug) {
|
if (!path || !collection || !slug) {
|
||||||
@@ -141,7 +145,10 @@ export async function GET(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!path.startsWith('/')) {
|
if (!path.startsWith('/')) {
|
||||||
return new Response('This endpoint can only be used for relative previews', { status: 500 })
|
return new Response(
|
||||||
|
'This endpoint can only be used for relative previews',
|
||||||
|
{ status: 500 },
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let user
|
let user
|
||||||
@@ -152,15 +159,22 @@ export async function GET(
|
|||||||
headers: req.headers,
|
headers: req.headers,
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
payload.logger.error({ err: error }, 'Error verifying token for live preview')
|
payload.logger.error(
|
||||||
return new Response('You are not allowed to preview this page', { status: 403 })
|
{ err: error },
|
||||||
|
'Error verifying token for live preview',
|
||||||
|
)
|
||||||
|
return new Response('You are not allowed to preview this page', {
|
||||||
|
status: 403,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const draft = await draftMode()
|
const draft = await draftMode()
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
draft.disable()
|
draft.disable()
|
||||||
return new Response('You are not allowed to preview this page', { status: 403 })
|
return new Response('You are not allowed to preview this page', {
|
||||||
|
status: 403,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// You can add additional checks here to see if the user is allowed to preview this page
|
// You can add additional checks here to see if the user is allowed to preview this page
|
||||||
@@ -211,7 +225,9 @@ export default async function Page({ params: paramsPromise }) {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Note:**
|
**Note:** For fully working example of this, check of the official [Draft
|
||||||
For fully working example of this, check of the official [Draft Preview Example](https://github.com/payloadcms/payload/tree/main/examples/draft-preview) in the [Examples Directory](https://github.com/payloadcms/payload/tree/main/examples).
|
Preview
|
||||||
|
Example](https://github.com/payloadcms/payload/tree/main/examples/draft-preview)
|
||||||
|
in the [Examples
|
||||||
|
Directory](https://github.com/payloadcms/payload/tree/main/examples).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,11 @@ keywords: admin, components, custom, documentation, Content Management System, c
|
|||||||
Payload provides a variety of powerful [React Hooks](https://react.dev/reference/react-dom/hooks) that can be used within your own [Custom Components](../custom-components/overview), such as [Custom Fields](../fields/overview#custom-components). With them, you can interface with Payload itself to build just about any type of complex customization you can think of.
|
Payload provides a variety of powerful [React Hooks](https://react.dev/reference/react-dom/hooks) that can be used within your own [Custom Components](../custom-components/overview), such as [Custom Fields](../fields/overview#custom-components). With them, you can interface with Payload itself to build just about any type of complex customization you can think of.
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Reminder:**
|
**Reminder:** All Custom Components are [React Server
|
||||||
All Custom Components are [React Server Components](https://react.dev/reference/rsc/server-components) by default. Hooks, on the other hand, are only available in client-side environments. To use hooks, [ensure your component is a client component](../custom-components/overview#client-components).
|
Components](https://react.dev/reference/rsc/server-components) by default.
|
||||||
|
Hooks, on the other hand, are only available in client-side environments. To
|
||||||
|
use hooks, [ensure your component is a client
|
||||||
|
component](../custom-components/overview#client-components).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## useField
|
## useField
|
||||||
@@ -29,11 +32,11 @@ export const CustomTextField: TextFieldClientComponent = ({ path }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>{path}</p>
|
||||||
{path}
|
|
||||||
</p>
|
|
||||||
<input
|
<input
|
||||||
onChange={(e) => { setValue(e.target.value) }}
|
onChange={(e) => {
|
||||||
|
setValue(e.target.value)
|
||||||
|
}}
|
||||||
value={value}
|
value={value}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -44,7 +47,7 @@ export const CustomTextField: TextFieldClientComponent = ({ path }) => {
|
|||||||
The `useField` hook accepts the following arguments:
|
The `useField` hook accepts the following arguments:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| `path` | If you do not provide a `path`, `name` will be used instead. This is the path to the field in the form data. |
|
| `path` | If you do not provide a `path`, `name` will be used instead. This is the path to the field in the form data. |
|
||||||
| `validate` | A validation function executed client-side _before_ submitting the form to the server. Different than [Field-level Validation](../fields/overview#validation) which runs strictly on the server. |
|
| `validate` | A validation function executed client-side _before_ submitting the form to the server. Different than [Field-level Validation](../fields/overview#validation) which runs strictly on the server. |
|
||||||
| `disableFormData` | If `true`, the field will not be included in the form data when the form is submitted. |
|
| `disableFormData` | If `true`, the field will not be included in the form data when the form is submitted. |
|
||||||
@@ -78,8 +81,9 @@ type FieldType<T> = {
|
|||||||
There are times when a custom field component needs to have access to data from other fields, and you have a few options to do so. The `useFormFields` hook is a powerful and highly performant way to retrieve a form's field state, as well as to retrieve the `dispatchFields` method, which can be helpful for setting other fields' form states from anywhere within a form.
|
There are times when a custom field component needs to have access to data from other fields, and you have a few options to do so. The `useFormFields` hook is a powerful and highly performant way to retrieve a form's field state, as well as to retrieve the `dispatchFields` method, which can be helpful for setting other fields' form states from anywhere within a form.
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**This hook is great for retrieving only certain fields from form state** because it
|
**This hook is great for retrieving only certain fields from form state**
|
||||||
ensures that it will only cause a rerender when the items that you ask for change.
|
because it ensures that it will only cause a rerender when the items that you
|
||||||
|
ask for change.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
Thanks to the awesome package [`use-context-selector`](https://github.com/dai-shi/use-context-selector), you can retrieve a specific field's state easily. This is ideal because you can ensure you have an up-to-date field state, and your component will only re-render when _that field's state_ changes.
|
Thanks to the awesome package [`use-context-selector`](https://github.com/dai-shi/use-context-selector), you can retrieve a specific field's state easily. This is ideal because you can ensure you have an up-to-date field state, and your component will only re-render when _that field's state_ changes.
|
||||||
@@ -95,9 +99,14 @@ const MyComponent: React.FC = () => {
|
|||||||
const amount = useFormFields(([fields, dispatch]) => fields.amount)
|
const amount = useFormFields(([fields, dispatch]) => fields.amount)
|
||||||
|
|
||||||
// Do the same thing as above, but to the `feePercentage` field
|
// Do the same thing as above, but to the `feePercentage` field
|
||||||
const feePercentage = useFormFields(([fields, dispatch]) => fields.feePercentage)
|
const feePercentage = useFormFields(
|
||||||
|
([fields, dispatch]) => fields.feePercentage,
|
||||||
|
)
|
||||||
|
|
||||||
if (typeof amount?.value !== 'undefined' && typeof feePercentage?.value !== 'undefined') {
|
if (
|
||||||
|
typeof amount?.value !== 'undefined' &&
|
||||||
|
typeof feePercentage?.value !== 'undefined'
|
||||||
|
) {
|
||||||
return <span>The fee is ${(amount.value * feePercentage.value) / 100}</span>
|
return <span>The fee is ${(amount.value * feePercentage.value) / 100}</span>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -159,10 +168,11 @@ The `useForm` hook can be used to interact with the form itself, and sends back
|
|||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Warning:**
|
**Warning:**
|
||||||
|
|
||||||
This hook is optimized to avoid causing rerenders when fields change, and as such, its `fields`
|
This hook is optimized to avoid causing rerenders when fields change, and as such, its `fields`
|
||||||
property will be out of date. You should only leverage this hook if you need to perform actions
|
property will be out of date. You should only leverage this hook if you need to perform actions
|
||||||
against the form in response to your users' actions. Do not rely on its returned "fields" as being
|
against the form in response to your users' actions. Do not rely on its returned "fields" as being
|
||||||
up-to-date. They will be removed from this hook's response in an upcoming version.
|
up-to-date. They will be removed from this hook's response in an upcoming version.
|
||||||
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
The `useForm` hook returns an object with the following properties:
|
The `useForm` hook returns an object with the following properties:
|
||||||
@@ -384,20 +394,20 @@ The `useForm` hook returns an object with the following properties:
|
|||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
\`\`\`tsx
|
\`\`\`tsx
|
||||||
import { useForm } from "@payloadcms/ui"
|
import { useForm } from "@payloadcms/ui"
|
||||||
|
|
||||||
export const CustomArrayManager = () => {
|
export const CustomArrayManager = () => {
|
||||||
const { addFieldRow } = useForm()
|
const { addFieldRow } = useForm()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
|
||||||
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
addFieldRow({
|
addFieldRow({
|
||||||
path: "arrayField",
|
path: 'arrayField',
|
||||||
schemaPath: "arrayField",
|
schemaPath: 'arrayField',
|
||||||
rowIndex: 0, // optionally specify the index to add the row at
|
rowIndex: 0, // optionally specify the index to add the row at
|
||||||
subFieldState: {
|
subFieldState: {
|
||||||
textField: {
|
textField: {
|
||||||
@@ -410,39 +420,37 @@ export const CustomArrayManager = () => {
|
|||||||
// ^ if managing a block array, you need to specify the block type
|
// ^ if managing a block array, you need to specify the block type
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Add Row
|
Add Row
|
||||||
</button>
|
</button>
|
||||||
)
|
) } \`\`\`
|
||||||
}
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
An example config to go along with the Custom Component
|
An example config to go along with the Custom Component
|
||||||
|
|
||||||
\`\`\`tsx
|
\`\`\`tsx
|
||||||
const ExampleCollection = {
|
const ExampleCollection = {
|
||||||
slug: "example-collection",
|
slug: "example-collection",
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: "arrayField",
|
name: "arrayField",
|
||||||
type: "array",
|
type: "array",
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: "textField",
|
name: "textField",
|
||||||
type: "text",
|
type: "text",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "ui",
|
type: "ui",
|
||||||
name: "customArrayManager",
|
name: "customArrayManager",
|
||||||
admin: {
|
admin: {
|
||||||
components: {
|
components: {
|
||||||
Field: '/path/to/CustomArrayManagerField',
|
Field: '/path/to/CustomArrayManagerField',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
\`\`\`
|
\`\`\`
|
||||||
`
|
`
|
||||||
@@ -460,32 +468,28 @@ const ExampleCollection = {
|
|||||||
drawerDescription: 'A useful method to programmatically remove a row from an array or block field.',
|
drawerDescription: 'A useful method to programmatically remove a row from an array or block field.',
|
||||||
drawerSlug: 'removeFieldRow',
|
drawerSlug: 'removeFieldRow',
|
||||||
drawerContent: `
|
drawerContent: `
|
||||||
<TableWithDrawers
|
|
||||||
columns={[
|
<TableWithDrawers
|
||||||
'Prop',
|
columns={['Prop', 'Description']}
|
||||||
'Description',
|
|
||||||
]}
|
|
||||||
rows={[
|
rows={[
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
value: "**\\\`path\\\`**",
|
value: '**\\\`path\\\`**',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "The path to the array or block field",
|
value: 'The path to the array or block field',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
value: "**\\\`rowIndex\\\`**",
|
value: '**\\\`rowIndex\\\`**',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "The index of the row to remove",
|
value: 'The index of the row to remove',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
\`\`\`tsx
|
\`\`\`tsx
|
||||||
import { useForm } from "@payloadcms/ui"
|
import { useForm } from "@payloadcms/ui"
|
||||||
@@ -493,48 +497,47 @@ import { useForm } from "@payloadcms/ui"
|
|||||||
export const CustomArrayManager = () => {
|
export const CustomArrayManager = () => {
|
||||||
const { removeFieldRow } = useForm()
|
const { removeFieldRow } = useForm()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
|
||||||
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
removeFieldRow({
|
removeFieldRow({
|
||||||
path: "arrayField",
|
path: 'arrayField',
|
||||||
rowIndex: 0,
|
rowIndex: 0,
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Remove Row
|
Remove Row
|
||||||
</button>
|
</button>
|
||||||
)
|
) } \`\`\`
|
||||||
}
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
An example config to go along with the Custom Component
|
An example config to go along with the Custom Component
|
||||||
|
|
||||||
\`\`\`tsx
|
\`\`\`tsx
|
||||||
const ExampleCollection = {
|
const ExampleCollection = {
|
||||||
slug: "example-collection",
|
slug: "example-collection",
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: "arrayField",
|
name: "arrayField",
|
||||||
type: "array",
|
type: "array",
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: "textField",
|
name: "textField",
|
||||||
type: "text",
|
type: "text",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "ui",
|
type: "ui",
|
||||||
name: "customArrayManager",
|
name: "customArrayManager",
|
||||||
admin: {
|
admin: {
|
||||||
components: {
|
components: {
|
||||||
Field: '/path/to/CustomArrayManagerField',
|
Field: '/path/to/CustomArrayManagerField',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
\`\`\`
|
\`\`\`
|
||||||
`
|
`
|
||||||
@@ -552,41 +555,36 @@ const ExampleCollection = {
|
|||||||
drawerDescription: 'A useful method to programmatically replace a row from an array or block field.',
|
drawerDescription: 'A useful method to programmatically replace a row from an array or block field.',
|
||||||
drawerSlug: 'replaceFieldRow',
|
drawerSlug: 'replaceFieldRow',
|
||||||
drawerContent: `
|
drawerContent: `
|
||||||
<TableWithDrawers
|
|
||||||
columns={[
|
<TableWithDrawers
|
||||||
'Prop',
|
columns={['Prop', 'Description']}
|
||||||
'Description',
|
|
||||||
]}
|
|
||||||
rows={[
|
rows={[
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
value: "**\\\`path\\\`**",
|
value: '**\\\`path\\\`**',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "The path to the array or block field",
|
value: 'The path to the array or block field',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
value: "**\\\`rowIndex\\\`**",
|
value: '**\\\`rowIndex\\\`**',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "The index of the row to replace",
|
value: 'The index of the row to replace',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
value: "**\\\`data\\\`**",
|
value: '**\\\`data\\\`**',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "The data to replace within the row",
|
value: 'The data to replace within the row',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
\`\`\`tsx
|
\`\`\`tsx
|
||||||
import { useForm } from "@payloadcms/ui"
|
import { useForm } from "@payloadcms/ui"
|
||||||
@@ -594,13 +592,14 @@ import { useForm } from "@payloadcms/ui"
|
|||||||
export const CustomArrayManager = () => {
|
export const CustomArrayManager = () => {
|
||||||
const { replaceFieldRow } = useForm()
|
const { replaceFieldRow } = useForm()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
|
||||||
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
replaceFieldRow({
|
replaceFieldRow({
|
||||||
path: "arrayField",
|
path: 'arrayField',
|
||||||
schemaPath: "arrayField",
|
schemaPath: 'arrayField',
|
||||||
rowIndex: 0, // optionally specify the index to add the row at
|
rowIndex: 0, // optionally specify the index to add the row at
|
||||||
subFieldState: {
|
subFieldState: {
|
||||||
textField: {
|
textField: {
|
||||||
@@ -613,45 +612,43 @@ export const CustomArrayManager = () => {
|
|||||||
// ^ if managing a block array, you need to specify the block type
|
// ^ if managing a block array, you need to specify the block type
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Replace Row
|
Replace Row
|
||||||
</button>
|
</button>
|
||||||
)
|
) } \`\`\`
|
||||||
}
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
An example config to go along with the Custom Component
|
An example config to go along with the Custom Component
|
||||||
|
|
||||||
\`\`\`tsx
|
\`\`\`tsx
|
||||||
const ExampleCollection = {
|
const ExampleCollection = {
|
||||||
slug: "example-collection",
|
slug: "example-collection",
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: "arrayField",
|
name: "arrayField",
|
||||||
type: "array",
|
type: "array",
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: "textField",
|
name: "textField",
|
||||||
type: "text",
|
type: "text",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "ui",
|
type: "ui",
|
||||||
name: "customArrayManager",
|
name: "customArrayManager",
|
||||||
admin: {
|
admin: {
|
||||||
components: {
|
components: {
|
||||||
Field: '/path/to/CustomArrayManagerField',
|
Field: '/path/to/CustomArrayManagerField',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
\`\`\`
|
\`\`\`
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
## useDocumentForm
|
## useDocumentForm
|
||||||
@@ -669,7 +666,9 @@ const MyComponent: React.FC = () => {
|
|||||||
const { fields: parentDocumentFields } = useDocumentForm()
|
const { fields: parentDocumentFields } = useDocumentForm()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<p>The document's Form has ${Object.keys(parentDocumentFields).length} fields</p>
|
<p>
|
||||||
|
The document's Form has ${Object.keys(parentDocumentFields).length} fields
|
||||||
|
</p>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -712,7 +711,7 @@ const CustomComponent: React.FC = () => {
|
|||||||
The `useDocumentInfo` hook provides information about the current document being edited, including the following:
|
The `useDocumentInfo` hook provides information about the current document being edited, including the following:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| ----------------------------------- | ------------------------------------------------------------------------------------------------------- |
|
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| **`action`** | The URL attached to the action attribute on the underlying form element, which specifies where to send the form data when the form is submitted. |
|
| **`action`** | The URL attached to the action attribute on the underlying form element, which specifies where to send the form data when the form is submitted. |
|
||||||
| **`apiURL`** | The API URL for the current document. |
|
| **`apiURL`** | The API URL for the current document. |
|
||||||
| **`collectionSlug`** | The slug of the collection if editing a collection document. |
|
| **`collectionSlug`** | The slug of the collection if editing a collection document. |
|
||||||
@@ -764,7 +763,9 @@ const LinkFromCategoryToPosts: React.FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<a href={`/admin/collections/posts?where[or][0][and][0][category][in][0]=[${id}]`}>
|
<a
|
||||||
|
href={`/admin/collections/posts?where[or][0][and][0][category][in][0]=[${id}]`}
|
||||||
|
>
|
||||||
View posts
|
View posts
|
||||||
</a>
|
</a>
|
||||||
)
|
)
|
||||||
@@ -791,9 +792,9 @@ const MyComponent: React.FC = () => {
|
|||||||
The `useListQuery` hook returns an object with the following properties:
|
The `useListQuery` hook returns an object with the following properties:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| ----------------- | --------------------------------------------------------------------------------------------- |
|
| ------------------------- | ------------------------------------------------------------------------ |
|
||||||
| **`data`** | The data that is being displayed in the List View. |
|
| **`data`** | The data that is being displayed in the List View. |
|
||||||
| **`defaultLimit`**| The default limit of items to display in the List View. |
|
| **`defaultLimit`** | The default limit of items to display in the List View. |
|
||||||
| **`defaultSort`** | The default sort order of items in the List View. |
|
| **`defaultSort`** | The default sort order of items in the List View. |
|
||||||
| **`handlePageChange`** | A method to handle page changes in the List View. |
|
| **`handlePageChange`** | A method to handle page changes in the List View. |
|
||||||
| **`handlePerPageChange`** | A method to handle per page changes in the List View. |
|
| **`handlePerPageChange`** | A method to handle per page changes in the List View. |
|
||||||
@@ -829,11 +830,10 @@ const MyComponent: React.FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<span>Selected {count} out of {totalDocs} docs!</span>
|
<span>
|
||||||
<button
|
Selected {count} out of {totalDocs} docs!
|
||||||
type="button"
|
</span>
|
||||||
onClick={() => toggleAll(true)}
|
<button type="button" onClick={() => toggleAll(true)}>
|
||||||
>
|
|
||||||
Toggle All Selections
|
Toggle All Selections
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
@@ -917,10 +917,12 @@ import { useConfig } from '@payloadcms/ui'
|
|||||||
const MyComponent: React.FC = () => {
|
const MyComponent: React.FC = () => {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
const { getEntityConfig } = useConfig()
|
const { getEntityConfig } = useConfig()
|
||||||
const mediaConfig = getEntityConfig({ collectionSlug: 'media'})
|
const mediaConfig = getEntityConfig({ collectionSlug: 'media' })
|
||||||
// highlight-end
|
// highlight-end
|
||||||
|
|
||||||
return <span>The media collection has {mediaConfig.fields.length} fields.</span>
|
return (
|
||||||
|
<span>The media collection has {mediaConfig.fields.length} fields.</span>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -965,7 +967,9 @@ const MyComponent: React.FC = () => {
|
|||||||
</span>
|
</span>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setTheme((prev) => (prev === 'light' ? 'dark' : 'light'))}
|
onClick={() =>
|
||||||
|
setTheme((prev) => (prev === 'light' ? 'dark' : 'light'))
|
||||||
|
}
|
||||||
>
|
>
|
||||||
Toggle theme
|
Toggle theme
|
||||||
</button>
|
</button>
|
||||||
@@ -1022,8 +1026,9 @@ const ListenForUpdates: React.FC = () => {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
Right now the `useDocumentEvents` hook only tracks recently updated documents, but in the future
|
Right now the `useDocumentEvents` hook only tracks recently updated documents,
|
||||||
it will track more document-related events as needed, such as document creation, deletion, etc.
|
but in the future it will track more document-related events as needed, such
|
||||||
|
as document creation, deletion, etc.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## useStepNav
|
## useStepNav
|
||||||
@@ -1031,7 +1036,7 @@ const ListenForUpdates: React.FC = () => {
|
|||||||
The `useStepNav` hook provides a way to change the step-nav breadcrumb links in the app header.
|
The `useStepNav` hook provides a way to change the step-nav breadcrumb links in the app header.
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| ---------------- | --------------------------------------------------------------------------------- |
|
| ---------------- | -------------------------------------------------------------------------------- |
|
||||||
| **`setStepNav`** | A state setter function which sets the `stepNav` array. |
|
| **`setStepNav`** | A state setter function which sets the `stepNav` array. |
|
||||||
| **`stepNav`** | A `StepNavItem` array where each `StepNavItem` has a label and optionally a url. |
|
| **`stepNav`** | A `StepNavItem` array where each `StepNavItem` has a label and optionally a url. |
|
||||||
|
|
||||||
@@ -1074,7 +1079,9 @@ const MyComponent: React.FC = () => {
|
|||||||
// Fetch data from a collection item using its ID
|
// Fetch data from a collection item using its ID
|
||||||
const [{ data, isError, isLoading }, { setParams }] = usePayloadAPI(
|
const [{ data, isError, isLoading }, { setParams }] = usePayloadAPI(
|
||||||
'/api/posts/123',
|
'/api/posts/123',
|
||||||
{ initialParams: { depth: 1 } }
|
{
|
||||||
|
initialParams: { depth: 1 },
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
if (isLoading) return <p>Loading...</p>
|
if (isLoading) return <p>Loading...</p>
|
||||||
@@ -1141,11 +1148,7 @@ By default, any instances of `Link` from `@payloadcms/ui` will trigger route tra
|
|||||||
import { Link } from '@payloadcms/ui'
|
import { Link } from '@payloadcms/ui'
|
||||||
|
|
||||||
const MyComponent = () => {
|
const MyComponent = () => {
|
||||||
return (
|
return <Link href="/somewhere">Go Somewhere</Link>
|
||||||
<Link href="/somewhere">
|
|
||||||
Go Somewhere
|
|
||||||
</Link>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ For example, if you have a third-party service or external app that needs to be
|
|||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Tip:**
|
**Tip:**
|
||||||
|
|
||||||
This is particularly useful as you can create a "user" that reflects an integration with a specific external service and assign a "role" or specific access only needed by that service/integration.
|
This is particularly useful as you can create a "user" that reflects an integration with a specific external service and assign a "role" or specific access only needed by that service/integration.
|
||||||
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
Technically, both of these options will work for third-party integrations but the second option with API key is simpler, because it reduces the amount of work that your integrations need to do to be authenticated properly.
|
Technically, both of these options will work for third-party integrations but the second option with API key is simpler, because it reduces the amount of work that your integrations need to do to be authenticated properly.
|
||||||
@@ -42,8 +43,9 @@ your API keys will not be.
|
|||||||
**Important:**
|
**Important:**
|
||||||
If you change your `PAYLOAD_SECRET`, you will need to regenerate your API keys.
|
If you change your `PAYLOAD_SECRET`, you will need to regenerate your API keys.
|
||||||
|
|
||||||
The secret key is used to encrypt the API keys, so if you change the secret, existing API keys will
|
The secret key is used to encrypt the API keys, so if you change the secret, existing API keys will
|
||||||
no longer be valid.
|
no longer be valid.
|
||||||
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### HTTP Authentication
|
### HTTP Authentication
|
||||||
|
|||||||
@@ -9,8 +9,9 @@ keywords: authentication, config, configuration, documentation, Content Manageme
|
|||||||
Payload offers the ability to [Authenticate](./overview) via HTTP-only cookies. These can be read from the responses of `login`, `logout`, `refresh`, and `me` auth operations.
|
Payload offers the ability to [Authenticate](./overview) via HTTP-only cookies. These can be read from the responses of `login`, `logout`, `refresh`, and `me` auth operations.
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Tip:**
|
**Tip:** You can access the logged-in user from within [Access
|
||||||
You can access the logged-in user from within [Access Control](../access-control/overview) and [Hooks](../hooks/overview) through the `req.user` argument. [More details](./token-data).
|
Control](../access-control/overview) and [Hooks](../hooks/overview) through
|
||||||
|
the `req.user` argument. [More details](./token-data).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### Automatic browser inclusion
|
### Automatic browser inclusion
|
||||||
@@ -34,10 +35,10 @@ const pages = await response.json()
|
|||||||
For more about including cookies in requests from your app to your Payload API, [read the MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Sending_a_request_with_credentials_included).
|
For more about including cookies in requests from your app to your Payload API, [read the MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Sending_a_request_with_credentials_included).
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Tip:**
|
**Tip:** To make sure you have a Payload cookie set properly in your browser
|
||||||
To make sure you have a Payload cookie set properly in your browser after logging in, you can use
|
after logging in, you can use the browsers Developer Tools > Application >
|
||||||
the browsers Developer Tools > Application > Cookies > [your-domain-here]. The Developer tools
|
Cookies > [your-domain-here]. The Developer tools will still show HTTP-only
|
||||||
will still show HTTP-only cookies.
|
cookies.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### CSRF Attacks
|
### CSRF Attacks
|
||||||
@@ -53,8 +54,8 @@ So, if a user of `https://payload-finances.com` is logged in and is browsing aro
|
|||||||
// makes an authenticated request as on your behalf
|
// makes an authenticated request as on your behalf
|
||||||
|
|
||||||
const maliciousRequest = await fetch(`https://payload-finances.com/api/me`, {
|
const maliciousRequest = await fetch(`https://payload-finances.com/api/me`, {
|
||||||
credentials: 'include'
|
credentials: 'include',
|
||||||
}).then(res => await res.json())
|
}).then((res) => await res.json())
|
||||||
```
|
```
|
||||||
|
|
||||||
In this scenario, if your cookie was still valid, malicious-intent.com would be able to make requests like the one above on your behalf. This is a CSRF attack.
|
In this scenario, if your cookie was still valid, malicious-intent.com would be able to make requests like the one above on your behalf. This is a CSRF attack.
|
||||||
@@ -124,8 +125,8 @@ Configuration example:
|
|||||||
|
|
||||||
If you're configuring [cors](../production/preventing-abuse#cross-origin-resource-sharing-cors) in your Payload config, you won't be able to use a wildcard anymore, you'll need to specify the list of allowed domains.
|
If you're configuring [cors](../production/preventing-abuse#cross-origin-resource-sharing-cors) in your Payload config, you won't be able to use a wildcard anymore, you'll need to specify the list of allowed domains.
|
||||||
|
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Good to know:**
|
**Good to know:** Setting up `secure: true` will not work if you're developing
|
||||||
Setting up `secure: true` will not work if you're developing on `http://localhost` or any non-https domain. For local development you should conditionally set this to `false` based on the environment.
|
on `http://localhost` or any non-https domain. For local development you
|
||||||
|
should conditionally set this to `false` based on the environment.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ keywords: authentication, config, configuration, overview, documentation, Conten
|
|||||||
---
|
---
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
This is an advanced feature, so only attempt this if you are an experienced developer. Otherwise,
|
This is an advanced feature, so only attempt this if you are an experienced
|
||||||
just let Payload's built-in authentication handle user auth for you.
|
developer. Otherwise, just let Payload's built-in authentication handle user
|
||||||
|
auth for you.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### Creating a strategy
|
### Creating a strategy
|
||||||
@@ -18,19 +19,18 @@ At the core, a strategy is a way to authenticate a user making a request. As of
|
|||||||
A strategy is made up of the following:
|
A strategy is made up of the following:
|
||||||
|
|
||||||
| Parameter | Description |
|
| Parameter | Description |
|
||||||
| --------------------------- | ------------------------------------------------------------------------- |
|
| --------------------- | ------------------------------------------------------------------------- |
|
||||||
| **`name`** * | The name of your strategy |
|
| **`name`** \* | The name of your strategy |
|
||||||
| **`authenticate`** * | A function that takes in the parameters below and returns a user or null. |
|
| **`authenticate`** \* | A function that takes in the parameters below and returns a user or null. |
|
||||||
|
|
||||||
The `authenticate` function is passed the following arguments:
|
The `authenticate` function is passed the following arguments:
|
||||||
|
|
||||||
| Argument | Description |
|
| Argument | Description |
|
||||||
| ------------------- | ------------------------------------------------------------------------------------------------- |
|
| ---------------- | ------------------------------------------------------------------------------------------------- |
|
||||||
| **`headers`** * | The headers on the incoming request. Useful for retrieving identifiable information on a request. |
|
| **`headers`** \* | The headers on the incoming request. Useful for retrieving identifiable information on a request. |
|
||||||
| **`payload`** * | The Payload class. Useful for authenticating the identifiable information against Payload. |
|
| **`payload`** \* | The Payload class. Useful for authenticating the identifiable information against Payload. |
|
||||||
| **`isGraphQL`** | Whether or not the request was made from a GraphQL endpoint. Default is `false`. |
|
| **`isGraphQL`** | Whether or not the request was made from a GraphQL endpoint. Default is `false`. |
|
||||||
|
|
||||||
|
|
||||||
### Example Strategy
|
### Example Strategy
|
||||||
|
|
||||||
At its core a strategy simply takes information from the incoming request and returns a user. This is exactly how Payload's built-in strategies function.
|
At its core a strategy simply takes information from the incoming request and returns a user. This is exactly how Payload's built-in strategies function.
|
||||||
|
|||||||
@@ -20,14 +20,14 @@ import type { CollectionConfig } from 'payload'
|
|||||||
export const Customers: CollectionConfig = {
|
export const Customers: CollectionConfig = {
|
||||||
// ...
|
// ...
|
||||||
auth: {
|
auth: {
|
||||||
verify: true // highlight-line
|
verify: true, // highlight-line
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
**Tip:**
|
**Tip:** Verification emails are fully customizable. [More
|
||||||
Verification emails are fully customizable. [More details](#generateemailhtml).
|
details](#generateemailhtml).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
The following options are available:
|
The following options are available:
|
||||||
@@ -62,11 +62,11 @@ export const Customers: CollectionConfig = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Important:**
|
**Important:** If you specify a different URL to send your users to for email
|
||||||
If you specify a different URL to send your users to for email verification, such as a page on the
|
verification, such as a page on the frontend of your app or similar, you need
|
||||||
frontend of your app or similar, you need to handle making the call to the Payload REST or GraphQL
|
to handle making the call to the Payload REST or GraphQL verification
|
||||||
verification operation yourself on your frontend, using the token that was provided for you.
|
operation yourself on your frontend, using the token that was provided for
|
||||||
Above, it was passed via query parameter.
|
you. Above, it was passed via query parameter.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
#### generateEmailSubject
|
#### generateEmailSubject
|
||||||
@@ -82,11 +82,11 @@ export const Customers: CollectionConfig = {
|
|||||||
verify: {
|
verify: {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
generateEmailSubject: ({ req, user }) => {
|
generateEmailSubject: ({ req, user }) => {
|
||||||
return `Hey ${user.email}, reset your password!`;
|
return `Hey ${user.email}, reset your password!`
|
||||||
}
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -100,7 +100,8 @@ import type { CollectionConfig } from 'payload'
|
|||||||
export const Customers: CollectionConfig = {
|
export const Customers: CollectionConfig = {
|
||||||
// ...
|
// ...
|
||||||
auth: {
|
auth: {
|
||||||
forgotPassword: { // highlight-line
|
forgotPassword: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -110,7 +111,7 @@ export const Customers: CollectionConfig = {
|
|||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
|----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`expiration`** | Configure how long password reset tokens remain valid, specified in milliseconds. |
|
| **`expiration`** | Configure how long password reset tokens remain valid, specified in milliseconds. |
|
||||||
| **`generateEmailHTML`** | Allows for overriding the HTML within emails that are sent to users attempting to reset their password. [More details](#generateEmailHTML). |
|
| **`generateEmailHTML`** | Allows for overriding the HTML within emails that are sent to users attempting to reset their password. [More details](#generateEmailHTML). |
|
||||||
| **`generateEmailSubject`** | Allows for overriding the subject of the email that is sent to users attempting to reset their password. [More details](#generateEmailSubject). |
|
| **`generateEmailSubject`** | Allows for overriding the subject of the email that is sent to users attempting to reset their password. [More details](#generateEmailSubject). |
|
||||||
@@ -152,25 +153,25 @@ export const Customers: CollectionConfig = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Important:**
|
**Important:** If you specify a different URL to send your users to for
|
||||||
If you specify a different URL to send your users to for resetting their password, such as a page
|
resetting their password, such as a page on the frontend of your app or
|
||||||
on the frontend of your app or similar, you need to handle making the call to the Payload REST or
|
similar, you need to handle making the call to the Payload REST or GraphQL
|
||||||
GraphQL reset-password operation yourself on your frontend, using the token that was provided for
|
reset-password operation yourself on your frontend, using the token that was
|
||||||
you. Above, it was passed via query parameter.
|
provided for you. Above, it was passed via query parameter.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Tip:**
|
**Tip:** HTML templating can be used to create custom email templates, inline
|
||||||
HTML templating can be used to create custom email templates, inline CSS automatically, and more.
|
CSS automatically, and more. You can make a reusable function that
|
||||||
You can make a reusable function that standardizes all email sent from Payload, which makes
|
standardizes all email sent from Payload, which makes sending custom emails
|
||||||
sending custom emails more DRY. Payload doesn't ship with an HTML templating engine, so you are
|
more DRY. Payload doesn't ship with an HTML templating engine, so you are free
|
||||||
free to choose your own.
|
to choose your own.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
The following arguments are passed to the `generateEmailHTML` function:
|
The following arguments are passed to the `generateEmailHTML` function:
|
||||||
|
|
||||||
| Argument | Description |
|
| Argument | Description |
|
||||||
|----------|-----------------------------------------------------------------------------------------------|
|
| -------- | ----------------------------------------------------------------- |
|
||||||
| `req` | The request object. |
|
| `req` | The request object. |
|
||||||
| `token` | The token that is generated for the user to reset their password. |
|
| `token` | The token that is generated for the user to reset their password. |
|
||||||
| `user` | The user document that is attempting to reset their password. |
|
| `user` | The user document that is attempting to reset their password. |
|
||||||
@@ -188,17 +189,17 @@ export const Customers: CollectionConfig = {
|
|||||||
forgotPassword: {
|
forgotPassword: {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
generateEmailSubject: ({ req, user }) => {
|
generateEmailSubject: ({ req, user }) => {
|
||||||
return `Hey ${user.email}, reset your password!`;
|
return `Hey ${user.email}, reset your password!`
|
||||||
}
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The following arguments are passed to the `generateEmailSubject` function:
|
The following arguments are passed to the `generateEmailSubject` function:
|
||||||
|
|
||||||
| Argument | Description |
|
| Argument | Description |
|
||||||
|----------|-----------------------------------------------------------------------------------------------|
|
| -------- | ------------------------------------------------------------- |
|
||||||
| `req` | The request object. |
|
| `req` | The request object. |
|
||||||
| `user` | The user document that is attempting to reset their password. |
|
| `user` | The user document that is attempting to reset their password. |
|
||||||
|
|||||||
@@ -9,8 +9,9 @@ keywords: authentication, config, configuration, documentation, Content Manageme
|
|||||||
Payload offers the ability to [Authenticate](./overview) via JSON Web Tokens (JWT). These can be read from the responses of `login`, `logout`, `refresh`, and `me` auth operations.
|
Payload offers the ability to [Authenticate](./overview) via JSON Web Tokens (JWT). These can be read from the responses of `login`, `logout`, `refresh`, and `me` auth operations.
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Tip:**
|
**Tip:** You can access the logged-in user from within [Access
|
||||||
You can access the logged-in user from within [Access Control](../access-control/overview) and [Hooks](../hooks/overview) through the `req.user` argument. [More details](./token-data).
|
Control](../access-control/overview) and [Hooks](../hooks/overview) through
|
||||||
|
the `req.user` argument. [More details](./token-data).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### Identifying Users Via The Authorization Header
|
### Identifying Users Via The Authorization Header
|
||||||
@@ -25,8 +26,8 @@ const user = await fetch('http://localhost:3000/api/users/login', {
|
|||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
email: 'dev@payloadcms.com',
|
email: 'dev@payloadcms.com',
|
||||||
password: 'password',
|
password: 'password',
|
||||||
})
|
}),
|
||||||
}).then(req => await req.json())
|
}).then((req) => await req.json())
|
||||||
|
|
||||||
const request = await fetch('http://localhost:3000', {
|
const request = await fetch('http://localhost:3000', {
|
||||||
headers: {
|
headers: {
|
||||||
|
|||||||
@@ -200,12 +200,15 @@ If successful, this operation will automatically renew the user's HTTP-only cook
|
|||||||
**Example REST API token refresh**:
|
**Example REST API token refresh**:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const res = await fetch('http://localhost:3000/api/[collection-slug]/refresh-token', {
|
const res = await fetch(
|
||||||
|
'http://localhost:3000/api/[collection-slug]/refresh-token',
|
||||||
|
{
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
const json = await res.json()
|
const json = await res.json()
|
||||||
|
|
||||||
@@ -244,12 +247,15 @@ If your collection supports email verification, the Verify operation will be exp
|
|||||||
**Example REST API user verification**:
|
**Example REST API user verification**:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const res = await fetch(`http://localhost:3000/api/[collection-slug]/verify/${TOKEN_HERE}`, {
|
const res = await fetch(
|
||||||
|
`http://localhost:3000/api/[collection-slug]/verify/${TOKEN_HERE}`,
|
||||||
|
{
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
})
|
},
|
||||||
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Example GraphQL Mutation**:
|
**Example GraphQL Mutation**:
|
||||||
@@ -317,7 +323,9 @@ By default, the Forgot Password operations send users to the [Admin Panel](../ad
|
|||||||
**Example REST API Forgot Password**:
|
**Example REST API Forgot Password**:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const res = await fetch(`http://localhost:3000/api/[collection-slug]/forgot-password`, {
|
const res = await fetch(
|
||||||
|
`http://localhost:3000/api/[collection-slug]/forgot-password`,
|
||||||
|
{
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@@ -325,7 +333,8 @@ const res = await fetch(`http://localhost:3000/api/[collection-slug]/forgot-pass
|
|||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
email: 'dev@payloadcms.com',
|
email: 'dev@payloadcms.com',
|
||||||
}),
|
}),
|
||||||
})
|
},
|
||||||
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Example GraphQL Mutation**:
|
**Example GraphQL Mutation**:
|
||||||
@@ -349,17 +358,24 @@ const token = await payload.forgotPassword({
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
**Note:** if you do not have a `config.serverURL` set, Payload will attempt to create one for you if the `forgot-password` operation was triggered via REST or GraphQL by looking at the incoming `req`. But this is not supported if you are calling `payload.forgotPassword()` via the Local API. If you do not have a `serverURL` set, you may want to override your `auth.forgotPassword.generateEmailHTML` function to provide a full URL to link the user to a proper reset-password page.
|
**Note:** if you do not have a `config.serverURL` set, Payload will attempt to
|
||||||
|
create one for you if the `forgot-password` operation was triggered via REST
|
||||||
|
or GraphQL by looking at the incoming `req`. But this is not supported if you
|
||||||
|
are calling `payload.forgotPassword()` via the Local API. If you do not have a
|
||||||
|
`serverURL` set, you may want to override your
|
||||||
|
`auth.forgotPassword.generateEmailHTML` function to provide a full URL to link
|
||||||
|
the user to a proper reset-password page.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Tip:**
|
**Tip:**
|
||||||
|
|
||||||
You can stop the reset-password email from being sent via using the local API. This is helpful if
|
You can stop the reset-password email from being sent via using the local API. This is helpful if
|
||||||
you need to create user accounts programmatically, but not set their password for them. This
|
you need to create user accounts programmatically, but not set their password for them. This
|
||||||
effectively generates a reset password token which you can then use to send to a page you create,
|
effectively generates a reset password token which you can then use to send to a page you create,
|
||||||
allowing a user to "complete" their account by setting their password. In the background, you'd
|
allowing a user to "complete" their account by setting their password. In the background, you'd
|
||||||
use the token to "reset" their password.
|
use the token to "reset" their password.
|
||||||
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Reset Password
|
## Reset Password
|
||||||
|
|||||||
@@ -41,8 +41,9 @@ _Admin Panel screenshot depicting an Admins Collection with Auth enabled_
|
|||||||
Any [Collection](../configuration/collections) can opt-in to supporting Authentication. Once enabled, each Document that is created within the Collection can be thought of as a "user". This enables a complete authentication workflow on your Collection, such as logging in and out, resetting their password, and more.
|
Any [Collection](../configuration/collections) can opt-in to supporting Authentication. Once enabled, each Document that is created within the Collection can be thought of as a "user". This enables a complete authentication workflow on your Collection, such as logging in and out, resetting their password, and more.
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Note:**
|
**Note:** By default, Payload provides an auth-enabled `User` Collection which
|
||||||
By default, Payload provides an auth-enabled `User` Collection which is used to access the Admin Panel. [More details](../admin/overview#the-admin-user-collection).
|
is used to access the Admin Panel. [More
|
||||||
|
details](../admin/overview#the-admin-user-collection).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
To enable Authentication on a Collection, use the `auth` property in the [Collection Config](../configuration/collections):
|
To enable Authentication on a Collection, use the `auth` property in the [Collection Config](../configuration/collections):
|
||||||
@@ -65,19 +66,20 @@ export const Admins: CollectionConfig = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
**Tip:**
|
**Tip:** For default auth behavior, set `auth: true`. This is a good starting
|
||||||
For default auth behavior, set `auth: true`. This is a good starting point for most applications.
|
point for most applications.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Note:**
|
**Note:** Auth-enabled Collections with be automatically injected with the
|
||||||
Auth-enabled Collections with be automatically injected with the `hash`, `salt`, and `email` fields. [More details](../fields/overview#field-names).
|
`hash`, `salt`, and `email` fields. [More
|
||||||
|
details](../fields/overview#field-names).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
|----------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`cookies`** | Set cookie options, including `secure`, `sameSite`, and `domain`. For advanced users. |
|
| **`cookies`** | Set cookie options, including `secure`, `sameSite`, and `domain`. For advanced users. |
|
||||||
| **`depth`** | How many levels deep a `user` document should be populated when creating the JWT and binding the `user` to the `req`. Defaults to `0` and should only be modified if absolutely necessary, as this will affect performance. |
|
| **`depth`** | How many levels deep a `user` document should be populated when creating the JWT and binding the `user` to the `req`. Defaults to `0` and should only be modified if absolutely necessary, as this will affect performance. |
|
||||||
| **`disableLocalStrategy`** | Advanced - disable Payload's built-in local auth strategy. Only use this property if you have replaced Payload's auth mechanisms with your own. |
|
| **`disableLocalStrategy`** | Advanced - disable Payload's built-in local auth strategy. Only use this property if you have replaced Payload's auth mechanisms with your own. |
|
||||||
@@ -153,14 +155,15 @@ export default buildConfig({
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Warning:**
|
**Warning:** The recommended way to use this feature is behind an [Environment
|
||||||
The recommended way to use this feature is behind an [Environment Variable](../configuration/environment-vars). This will ensure it is _disabled_ in production.
|
Variable](../configuration/environment-vars). This will ensure it is
|
||||||
|
_disabled_ in production.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
|-------------------|-----------------------------------------------------------------------------------------------------------------|
|
| ----------------- | --------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`username`** | The username of the user to login as |
|
| **`username`** | The username of the user to login as |
|
||||||
| **`email`** | The email address of the user to login as |
|
| **`email`** | The email address of the user to login as |
|
||||||
| **`password`** | The password of the user to login as. This is only needed if `prefillOnly` is set to true |
|
| **`password`** | The password of the user to login as. This is only needed if `prefillOnly` is set to true |
|
||||||
|
|||||||
@@ -24,10 +24,7 @@ export const Users: CollectionConfig = {
|
|||||||
saveToJWT: true,
|
saveToJWT: true,
|
||||||
type: 'select',
|
type: 'select',
|
||||||
name: 'role',
|
name: 'role',
|
||||||
options: [
|
options: ['super-admin', 'user'],
|
||||||
'super-admin',
|
|
||||||
'user',
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// the entire object will be stored in the JWT
|
// the entire object will be stored in the JWT
|
||||||
@@ -46,7 +43,7 @@ export const Users: CollectionConfig = {
|
|||||||
type: 'text',
|
type: 'text',
|
||||||
name: 'omitField',
|
name: 'omitField',
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'group',
|
type: 'group',
|
||||||
@@ -63,18 +60,18 @@ export const Users: CollectionConfig = {
|
|||||||
type: 'text',
|
type: 'text',
|
||||||
name: 'omitField',
|
name: 'omitField',
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Tip:**
|
**Tip:**
|
||||||
|
|
||||||
If you wish to use a different key other than the field `name`, you can define `saveToJWT` as a string.
|
If you wish to use a different key other than the field `name`, you can define `saveToJWT` as a string.
|
||||||
</Banner>
|
|
||||||
|
|
||||||
|
</Banner>
|
||||||
|
|
||||||
### Using Token Data
|
### Using Token Data
|
||||||
|
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ keywords: configuration, config, settings, project, cloud, payload cloud, deploy
|
|||||||
Once you have created a project, you will need to select your plan. This will determine the resources that are allocated to your project and the features that are available to you.
|
Once you have created a project, you will need to select your plan. This will determine the resources that are allocated to your project and the features that are available to you.
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
Note: All Payload Cloud teams that deploy a project require a card on file. This helps us prevent
|
Note: All Payload Cloud teams that deploy a project require a card on file.
|
||||||
fraud and abuse on our platform. If you select a plan with a free trial, you will not be charged
|
This helps us prevent fraud and abuse on our platform. If you select a plan
|
||||||
until your trial period is over. We’ll remind you 7 days before your trial ends and you can cancel
|
with a free trial, you will not be charged until your trial period is over.
|
||||||
anytime.
|
We’ll remind you 7 days before your trial ends and you can cancel anytime.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Project Details
|
## Project Details
|
||||||
@@ -44,8 +44,8 @@ If you are deploying a new project from a template, the following settings will
|
|||||||
Any of the features in Payload Cloud that require environment variables will automatically be provided to your application. If your app requires any custom environment variables, you can set them here.
|
Any of the features in Payload Cloud that require environment variables will automatically be provided to your application. If your app requires any custom environment variables, you can set them here.
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
Note: For security reasons, any variables you wish to provide to the [Admin Panel](../admin/overview) must be prefixed
|
Note: For security reasons, any variables you wish to provide to the [Admin
|
||||||
with `NEXT_PUBLIC_`. Learn more
|
Panel](../admin/overview) must be prefixed with `NEXT_PUBLIC_`. Learn more
|
||||||
[here](../configuration/environment-vars).
|
[here](../configuration/environment-vars).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
@@ -54,8 +54,9 @@ Any of the features in Payload Cloud that require environment variables will aut
|
|||||||
Payment methods can be set per project and can be updated any time. You can use team’s default payment method, or add a new one. Modify your payment methods in your Project settings / Team settings.
|
Payment methods can be set per project and can be updated any time. You can use team’s default payment method, or add a new one. Modify your payment methods in your Project settings / Team settings.
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Note:** All Payload Cloud teams that deploy a project require a card on file. This
|
**Note:** All Payload Cloud teams that deploy a project require a card on
|
||||||
helps us prevent fraud and abuse on our platform. If you select a plan with a free trial, you will
|
file. This helps us prevent fraud and abuse on our platform. If you select a
|
||||||
not be charged until your trial period is over. We’ll remind you 7 days before your trial ends and
|
plan with a free trial, you will not be charged until your trial period is
|
||||||
you can cancel anytime.
|
over. We’ll remind you 7 days before your trial ends and you can cancel
|
||||||
|
anytime.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|||||||
@@ -13,8 +13,9 @@ Payload Cloud offers various plans tailored to meet your specific needs, includi
|
|||||||
To get started, you first need to create an account. Head over to [the login screen](https://payloadcms.com/login) and **Register for Free**.
|
To get started, you first need to create an account. Head over to [the login screen](https://payloadcms.com/login) and **Register for Free**.
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
To create your first project, you can either select [a template](#starting-from-a-template) or
|
To create your first project, you can either select [a
|
||||||
[import an existing project](#importing-from-an-existing-codebase) from GitHub.
|
template](#starting-from-a-template) or [import an existing
|
||||||
|
project](#importing-from-an-existing-codebase) from GitHub.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Starting from a Template
|
## Starting from a Template
|
||||||
@@ -45,7 +46,8 @@ Payload Cloud works for any Node.js + MongoDB app. From the New Project page, se
|
|||||||
_Creating a new project from an existing repository._
|
_Creating a new project from an existing repository._
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Note:** In order to make use of the features of Payload Cloud in your own codebase,
|
**Note:** In order to make use of the features of Payload Cloud in your own
|
||||||
you will need to add the [Cloud Plugin](https://github.com/payloadcms/payload/tree/main/packages/payload-cloud) to your
|
codebase, you will need to add the [Cloud
|
||||||
Payload app.
|
Plugin](https://github.com/payloadcms/payload/tree/main/packages/payload-cloud)
|
||||||
|
to your Payload app.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|||||||
@@ -9,10 +9,11 @@ keywords: cloud, payload cloud, projects, project, overview, database, file stor
|
|||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
<Banner>
|
<Banner>
|
||||||
The overview tab shows your most recent deployment, along with build and deployment logs. From
|
The overview tab shows your most recent deployment, along with build and
|
||||||
here, you can see your live URL, deployment details like timestamps and commit hash, as well as
|
deployment logs. From here, you can see your live URL, deployment details like
|
||||||
the status of your deployment. You can also trigger a redeployment manually, which will rebuild
|
timestamps and commit hash, as well as the status of your deployment. You can
|
||||||
your project using the current configuration.
|
also trigger a redeployment manually, which will rebuild your project using
|
||||||
|
the current configuration.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||

|

|
||||||
@@ -59,7 +60,9 @@ You can update settings from your Project’s Settings tab. Changes to your buil
|
|||||||
From the Environment Variables page of the Settings tab, you can add, update and delete variables for use in your project. Like build settings, these changes will trigger a redeployment of your project.
|
From the Environment Variables page of the Settings tab, you can add, update and delete variables for use in your project. Like build settings, these changes will trigger a redeployment of your project.
|
||||||
|
|
||||||
<Banner>
|
<Banner>
|
||||||
Note: For security reasons, any variables you wish to provide to the [Admin Panel](../admin/overview) must be prefixed with `NEXT_PUBLIC_`. [More details](../configuration/environment-vars).
|
Note: For security reasons, any variables you wish to provide to the [Admin
|
||||||
|
Panel](../admin/overview) must be prefixed with `NEXT_PUBLIC_`. [More
|
||||||
|
details](../configuration/environment-vars).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Custom Domains
|
## Custom Domains
|
||||||
@@ -67,8 +70,9 @@ From the Environment Variables page of the Settings tab, you can add, update and
|
|||||||
With Payload Cloud, you can add custom domain names to your project. To do so, first go to the Domains page of the Settings tab of your project. Here you can see your default domain. To add a new domain, type in the domain name you wish to use.
|
With Payload Cloud, you can add custom domain names to your project. To do so, first go to the Domains page of the Settings tab of your project. Here you can see your default domain. To add a new domain, type in the domain name you wish to use.
|
||||||
|
|
||||||
<Banner>
|
<Banner>
|
||||||
Note: do not include the protocol (http:// or https://) or any paths (/page). Only include the
|
Note: do not include the protocol (http:// or https://) or any paths (/page).
|
||||||
domain name and extension, and optionally a subdomain. - your-domain.com - backend.your-domain.com
|
Only include the domain name and extension, and optionally a subdomain. -
|
||||||
|
your-domain.com - backend.your-domain.com
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
Once you click save, a DNS record will be generated for your domain name to point to your live project. Add this record into your DNS provider’s records, and once the records are resolving properly (this can take 1hr to 48hrs in some cases), your domain will now to point to your live project.
|
Once you click save, a DNS record will be generated for your domain name to point to your live project. Add this record into your DNS provider’s records, and once the records are resolving properly (this can take 1hr to 48hrs in some cases), your domain will now to point to your live project.
|
||||||
@@ -111,13 +115,14 @@ export default buildConfig({
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Note:** If your Payload Config already has an email with transport, this will take precedence
|
**Note:** If your Payload Config already has an email with transport, this
|
||||||
over Payload Cloud's email service.
|
will take precedence over Payload Cloud's email service.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
Good to know: the Payload Cloud Plugin was previously named `@payloadcms/plugin-cloud`. If you are
|
Good to know: the Payload Cloud Plugin was previously named
|
||||||
using this plugin, you should update to the new package name.
|
`@payloadcms/plugin-cloud`. If you are using this plugin, you should update to
|
||||||
|
the new package name.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
#### **Optional configuration**
|
#### **Optional configuration**
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ keywords: team, teams, billing, subscription, payment, plan, plans, cloud, paylo
|
|||||||
---
|
---
|
||||||
|
|
||||||
<Banner>
|
<Banner>
|
||||||
Within Payload Cloud, the team management feature offers you the ability to manage your
|
Within Payload Cloud, the team management feature offers you the ability to
|
||||||
organization, team members, billing, and subscription settings.
|
manage your organization, team members, billing, and subscription settings.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@@ -19,15 +19,16 @@ import { buildConfig } from 'payload'
|
|||||||
|
|
||||||
export default buildConfig({
|
export default buildConfig({
|
||||||
// ...
|
// ...
|
||||||
collections: [ // highlight-line
|
collections: [
|
||||||
|
// highlight-line
|
||||||
// Your Collections go here
|
// Your Collections go here
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Tip:**
|
**Tip:** If your Collection is only ever meant to contain a single Document,
|
||||||
If your Collection is only ever meant to contain a single Document, consider using a [Global](./globals) instead.
|
consider using a [Global](./globals) instead.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Config Options
|
## Config Options
|
||||||
@@ -45,14 +46,16 @@ export const Posts: CollectionConfig = {
|
|||||||
{
|
{
|
||||||
name: 'title',
|
name: 'title',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Reminder:**
|
**Reminder:** For more complex examples, see the
|
||||||
For more complex examples, see the [Templates](https://github.com/payloadcms/payload/tree/main/templates) and [Examples](https://github.com/payloadcms/payload/tree/main/examples) directories in the Payload repository.
|
[Templates](https://github.com/payloadcms/payload/tree/main/templates) and
|
||||||
|
[Examples](https://github.com/payloadcms/payload/tree/main/examples)
|
||||||
|
directories in the Payload repository.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
The following options are available:
|
The following options are available:
|
||||||
@@ -67,12 +70,12 @@ The following options are available:
|
|||||||
| `defaultSort` | Pass a top-level field to sort by default in the Collection List View. Prefix the name of the field with a minus symbol ("-") to sort in descending order. Multiple fields can be specified by using a string array. |
|
| `defaultSort` | Pass a top-level field to sort by default in the Collection List View. Prefix the name of the field with a minus symbol ("-") to sort in descending order. Multiple fields can be specified by using a string array. |
|
||||||
| `dbName` | Custom table or Collection name depending on the Database Adapter. Auto-generated from slug if not defined. |
|
| `dbName` | Custom table or Collection name depending on the Database Adapter. Auto-generated from slug if not defined. |
|
||||||
| `endpoints` | Add custom routes to the REST API. Set to `false` to disable routes. [More details](../rest-api/overview#custom-endpoints). |
|
| `endpoints` | Add custom routes to the REST API. Set to `false` to disable routes. [More details](../rest-api/overview#custom-endpoints). |
|
||||||
| `fields` * | Array of field types that will determine the structure and functionality of the data stored within this Collection. [More details](../fields/overview). |
|
| `fields` \* | Array of field types that will determine the structure and functionality of the data stored within this Collection. [More details](../fields/overview). |
|
||||||
| `graphQL` | Manage GraphQL-related properties for this collection. [More](#graphql) |
|
| `graphQL` | Manage GraphQL-related properties for this collection. [More](#graphql) |
|
||||||
| `hooks` | Entry point for Hooks. [More details](../hooks/overview#collection-hooks). |
|
| `hooks` | Entry point for Hooks. [More details](../hooks/overview#collection-hooks). |
|
||||||
| `labels` | Singular and plural labels for use in identifying this Collection throughout Payload. Auto-generated from slug if not defined. |
|
| `labels` | Singular and plural labels for use in identifying this Collection throughout Payload. Auto-generated from slug if not defined. |
|
||||||
| `lockDocuments` | Enables or disables document locking. By default, document locking is enabled. Set to an object to configure, or set to `false` to disable locking. [More details](../admin/locked-documents). |
|
| `lockDocuments` | Enables or disables document locking. By default, document locking is enabled. Set to an object to configure, or set to `false` to disable locking. [More details](../admin/locked-documents). |
|
||||||
| `slug` * | Unique, URL-friendly string that will act as an identifier for this Collection. |
|
| `slug` \* | Unique, URL-friendly string that will act as an identifier for this Collection. |
|
||||||
| `timestamps` | Set to false to disable documents' automatically generated `createdAt` and `updatedAt` timestamps. |
|
| `timestamps` | Set to false to disable documents' automatically generated `createdAt` and `updatedAt` timestamps. |
|
||||||
| `typescript` | An object with property `interface` as the text used in schema generation. Auto-generated from slug if not defined. |
|
| `typescript` | An object with property `interface` as the text used in schema generation. Auto-generated from slug if not defined. |
|
||||||
| `upload` | Specify options if you would like this Collection to support file uploads. For more, consult the [Uploads](../upload/overview) documentation. |
|
| `upload` | Specify options if you would like this Collection to support file uploads. For more, consult the [Uploads](../upload/overview) documentation. |
|
||||||
@@ -81,7 +84,7 @@ The following options are available:
|
|||||||
| `indexes` | Define compound indexes for this collection. This can be used to either speed up querying/sorting by 2 or more fields at the same time or to ensure uniqueness between several fields. |
|
| `indexes` | Define compound indexes for this collection. This can be used to either speed up querying/sorting by 2 or more fields at the same time or to ensure uniqueness between several fields. |
|
||||||
| `forceSelect` | Specify which fields should be selected always, regardless of the `select` query which can be useful that the field exists for access control / hooks |
|
| `forceSelect` | Specify which fields should be selected always, regardless of the `select` query which can be useful that the field exists for access control / hooks |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
### Fields
|
### Fields
|
||||||
|
|
||||||
@@ -106,7 +109,8 @@ import type { CollectionConfig } from 'payload'
|
|||||||
|
|
||||||
export const MyCollection: CollectionConfig = {
|
export const MyCollection: CollectionConfig = {
|
||||||
// ...
|
// ...
|
||||||
admin: { // highlight-line
|
admin: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -115,7 +119,7 @@ export const MyCollection: CollectionConfig = {
|
|||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `group` | Text or localization object used to group Collection and Global links in the admin navigation. Set to `false` to hide the link from the navigation while keeping its routes accessible. |
|
| `group` | Text or localization object used to group Collection and Global links in the admin navigation. Set to `false` to hide the link from the navigation while keeping its routes accessible. |
|
||||||
| `hidden` | Set to true or a function, called with the current user, returning true to exclude this Collection from navigation and admin routing. |
|
| `hidden` | Set to true or a function, called with the current user, returning true to exclude this Collection from navigation and admin routing. |
|
||||||
| `hooks` | Admin-specific hooks for this Collection. [More details](../hooks/collections). |
|
| `hooks` | Admin-specific hooks for this Collection. [More details](../hooks/collections). |
|
||||||
@@ -146,7 +150,8 @@ import type { CollectionConfig } from 'payload'
|
|||||||
export const MyCollection: CollectionConfig = {
|
export const MyCollection: CollectionConfig = {
|
||||||
// ...
|
// ...
|
||||||
admin: {
|
admin: {
|
||||||
components: { // highlight-line
|
components: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -156,7 +161,7 @@ export const MyCollection: CollectionConfig = {
|
|||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| --------------------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `afterList` | An array of components to inject _after_ the built-in List View. [More details](../custom-components/list-view#afterlist). |
|
| `afterList` | An array of components to inject _after_ the built-in List View. [More details](../custom-components/list-view#afterlist). |
|
||||||
| `afterListTable` | An array of components to inject _after_ the built-in List View's table. [More details](../custom-components/list-view#afterlisttable). |
|
| `afterListTable` | An array of components to inject _after_ the built-in List View's table. [More details](../custom-components/list-view#afterlisttable). |
|
||||||
| `beforeList` | An array of components to inject _before_ the built-in List View. [More details](../custom-components/list-view#beforelist). |
|
| `beforeList` | An array of components to inject _before_ the built-in List View. [More details](../custom-components/list-view#beforelist). |
|
||||||
@@ -175,7 +180,8 @@ export const MyCollection: CollectionCOnfig = {
|
|||||||
// ...
|
// ...
|
||||||
admin: {
|
admin: {
|
||||||
components: {
|
components: {
|
||||||
edit: { // highlight-line
|
edit: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -186,7 +192,7 @@ export const MyCollection: CollectionCOnfig = {
|
|||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `SaveButton` | Replace the default Save Button within the Edit View. [Drafts](../versions/drafts) must be disabled. [More details](../custom-components/edit-view#save-button). |
|
| `SaveButton` | Replace the default Save Button within the Edit View. [Drafts](../versions/drafts) must be disabled. [More details](../custom-components/edit-view#save-button). |
|
||||||
| `SaveDraftButton` | Replace the default Save Draft Button within the Edit View. [Drafts](../versions/drafts) must be enabled and autosave must be disabled. [More details](../custom-components/edit-view#save-draft-button). |
|
| `SaveDraftButton` | Replace the default Save Draft Button within the Edit View. [Drafts](../versions/drafts) must be enabled and autosave must be disabled. [More details](../custom-components/edit-view#save-draft-button). |
|
||||||
| `PublishButton` | Replace the default Publish Button within the Edit View. [Drafts](../versions/drafts) must be enabled. [More details](../custom-components/edit-view#publish-button). |
|
| `PublishButton` | Replace the default Publish Button within the Edit View. [Drafts](../versions/drafts) must be enabled. [More details](../custom-components/edit-view#publish-button). |
|
||||||
@@ -194,8 +200,8 @@ The following options are available:
|
|||||||
| `Upload` | Replace the default Upload component within the Edit View. [Upload](../upload/overview) must be enabled. [More details](../custom-components/edit-view#upload). |
|
| `Upload` | Replace the default Upload component within the Edit View. [Upload](../upload/overview) must be enabled. [More details](../custom-components/edit-view#upload). |
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Note:**
|
**Note:** For details on how to build Custom Components, see [Building Custom
|
||||||
For details on how to build Custom Components, see [Building Custom Components](../custom-components/overview#building-custom-components).
|
Components](../custom-components/overview#building-custom-components).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### Pagination
|
### Pagination
|
||||||
@@ -247,8 +253,8 @@ export const Posts: CollectionConfig = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Tip:**
|
**Tip:** If you are adding `listSearchableFields`, make sure you index each of
|
||||||
If you are adding `listSearchableFields`, make sure you index each of these fields so your admin queries can remain performant.
|
these fields so your admin queries can remain performant.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## GraphQL
|
## GraphQL
|
||||||
@@ -258,7 +264,7 @@ You can completely disable GraphQL for this collection by passing `graphQL: fals
|
|||||||
You can also pass an object to the collection's `graphQL` property, which allows you to define the following properties:
|
You can also pass an object to the collection's `graphQL` property, which allows you to define the following properties:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ---------------------- | ----------------------------------------------------------------------------------- |
|
| ------------------ | ----------------------------------------------------------------------------------- |
|
||||||
| `singularName` | Override the "singular" name that will be used in GraphQL schema generation. |
|
| `singularName` | Override the "singular" name that will be used in GraphQL schema generation. |
|
||||||
| `pluralName` | Override the "plural" name that will be used in GraphQL schema generation. |
|
| `pluralName` | Override the "plural" name that will be used in GraphQL schema generation. |
|
||||||
| `disableQueries` | Disable all GraphQL queries that correspond to this collection by passing `true`. |
|
| `disableQueries` | Disable all GraphQL queries that correspond to this collection by passing `true`. |
|
||||||
|
|||||||
@@ -45,8 +45,10 @@ For security and safety reasons, the [Admin Panel](../admin/overview) does **not
|
|||||||
If you are building a [Custom Component](../custom-components/overview) and need to access Environment Variables from the client-side, you can do so by prefixing them with `NEXT_PUBLIC_`.
|
If you are building a [Custom Component](../custom-components/overview) and need to access Environment Variables from the client-side, you can do so by prefixing them with `NEXT_PUBLIC_`.
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Important:**
|
**Important:** Be careful about what variables you provide to your client-side
|
||||||
Be careful about what variables you provide to your client-side code. Analyze every single one to make sure that you're not accidentally leaking sensitive information. Only ever include keys that are safe for the public to read in plain text.
|
code. Analyze every single one to make sure that you're not accidentally
|
||||||
|
leaking sensitive information. Only ever include keys that are safe for the
|
||||||
|
public to read in plain text.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
For example, if you've got the following Environment Variable:
|
For example, if you've got the following Environment Variable:
|
||||||
@@ -66,11 +68,7 @@ const stripeKey = process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY // highlight-li
|
|||||||
const MyClientComponent = () => {
|
const MyClientComponent = () => {
|
||||||
// do something with the key
|
// do something with the key
|
||||||
|
|
||||||
return (
|
return <div>My Client Component</div>
|
||||||
<div>
|
|
||||||
My Client Component
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -95,7 +93,7 @@ export default buildConfig({
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Tip:**
|
**Tip:** Be sure that `dotenv` can find your `.env` file. By default, it will
|
||||||
Be sure that `dotenv` can find your `.env` file. By default, it will look for a file named `.env` in the root of your project. If you need to specify a different file, pass the path into the config options.
|
look for a file named `.env` in the root of your project. If you need to
|
||||||
|
specify a different file, pass the path into the config options.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
|
|||||||
@@ -17,15 +17,16 @@ import { buildConfig } from 'payload'
|
|||||||
|
|
||||||
export default buildConfig({
|
export default buildConfig({
|
||||||
// ...
|
// ...
|
||||||
globals: [ // highlight-line
|
globals: [
|
||||||
|
// highlight-line
|
||||||
// Your Globals go here
|
// Your Globals go here
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Tip:**
|
**Tip:** If you have more than one Global that share the same structure,
|
||||||
If you have more than one Global that share the same structure, consider using a [Collection](./collections) instead.
|
consider using a [Collection](./collections) instead.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Config Options
|
## Config Options
|
||||||
@@ -59,8 +60,10 @@ export const Nav: GlobalConfig = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Reminder:**
|
**Reminder:** For more complex examples, see the
|
||||||
For more complex examples, see the [Templates](https://github.com/payloadcms/payload/tree/main/templates) and [Examples](https://github.com/payloadcms/payload/tree/main/examples) directories in the Payload repository.
|
[Templates](https://github.com/payloadcms/payload/tree/main/templates) and
|
||||||
|
[Examples](https://github.com/payloadcms/payload/tree/main/examples)
|
||||||
|
directories in the Payload repository.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
The following options are available:
|
The following options are available:
|
||||||
@@ -73,17 +76,17 @@ The following options are available:
|
|||||||
| `dbName` | Custom table or collection name for this Global depending on the Database Adapter. Auto-generated from slug if not defined. |
|
| `dbName` | Custom table or collection name for this Global depending on the Database Adapter. Auto-generated from slug if not defined. |
|
||||||
| `description` | Text or React component to display below the Global header to give editors more information. |
|
| `description` | Text or React component to display below the Global header to give editors more information. |
|
||||||
| `endpoints` | Add custom routes to the REST API. [More details](../rest-api/overview#custom-endpoints). |
|
| `endpoints` | Add custom routes to the REST API. [More details](../rest-api/overview#custom-endpoints). |
|
||||||
| `fields` * | Array of field types that will determine the structure and functionality of the data stored within this Global. [More details](../fields/overview). |
|
| `fields` \* | Array of field types that will determine the structure and functionality of the data stored within this Global. [More details](../fields/overview). |
|
||||||
| `graphQL` | Manage GraphQL-related properties related to this global. [More details](#graphql) |
|
| `graphQL` | Manage GraphQL-related properties related to this global. [More details](#graphql) |
|
||||||
| `hooks` | Entry point for Hooks. [More details](../hooks/overview#global-hooks). |
|
| `hooks` | Entry point for Hooks. [More details](../hooks/overview#global-hooks). |
|
||||||
| `label` | Text for the name in the Admin Panel or an object with keys for each language. Auto-generated from slug if not defined. |
|
| `label` | Text for the name in the Admin Panel or an object with keys for each language. Auto-generated from slug if not defined. |
|
||||||
| `lockDocuments` | Enables or disables document locking. By default, document locking is enabled. Set to an object to configure, or set to `false` to disable locking. [More details](../admin/locked-documents). |
|
| `lockDocuments` | Enables or disables document locking. By default, document locking is enabled. Set to an object to configure, or set to `false` to disable locking. [More details](../admin/locked-documents). |
|
||||||
| `slug` * | Unique, URL-friendly string that will act as an identifier for this Global. |
|
| `slug` \* | Unique, URL-friendly string that will act as an identifier for this Global. |
|
||||||
| `typescript` | An object with property `interface` as the text used in schema generation. Auto-generated from slug if not defined. |
|
| `typescript` | An object with property `interface` as the text used in schema generation. Auto-generated from slug if not defined. |
|
||||||
| `versions` | Set to true to enable default options, or configure with object properties. [More details](../versions/overview#global-config). |
|
| `versions` | Set to true to enable default options, or configure with object properties. [More details](../versions/overview#global-config). |
|
||||||
| `forceSelect` | Specify which fields should be selected always, regardless of the `select` query which can be useful that the field exists for access control / hooks |
|
| `forceSelect` | Specify which fields should be selected always, regardless of the `select` query which can be useful that the field exists for access control / hooks |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
### Fields
|
### Fields
|
||||||
|
|
||||||
@@ -108,7 +111,8 @@ import { GlobalConfig } from 'payload'
|
|||||||
|
|
||||||
export const MyGlobal: GlobalConfig = {
|
export const MyGlobal: GlobalConfig = {
|
||||||
// ...
|
// ...
|
||||||
admin: { // highlight-line
|
admin: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -117,7 +121,7 @@ export const MyGlobal: GlobalConfig = {
|
|||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `group` | Text or localization object used to group Collection and Global links in the admin navigation. Set to `false` to hide the link from the navigation while keeping its routes accessible. |
|
| `group` | Text or localization object used to group Collection and Global links in the admin navigation. Set to `false` to hide the link from the navigation while keeping its routes accessible. |
|
||||||
| `hidden` | Set to true or a function, called with the current user, returning true to exclude this Global from navigation and admin routing. |
|
| `hidden` | Set to true or a function, called with the current user, returning true to exclude this Global from navigation and admin routing. |
|
||||||
| `components` | Swap in your own React components to be used within this Global. [More details](#custom-components). |
|
| `components` | Swap in your own React components to be used within this Global. [More details](#custom-components). |
|
||||||
@@ -138,7 +142,8 @@ import type { SanitizedGlobalConfig } from 'payload'
|
|||||||
export const MyGlobal: SanitizedGlobalConfig = {
|
export const MyGlobal: SanitizedGlobalConfig = {
|
||||||
// ...
|
// ...
|
||||||
admin: {
|
admin: {
|
||||||
components: { // highlight-line
|
components: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -150,7 +155,7 @@ The following options are available:
|
|||||||
#### General
|
#### General
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
|
| ---------- | ------------------------------------------------------------------------------------------------------- |
|
||||||
| `elements` | Override or create new elements within the Edit View. [More details](#edit-view-options). |
|
| `elements` | Override or create new elements within the Edit View. [More details](#edit-view-options). |
|
||||||
| `views` | Override or create new views within the Admin Panel. [More details](../custom-components/custom-views). |
|
| `views` | Override or create new views within the Admin Panel. [More details](../custom-components/custom-views). |
|
||||||
|
|
||||||
@@ -163,7 +168,8 @@ export const MyGlobal: SanitizedGlobalConfig = {
|
|||||||
// ...
|
// ...
|
||||||
admin: {
|
admin: {
|
||||||
components: {
|
components: {
|
||||||
elements: { // highlight-line
|
elements: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -174,15 +180,15 @@ export const MyGlobal: SanitizedGlobalConfig = {
|
|||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| `SaveButton` | Replace the default Save Button with a Custom Component. [Drafts](../versions/drafts) must be disabled. [More details](../custom-components/edit-view#save-button). |
|
| `SaveButton` | Replace the default Save Button with a Custom Component. [Drafts](../versions/drafts) must be disabled. [More details](../custom-components/edit-view#save-button). |
|
||||||
| `SaveDraftButton` | Replace the default Save Draft Button with a Custom Component. [Drafts](../versions/drafts) must be enabled and autosave must be disabled. [More details](../custom-components/edit-view#save-draft-button). |
|
| `SaveDraftButton` | Replace the default Save Draft Button with a Custom Component. [Drafts](../versions/drafts) must be enabled and autosave must be disabled. [More details](../custom-components/edit-view#save-draft-button). |
|
||||||
| `PublishButton` | Replace the default Publish Button with a Custom Component. [Drafts](../versions/drafts) must be enabled. [More details](../custom-components/edit-view#publish-button). |
|
| `PublishButton` | Replace the default Publish Button with a Custom Component. [Drafts](../versions/drafts) must be enabled. [More details](../custom-components/edit-view#publish-button). |
|
||||||
| `PreviewButton` | Replace the default Preview Button with a Custom Component. [Preview](../admin/preview) must be enabled. [More details](../custom-components/edit-view#preview-button). |
|
| `PreviewButton` | Replace the default Preview Button with a Custom Component. [Preview](../admin/preview) must be enabled. [More details](../custom-components/edit-view#preview-button). |
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Note:**
|
**Note:** For details on how to build Custom Components, see [Building Custom
|
||||||
For details on how to build Custom Components, see [Building Custom Components](../custom-components/overview#building-custom-components).
|
Components](../custom-components/overview#building-custom-components).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## GraphQL
|
## GraphQL
|
||||||
@@ -192,7 +198,7 @@ You can completely disable GraphQL for this global by passing `graphQL: false` t
|
|||||||
You can also pass an object to the global's `graphQL` property, which allows you to define the following properties:
|
You can also pass an object to the global's `graphQL` property, which allows you to define the following properties:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ---------------------- | ----------------------------------------------------------------------------------- |
|
| ------------------ | ------------------------------------------------------------------------------- |
|
||||||
| `name` | Override the name that will be used in GraphQL schema generation. |
|
| `name` | Override the name that will be used in GraphQL schema generation. |
|
||||||
| `disableQueries` | Disable all GraphQL queries that correspond to this global by passing `true`. |
|
| `disableQueries` | Disable all GraphQL queries that correspond to this global by passing `true`. |
|
||||||
| `disableMutations` | Disable all GraphQL mutations that correspond to this global by passing `true`. |
|
| `disableMutations` | Disable all GraphQL mutations that correspond to this global by passing `true`. |
|
||||||
|
|||||||
@@ -23,15 +23,17 @@ import { buildConfig } from 'payload'
|
|||||||
|
|
||||||
export default buildConfig({
|
export default buildConfig({
|
||||||
// ...
|
// ...
|
||||||
i18n: { // highlight-line
|
i18n: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Note:**
|
**Note:** If there is a language that Payload does not yet support, we accept
|
||||||
If there is a language that Payload does not yet support, we accept [code contributions](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md).
|
[code
|
||||||
|
contributions](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Config Options
|
## Config Options
|
||||||
@@ -46,7 +48,7 @@ export default buildConfig({
|
|||||||
// highlight-start
|
// highlight-start
|
||||||
i18n: {
|
i18n: {
|
||||||
fallbackLanguage: 'en', // default
|
fallbackLanguage: 'en', // default
|
||||||
}
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
@@ -54,7 +56,7 @@ export default buildConfig({
|
|||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| --------------------- | --------------------------------|
|
| -------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
||||||
| `fallbackLanguage` | The language to fall back to if the user's preferred language is not supported. Default is `'en'`. |
|
| `fallbackLanguage` | The language to fall back to if the user's preferred language is not supported. Default is `'en'`. |
|
||||||
| `translations` | An object containing the translations. The keys are the language codes and the values are the translations. |
|
| `translations` | An object containing the translations. The keys are the language codes and the values are the translations. |
|
||||||
| `supportedLanguages` | An object containing the supported languages. The keys are the language codes and the values are the translations. |
|
| `supportedLanguages` | An object containing the supported languages. The keys are the language codes and the values are the translations. |
|
||||||
@@ -81,8 +83,8 @@ export default buildConfig({
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Tip:**
|
**Tip:** It's best to only support the languages that you need so that the
|
||||||
It's best to only support the languages that you need so that the bundled JavaScript is kept to a minimum for your project.
|
bundled JavaScript is kept to a minimum for your project.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### Custom Translations
|
### Custom Translations
|
||||||
@@ -163,7 +165,7 @@ export const Articles: CollectionConfig = {
|
|||||||
placeholder: {
|
placeholder: {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
en: 'Enter title',
|
en: 'Enter title',
|
||||||
es: 'Introduce el título'
|
es: 'Introduce el título',
|
||||||
// highlight-end
|
// highlight-end
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -203,12 +205,14 @@ export const customTranslations = {
|
|||||||
},
|
},
|
||||||
fields: {
|
fields: {
|
||||||
addLabel: 'Add!',
|
addLabel: 'Add!',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CustomTranslationsObject = typeof customTranslations.en & typeof enTranslations
|
export type CustomTranslationsObject = typeof customTranslations.en &
|
||||||
export type CustomTranslationsKeys = NestedKeysStripped<CustomTranslationsObject>
|
typeof enTranslations
|
||||||
|
export type CustomTranslationsKeys =
|
||||||
|
NestedKeysStripped<CustomTranslationsObject>
|
||||||
```
|
```
|
||||||
|
|
||||||
Import the shared translations object into our Payload config so they are available for use:
|
Import the shared translations object into our Payload config so they are available for use:
|
||||||
@@ -238,10 +242,16 @@ Import the shared translation types to use in your [Custom Component](../custom-
|
|||||||
import type React from 'react'
|
import type React from 'react'
|
||||||
import { useTranslation } from '@payloadcms/ui'
|
import { useTranslation } from '@payloadcms/ui'
|
||||||
|
|
||||||
import type { CustomTranslationsObject, CustomTranslationsKeys } from '../custom-translations'
|
import type {
|
||||||
|
CustomTranslationsObject,
|
||||||
|
CustomTranslationsKeys,
|
||||||
|
} from '../custom-translations'
|
||||||
|
|
||||||
export const MyComponent: React.FC = () => {
|
export const MyComponent: React.FC = () => {
|
||||||
const { i18n, t } = useTranslation<CustomTranslationsObject, CustomTranslationsKeys>() // These generics merge your custom translations with the default client translations
|
const { i18n, t } = useTranslation<
|
||||||
|
CustomTranslationsObject,
|
||||||
|
CustomTranslationsKeys
|
||||||
|
>() // These generics merge your custom translations with the default client translations
|
||||||
|
|
||||||
return t('general:myCustomKey')
|
return t('general:myCustomKey')
|
||||||
}
|
}
|
||||||
@@ -252,7 +262,10 @@ Additionally, Payload exposes the `t` function in various places, for example in
|
|||||||
```ts
|
```ts
|
||||||
// <rootDir>/fields/myField.ts
|
// <rootDir>/fields/myField.ts
|
||||||
|
|
||||||
import type { DefaultTranslationKeys, TFunction } from '@payloadcms/translations'
|
import type {
|
||||||
|
DefaultTranslationKeys,
|
||||||
|
TFunction,
|
||||||
|
} from '@payloadcms/translations'
|
||||||
import type { Field } from 'payload'
|
import type { Field } from 'payload'
|
||||||
|
|
||||||
import { CustomTranslationsKeys } from '../custom-translations'
|
import { CustomTranslationsKeys } from '../custom-translations'
|
||||||
@@ -260,9 +273,7 @@ import { CustomTranslationsKeys } from '../custom-translations'
|
|||||||
const field: Field = {
|
const field: Field = {
|
||||||
name: 'myField',
|
name: 'myField',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
label: (
|
label: ({ t: defaultT }) => {
|
||||||
{ t: defaultT }
|
|
||||||
) => {
|
|
||||||
const t = defaultT as TFunction<CustomTranslationsKeys>
|
const t = defaultT as TFunction<CustomTranslationsKeys>
|
||||||
return t('fields:addLabel')
|
return t('fields:addLabel')
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ import { buildConfig } from 'payload'
|
|||||||
|
|
||||||
export default buildConfig({
|
export default buildConfig({
|
||||||
// ...
|
// ...
|
||||||
localization: { // highlight-line
|
localization: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -71,14 +72,14 @@ export default buildConfig({
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Tip:**
|
**Tip:** Localization works very well alongside
|
||||||
Localization works very well alongside [I18n](/docs/configuration/i18n).
|
[I18n](/docs/configuration/i18n).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
|------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`locales`** | Array of all the languages that you would like to support. [More details](#locales) |
|
| **`locales`** | Array of all the languages that you would like to support. [More details](#locales) |
|
||||||
| **`defaultLocale`** | Required string that matches one of the locale codes from the array provided. By default, if no locale is specified, documents will be returned in this locale. |
|
| **`defaultLocale`** | Required string that matches one of the locale codes from the array provided. By default, if no locale is specified, documents will be returned in this locale. |
|
||||||
| **`fallback`** | Boolean enabling "fallback" locale functionality. If a document is requested in a locale, but a field does not have a localized value corresponding to the requested locale, then if this property is enabled, the document will automatically fall back to the fallback locale value. If this property is not enabled, the value will not be populated unless a fallback is explicitly provided in the request. True by default. |
|
| **`fallback`** | Boolean enabling "fallback" locale functionality. If a document is requested in a locale, but a field does not have a localized value corresponding to the requested locale, then if this property is enabled, the document will automatically fall back to the fallback locale value. If this property is not enabled, the value will not be populated unless a fallback is explicitly provided in the request. True by default. |
|
||||||
@@ -94,14 +95,15 @@ The locale codes do not need to be in any specific format. It's up to you to def
|
|||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| **`code`** * | Unique code to identify the language throughout the APIs for `locale` and `fallbackLocale` |
|
| **`code`** \* | Unique code to identify the language throughout the APIs for `locale` and `fallbackLocale` |
|
||||||
| **`label`** | A string to use for the selector when choosing a language, or an object keyed on the i18n keys for different languages in use. |
|
| **`label`** | A string to use for the selector when choosing a language, or an object keyed on the i18n keys for different languages in use. |
|
||||||
| **`rtl`** | A boolean that when true will make the admin UI display in Right-To-Left. |
|
| **`rtl`** | A boolean that when true will make the admin UI display in Right-To-Left. |
|
||||||
| **`fallbackLocale`** | The code for this language to fallback to when properties of a document are not present. |
|
| **`fallbackLocale`** | The code for this language to fallback to when properties of a document are not present. |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
#### Filter Available Options
|
#### Filter Available Options
|
||||||
|
|
||||||
In some projects you may want to filter the available locales shown in the admin UI selector. You can do this by providing a `filterAvailableLocales` function in your Payload Config. This is called on the server side and is passed the array of locales. This means that you can determine what locales are visible in the localizer selection menu at the top of the admin panel. You could do this per user, or implement a function that scopes these to tenants and more. Here is an example using request headers in a multi-tenant application:
|
In some projects you may want to filter the available locales shown in the admin UI selector. You can do this by providing a `filterAvailableLocales` function in your Payload Config. This is called on the server side and is passed the array of locales. This means that you can determine what locales are visible in the localizer selection menu at the top of the admin panel. You could do this per user, or implement a function that scopes these to tenants and more. Here is an example using request headers in a multi-tenant application:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
@@ -129,7 +131,6 @@ localization: {
|
|||||||
|
|
||||||
Since the filtering happens at the root level of the application and its result is not calculated every time you navigate to a new page, you may want to call `router.refresh` in a custom component that watches when values that affect the result change. In the example above, you would want to do this when `supportedLocales` changes on the tenant document.
|
Since the filtering happens at the root level of the application and its result is not calculated every time you navigate to a new page, you may want to call `router.refresh` in a custom component that watches when values that affect the result change. In the example above, you would want to do this when `supportedLocales` changes on the tenant document.
|
||||||
|
|
||||||
|
|
||||||
## Field Localization
|
## Field Localization
|
||||||
|
|
||||||
Payload Localization works on a **field** level—not a document level. In addition to configuring the base Payload Config to support Localization, you need to specify each field that you would like to localize.
|
Payload Localization works on a **field** level—not a document level. In addition to configuring the base Payload Config to support Localization, you need to specify each field that you would like to localize.
|
||||||
@@ -151,18 +152,18 @@ With the above configuration, the `title` field will now be saved in the databas
|
|||||||
All field types with a `name` property support the `localized` property—even the more complex field types like `array`s and `block`s.
|
All field types with a `name` property support the `localized` property—even the more complex field types like `array`s and `block`s.
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
**Note:**
|
**Note:** Enabling Localization for field types that support nested fields
|
||||||
Enabling Localization for field types that support nested fields will automatically create
|
will automatically create localized "sets" of all fields contained within the
|
||||||
localized "sets" of all fields contained within the field. For example, if you have a page layout
|
field. For example, if you have a page layout using a blocks field type, you
|
||||||
using a blocks field type, you have the choice of either localizing the full layout, by enabling
|
have the choice of either localizing the full layout, by enabling Localization
|
||||||
Localization on the top-level blocks field, or only certain fields within the layout.
|
on the top-level blocks field, or only certain fields within the layout.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Important:**
|
**Important:** When converting an existing field to or from `localized: true`
|
||||||
When converting an existing field to or from `localized: true` the data structure in the document
|
the data structure in the document will change for this field and so existing
|
||||||
will change for this field and so existing data for this field will be lost. Before changing the
|
data for this field will be lost. Before changing the Localization setting on
|
||||||
Localization setting on fields with existing data, you may need to consider a field migration
|
fields with existing data, you may need to consider a field migration
|
||||||
strategy.
|
strategy.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
@@ -213,9 +214,10 @@ query {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner>
|
<Banner>
|
||||||
In GraphQL, specifying the locale at the top level of a query will automatically apply it
|
In GraphQL, specifying the locale at the top level of a query will
|
||||||
throughout all nested relationship fields. You can override this behavior by re-specifying locale
|
automatically apply it throughout all nested relationship fields. You can
|
||||||
arguments in nested related document queries.
|
override this behavior by re-specifying locale arguments in nested related
|
||||||
|
document queries.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
#### Local API
|
#### Local API
|
||||||
@@ -235,8 +237,8 @@ const posts = await payload.find({
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Tip:**
|
**Tip:** The REST and Local APIs can return all Localization data in one
|
||||||
The REST and Local APIs can return all Localization data in one request by passing 'all' or '*' as
|
request by passing 'all' or '*' as the **locale** parameter. The response will
|
||||||
the **locale** parameter. The response will be structured so that field values come
|
be structured so that field values come back as the full objects keyed for
|
||||||
back as the full objects keyed for each locale instead of the single, translated value.
|
each locale instead of the single, translated value.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ export default buildConfig({
|
|||||||
The Payload Config is strongly typed and ties directly into Payload's TypeScript codebase. This means your IDE (such as VSCode) will provide helpful information like type-ahead suggestions while you write your config.
|
The Payload Config is strongly typed and ties directly into Payload's TypeScript codebase. This means your IDE (such as VSCode) will provide helpful information like type-ahead suggestions while you write your config.
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Tip:**
|
**Tip:** The location of your Payload Config can be customized. [More
|
||||||
The location of your Payload Config can be customized. [More details](#customizing-the-config-location).
|
details](#customizing-the-config-location).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Config Options
|
## Config Options
|
||||||
@@ -48,17 +48,19 @@ export default buildConfig({
|
|||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: 'title',
|
name: 'title',
|
||||||
type: 'text'
|
type: 'text',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Note:**
|
**Note:** For more complex examples, see the
|
||||||
For more complex examples, see the [Templates](https://github.com/payloadcms/payload/tree/main/templates) and [Examples](https://github.com/payloadcms/payload/tree/main/examples) directories in the Payload repository.
|
[Templates](https://github.com/payloadcms/payload/tree/main/templates) and
|
||||||
|
[Examples](https://github.com/payloadcms/payload/tree/main/examples)
|
||||||
|
directories in the Payload repository.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
The following options are available:
|
The following options are available:
|
||||||
@@ -68,7 +70,7 @@ The following options are available:
|
|||||||
| **`admin`** | The configuration options for the Admin Panel, including Custom Components, Live Preview, etc. [More details](../admin/overview#admin-options). |
|
| **`admin`** | The configuration options for the Admin Panel, including Custom Components, Live Preview, etc. [More details](../admin/overview#admin-options). |
|
||||||
| **`bin`** | Register custom bin scripts for Payload to execute. [More Details](#custom-bin-scripts). |
|
| **`bin`** | Register custom bin scripts for Payload to execute. [More Details](#custom-bin-scripts). |
|
||||||
| **`editor`** | The Rich Text Editor which will be used by `richText` fields. [More details](../rich-text/overview). |
|
| **`editor`** | The Rich Text Editor which will be used by `richText` fields. [More details](../rich-text/overview). |
|
||||||
| **`db`** * | The Database Adapter which will be used by Payload. [More details](../database/overview). |
|
| **`db`** \* | The Database Adapter which will be used by Payload. [More details](../database/overview). |
|
||||||
| **`serverURL`** | A string used to define the absolute URL of your app. This includes the protocol, for example `https://example.com`. No paths allowed, only protocol, domain and (optionally) port. |
|
| **`serverURL`** | A string used to define the absolute URL of your app. This includes the protocol, for example `https://example.com`. No paths allowed, only protocol, domain and (optionally) port. |
|
||||||
| **`collections`** | An array of Collections for Payload to manage. [More details](./collections). |
|
| **`collections`** | An array of Collections for Payload to manage. [More details](./collections). |
|
||||||
| **`compatibility`** | Compatibility flags for earlier versions of Payload. [More details](#compatibility-flags). |
|
| **`compatibility`** | Compatibility flags for earlier versions of Payload. [More details](#compatibility-flags). |
|
||||||
@@ -95,15 +97,15 @@ The following options are available:
|
|||||||
| **`endpoints`** | An array of Custom Endpoints added to the Payload router. [More details](../rest-api/overview#custom-endpoints). |
|
| **`endpoints`** | An array of Custom Endpoints added to the Payload router. [More details](../rest-api/overview#custom-endpoints). |
|
||||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins). |
|
| **`custom`** | Extension point for adding custom data (e.g. for plugins). |
|
||||||
| **`i18n`** | Internationalization configuration. Pass all i18n languages you'd like the admin UI to support. Defaults to English-only. [More details](./i18n). |
|
| **`i18n`** | Internationalization configuration. Pass all i18n languages you'd like the admin UI to support. Defaults to English-only. [More details](./i18n). |
|
||||||
| **`secret`** * | A secure, unguessable string that Payload will use for any encryption workflows - for example, password salt / hashing. |
|
| **`secret`** \* | A secure, unguessable string that Payload will use for any encryption workflows - for example, password salt / hashing. |
|
||||||
| **`sharp`** | If you would like Payload to offer cropping, focal point selection, and automatic media resizing, install and pass the Sharp module to the config here. |
|
| **`sharp`** | If you would like Payload to offer cropping, focal point selection, and automatic media resizing, install and pass the Sharp module to the config here. |
|
||||||
| **`typescript`** | Configure TypeScript settings here. [More details](#typescript). |
|
| **`typescript`** | Configure TypeScript settings here. [More details](#typescript). |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Note:**
|
**Note:** Some properties are removed from the client-side bundle. [More
|
||||||
Some properties are removed from the client-side bundle. [More details](../custom-components/overview#accessing-the-payload-config).
|
details](../custom-components/overview#accessing-the-payload-config).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### Typescript Config
|
### Typescript Config
|
||||||
@@ -117,16 +119,17 @@ import { buildConfig } from 'payload'
|
|||||||
|
|
||||||
export default buildConfig({
|
export default buildConfig({
|
||||||
// ...
|
// ...
|
||||||
typescript: { // highlight-line
|
typescript: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| --------------- | --------------------- |
|
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`autoGenerate`** | By default, Payload will auto-generate TypeScript interfaces for all collections and globals that your config defines. Opt out by setting `typescript.autoGenerate: false`. [More details](../typescript/overview). |
|
| **`autoGenerate`** | By default, Payload will auto-generate TypeScript interfaces for all collections and globals that your config defines. Opt out by setting `typescript.autoGenerate: false`. [More details](../typescript/overview). |
|
||||||
| **`declare`** | By default, Payload adds a `declare` block to your generated types, which makes sure that Payload uses your generated types for all Local API methods. Opt out by setting `typescript.declare: false`. |
|
| **`declare`** | By default, Payload adds a `declare` block to your generated types, which makes sure that Payload uses your generated types for all Local API methods. Opt out by setting `typescript.declare: false`. |
|
||||||
| **`outputFile`** | Control the output path and filename of Payload's auto-generated types by defining the `typescript.outputFile` property to a full, absolute path. |
|
| **`outputFile`** | Control the output path and filename of Payload's auto-generated types by defining the `typescript.outputFile` property to a full, absolute path. |
|
||||||
@@ -136,14 +139,16 @@ The following options are available:
|
|||||||
For Payload command-line scripts, we need to be able to locate your Payload Config. We'll check a variety of locations for the presence of `payload.config.ts` by default, including:
|
For Payload command-line scripts, we need to be able to locate your Payload Config. We'll check a variety of locations for the presence of `payload.config.ts` by default, including:
|
||||||
|
|
||||||
1. The root current working directory
|
1. The root current working directory
|
||||||
1. The `compilerOptions` in your `tsconfig`*
|
1. The `compilerOptions` in your `tsconfig`\*
|
||||||
1. The `dist` directory*
|
1. The `dist` directory\*
|
||||||
|
|
||||||
_* Config location detection is different between development and production environments. See below for more details._
|
_\* Config location detection is different between development and production environments. See below for more details._
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Important:**
|
**Important:** Ensure your `tsconfig.json` is properly configured for Payload
|
||||||
Ensure your `tsconfig.json` is properly configured for Payload to auto-detect your config location. If if does not exist, or does not specify the proper `compilerOptions`, Payload will default to the current working directory.
|
to auto-detect your config location. If if does not exist, or does not specify
|
||||||
|
the proper `compilerOptions`, Payload will default to the current working
|
||||||
|
directory.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
**Development Mode**
|
**Development Mode**
|
||||||
@@ -194,8 +199,8 @@ To use a custom config location, set the `PAYLOAD_CONFIG_PATH` environment varia
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
**Tip:**
|
**Tip:** `PAYLOAD_CONFIG_PATH` can be either an absolute path, or path
|
||||||
`PAYLOAD_CONFIG_PATH` can be either an absolute path, or path relative to your current working directory.
|
relative to your current working directory.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Telemetry
|
## Telemetry
|
||||||
@@ -209,7 +214,7 @@ For more information about what we track, take a look at our [privacy policy](/p
|
|||||||
Cross-origin resource sharing (CORS) can be configured with either a whitelist array of URLS to allow CORS requests from, a wildcard string (`*`) to accept incoming requests from any domain, or a object with the following properties:
|
Cross-origin resource sharing (CORS) can be configured with either a whitelist array of URLS to allow CORS requests from, a wildcard string (`*`) to accept incoming requests from any domain, or a object with the following properties:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| --------- | --------------------------------------------------------------------------------------------------------------------------------------- |
|
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`origins`** | Either a whitelist array of URLS to allow CORS requests from, or a wildcard string (`'*'`) to accept incoming requests from any domain. |
|
| **`origins`** | Either a whitelist array of URLS to allow CORS requests from, or a wildcard string (`'*'`) to accept incoming requests from any domain. |
|
||||||
| **`headers`** | A list of allowed headers that will be appended in `Access-Control-Allow-Headers`. |
|
| **`headers`** | A list of allowed headers that will be appended in `Access-Control-Allow-Headers`. |
|
||||||
|
|
||||||
@@ -220,7 +225,7 @@ import { buildConfig } from 'payload'
|
|||||||
|
|
||||||
export default buildConfig({
|
export default buildConfig({
|
||||||
// ...
|
// ...
|
||||||
cors: '*' // highlight-line
|
cors: '*', // highlight-line
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -266,13 +271,11 @@ Payload localization works on a field-by-field basis. As you can nest fields wit
|
|||||||
|
|
||||||
By default, Payload will remove the `localized: true` property from sub-fields if a parent field is localized. Set this compatibility flag to `true` only if you have an existing Payload MongoDB database from pre-3.0, and you have nested localized fields that you would like to maintain without migrating.
|
By default, Payload will remove the `localized: true` property from sub-fields if a parent field is localized. Set this compatibility flag to `true` only if you have an existing Payload MongoDB database from pre-3.0, and you have nested localized fields that you would like to maintain without migrating.
|
||||||
|
|
||||||
|
|
||||||
## Custom bin scripts
|
## Custom bin scripts
|
||||||
|
|
||||||
Using the `bin` configuration property, you can inject your own scripts to `npx payload`.
|
Using the `bin` configuration property, you can inject your own scripts to `npx payload`.
|
||||||
Example for `pnpm payload seed`:
|
Example for `pnpm payload seed`:
|
||||||
|
|
||||||
|
|
||||||
Step 1: create `seed.ts` file in the same folder with `payload.config.ts` with:
|
Step 1: create `seed.ts` file in the same folder with `payload.config.ts` with:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
@@ -283,13 +286,17 @@ import payload from 'payload'
|
|||||||
// Script must define a "script" function export that accepts the sanitized config
|
// Script must define a "script" function export that accepts the sanitized config
|
||||||
export const script = async (config: SanitizedConfig) => {
|
export const script = async (config: SanitizedConfig) => {
|
||||||
await payload.init({ config })
|
await payload.init({ config })
|
||||||
await payload.create({ collection: 'pages', data: { title: 'my title' } })
|
await payload.create({
|
||||||
|
collection: 'pages',
|
||||||
|
data: { title: 'my title' },
|
||||||
|
})
|
||||||
payload.logger.info('Succesffully seeded!')
|
payload.logger.info('Succesffully seeded!')
|
||||||
process.exit(0)
|
process.exit(0)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Step 2: add the `seed` script to `bin`:
|
Step 2: add the `seed` script to `bin`:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
export default buildConfig({
|
export default buildConfig({
|
||||||
bin: [
|
bin: [
|
||||||
@@ -302,6 +309,7 @@ export default buildConfig({
|
|||||||
```
|
```
|
||||||
|
|
||||||
Now you can run the command using:
|
Now you can run the command using:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
pnpm payload seed
|
pnpm payload seed
|
||||||
```
|
```
|
||||||
@@ -32,11 +32,7 @@ import React, { createContext, use } from 'react'
|
|||||||
const MyCustomContext = React.createContext(myCustomValue)
|
const MyCustomContext = React.createContext(myCustomValue)
|
||||||
|
|
||||||
export function MyProvider({ children }: { children: React.ReactNode }) {
|
export function MyProvider({ children }: { children: React.ReactNode }) {
|
||||||
return (
|
return <MyCustomContext value={myCustomValue}>{children}</MyCustomContext>
|
||||||
<MyCustomContext value={myCustomValue}>
|
|
||||||
{children}
|
|
||||||
</MyCustomContext>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useMyCustomContext = () => use(MyCustomContext)
|
export const useMyCustomContext = () => use(MyCustomContext)
|
||||||
@@ -45,5 +41,8 @@ export const useMyCustomContext = () => use(MyCustomContext)
|
|||||||
_For details on how to build Custom Components, see [Building Custom Components](./overview#building-custom-components)._
|
_For details on how to build Custom Components, see [Building Custom Components](./overview#building-custom-components)._
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Reminder:** React Context exists only within Client Components. This means they must include the `use client` directive at the top of their files and cannot contain server-only code. To use a Server Component here, simply _wrap_ your Client Component with it.
|
**Reminder:** React Context exists only within Client Components. This means
|
||||||
|
they must include the `use client` directive at the top of their files and
|
||||||
|
cannot contain server-only code. To use a Server Component here, simply _wrap_
|
||||||
|
your Client Component with it.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|||||||
@@ -38,26 +38,26 @@ const config = buildConfig({
|
|||||||
// highlight-start
|
// highlight-start
|
||||||
dashboard: {
|
dashboard: {
|
||||||
Component: '/path/to/MyCustomDashboard',
|
Component: '/path/to/MyCustomDashboard',
|
||||||
}
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
For more granular control, pass a configuration object instead. Payload exposes the following properties for each view:
|
For more granular control, pass a configuration object instead. Payload exposes the following properties for each view:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `Component` * | Pass in the component path that should be rendered when a user navigates to this route. |
|
| `Component` \* | Pass in the component path that should be rendered when a user navigates to this route. |
|
||||||
| `path` * | Any valid URL path or array of paths that [`path-to-regexp`](https://www.npmjs.com/package/path-to-regex) understands. |
|
| `path` \* | Any valid URL path or array of paths that [`path-to-regexp`](https://www.npmjs.com/package/path-to-regex) understands. |
|
||||||
| `exact` | Boolean. When true, will only match if the path matches the `usePathname()` exactly. |
|
| `exact` | Boolean. When true, will only match if the path matches the `usePathname()` exactly. |
|
||||||
| `strict` | When true, a path that has a trailing slash will only match a `location.pathname` with a trailing slash. This has no effect when there are additional URL segments in the pathname. |
|
| `strict` | When true, a path that has a trailing slash will only match a `location.pathname` with a trailing slash. This has no effect when there are additional URL segments in the pathname. |
|
||||||
| `sensitive` | When true, will match if the path is case sensitive.|
|
| `sensitive` | When true, will match if the path is case sensitive. |
|
||||||
| `meta` | Page metadata overrides to apply to this view within the Admin Panel. [More details](./metadata). |
|
| `meta` | Page metadata overrides to apply to this view within the Admin Panel. [More details](./metadata). |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
### Adding New Views
|
### Adding New Views
|
||||||
|
|
||||||
@@ -86,14 +86,12 @@ const config = buildConfig({
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Note:**
|
**Note:** Routes are cascading, so unless explicitly given the `exact`
|
||||||
Routes are cascading, so unless explicitly given the `exact` property, they will
|
property, they will match on URLs that simply _start_ with the route's path.
|
||||||
match on URLs that simply _start_ with the route's path. This is helpful when creating catch-all
|
This is helpful when creating catch-all routes in your application.
|
||||||
routes in your application. Alternatively, define your nested route _before_ your parent
|
Alternatively, define your nested route _before_ your parent route.
|
||||||
route.
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
|
|
||||||
## Building Custom Views
|
## Building Custom Views
|
||||||
|
|
||||||
Custom Views are simply [Custom Components](./overview) rendered at the page-level. Custom Views can either [replace existing views](#replacing-views) or [add entirely new ones](#adding-new-views). The process is generally the same regardless of the type of view you are customizing.
|
Custom Views are simply [Custom Components](./overview) rendered at the page-level. Custom Views can either [replace existing views](#replacing-views) or [add entirely new ones](#adding-new-views). The process is generally the same regardless of the type of view you are customizing.
|
||||||
@@ -110,8 +108,8 @@ export const MyCollectionConfig: CollectionConfig = {
|
|||||||
views: {
|
views: {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
edit: {
|
edit: {
|
||||||
Component: '/path/to/MyCustomView' // highlight-line
|
Component: '/path/to/MyCustomView', // highlight-line
|
||||||
}
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -124,7 +122,7 @@ export const MyCollectionConfig: CollectionConfig = {
|
|||||||
Your Custom Views will be provided with the following props:
|
Your Custom Views will be provided with the following props:
|
||||||
|
|
||||||
| Prop | Description |
|
| Prop | Description |
|
||||||
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `initPageResult` | An object containing `req`, `payload`, `permissions`, etc. |
|
| `initPageResult` | An object containing `req`, `payload`, `permissions`, etc. |
|
||||||
| `clientConfig` | The Client Config object. [More details](./overview#accessing-the-payload-config). |
|
| `clientConfig` | The Client Config object. [More details](./overview#accessing-the-payload-config). |
|
||||||
| `importMap` | The import map object. |
|
| `importMap` | The import map object. |
|
||||||
@@ -135,8 +133,9 @@ Your Custom Views will be provided with the following props:
|
|||||||
| `payload` | The [Payload](../local-api/overview) class. |
|
| `payload` | The [Payload](../local-api/overview) class. |
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Note:**
|
**Note:** Some views may receive additional props, such as [Collection
|
||||||
Some views may receive additional props, such as [Collection Views](#collection-views) and [Global Views](#global-views). See the relevant section for more details.
|
Views](#collection-views) and [Global Views](#global-views). See the relevant
|
||||||
|
section for more details.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
Here is an example of a Custom View component:
|
Here is an example of a Custom View component:
|
||||||
@@ -158,8 +157,8 @@ export function MyCustomView(props: AdminViewServerProps) {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Tip:**
|
**Tip:** For consistent layout and navigation, you may want to wrap your
|
||||||
For consistent layout and navigation, you may want to wrap your Custom View with one of the built-in [Template](./overview#templates).
|
Custom View with one of the built-in [Template](./overview#templates).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### View Templates
|
### View Templates
|
||||||
@@ -212,13 +211,9 @@ import type { AdminViewServerProps } from 'payload'
|
|||||||
import { Gutter } from '@payloadcms/ui'
|
import { Gutter } from '@payloadcms/ui'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
export function MyCustomView({
|
export function MyCustomView({ initPageResult }: AdminViewServerProps) {
|
||||||
initPageResult
|
|
||||||
}: AdminViewServerProps) {
|
|
||||||
const {
|
const {
|
||||||
req: {
|
req: { user },
|
||||||
user
|
|
||||||
}
|
|
||||||
} = initPageResult
|
} = initPageResult
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
@@ -251,7 +246,7 @@ const config = buildConfig({
|
|||||||
// highlight-start
|
// highlight-start
|
||||||
dashboard: {
|
dashboard: {
|
||||||
Component: '/path/to/Dashboard',
|
Component: '/path/to/Dashboard',
|
||||||
}
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
// Other options include:
|
// Other options include:
|
||||||
// - account
|
// - account
|
||||||
@@ -268,7 +263,7 @@ _For details on how to build Custom Views, including all available props, see [B
|
|||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| --------------- | ----------------------------------------------------------------------------- |
|
| ----------- | ----------------------------------------------------------------------------------------------- |
|
||||||
| `account` | The Account view is used to show the currently logged in user's Account page. |
|
| `account` | The Account view is used to show the currently logged in user's Account page. |
|
||||||
| `dashboard` | The main landing page of the Admin Panel. |
|
| `dashboard` | The main landing page of the Admin Panel. |
|
||||||
| `[key]` | Any other key can be used to add a completely new Root View. [More details](#adding-new-views). |
|
| `[key]` | Any other key can be used to add a completely new Root View. [More details](#adding-new-views). |
|
||||||
@@ -291,8 +286,8 @@ export const MyCollectionConfig: CollectionConfig = {
|
|||||||
edit: {
|
edit: {
|
||||||
default: {
|
default: {
|
||||||
Component: '/path/to/MyCustomCollectionView',
|
Component: '/path/to/MyCustomCollectionView',
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
// Other options include:
|
// Other options include:
|
||||||
// - list
|
// - list
|
||||||
@@ -305,14 +300,15 @@ export const MyCollectionConfig: CollectionConfig = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Reminder:**
|
**Reminder:** The `edit` key is comprised of various nested views, known as
|
||||||
The `edit` key is comprised of various nested views, known as Document Views, that relate to the same Collection Document. [More details](./document-views).
|
Document Views, that relate to the same Collection Document. [More
|
||||||
|
details](./document-views).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `edit` | The Edit View corresponds to a single Document for any given Collection and consists of various nested views. [More details](./document-views). |
|
| `edit` | The Edit View corresponds to a single Document for any given Collection and consists of various nested views. [More details](./document-views). |
|
||||||
| `list` | The List View is used to show a list of Documents for any given Collection. [More details](#list-view). |
|
| `list` | The List View is used to show a list of Documents for any given Collection. [More details](#list-view). |
|
||||||
| `[key]` | Any other key can be used to add a completely new Collection View. [More details](#adding-new-views). |
|
| `[key]` | Any other key can be used to add a completely new Collection View. [More details](#adding-new-views). |
|
||||||
@@ -337,8 +333,8 @@ export const MyGlobalConfig: SanitizedGlobalConfig = {
|
|||||||
edit: {
|
edit: {
|
||||||
default: {
|
default: {
|
||||||
Component: '/path/to/MyCustomGlobalView',
|
Component: '/path/to/MyCustomGlobalView',
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
// Other options include:
|
// Other options include:
|
||||||
// - [key: string]
|
// - [key: string]
|
||||||
@@ -350,14 +346,15 @@ export const MyGlobalConfig: SanitizedGlobalConfig = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Reminder:**
|
**Reminder:** The `edit` key is comprised of various nested views, known as
|
||||||
The `edit` key is comprised of various nested views, known as Document Views, that relate to the same Global Document. [More details](./document-views).
|
Document Views, that relate to the same Global Document. [More
|
||||||
|
details](./document-views).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
|
| -------- | --------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `edit` | The Edit View represents a single Document for any given Global and consists of various nested views. [More details](./document-views). |
|
| `edit` | The Edit View represents a single Document for any given Global and consists of various nested views. [More details](./document-views). |
|
||||||
| `[key]` | Any other key can be used to add a completely new Global View. [More details](#adding-new-views). |
|
| `[key]` | Any other key can be used to add a completely new Global View. [More details](#adding-new-views). |
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export const MyCollectionOrGlobalConfig: CollectionConfig = {
|
|||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `root` | The Root View overrides all other nested views and routes. No document controls or tabs are rendered when this key is set. [More details](#document-root). |
|
| `root` | The Root View overrides all other nested views and routes. No document controls or tabs are rendered when this key is set. [More details](#document-root). |
|
||||||
| `default` | The Default View is the primary view in which your document is edited. It is rendered within the "Edit" tab. [More details](./edit-view). |
|
| `default` | The Default View is the primary view in which your document is edited. It is rendered within the "Edit" tab. [More details](./edit-view). |
|
||||||
| `versions` | The Versions View is used to navigate the version history of a single document. It is rendered within the "Versions" tab. [More details](../versions/overview). |
|
| `versions` | The Versions View is used to navigate the version history of a single document. It is rendered within the "Versions" tab. [More details](../versions/overview). |
|
||||||
@@ -112,8 +112,8 @@ export const MyCollection: CollectionConfig = {
|
|||||||
path: '/my-custom-tab',
|
path: '/my-custom-tab',
|
||||||
// highlight-start
|
// highlight-start
|
||||||
tab: {
|
tab: {
|
||||||
Component: '/path/to/MyCustomTabComponent'
|
Component: '/path/to/MyCustomTabComponent',
|
||||||
}
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
},
|
},
|
||||||
anotherCustomTab: {
|
anotherCustomTab: {
|
||||||
@@ -123,7 +123,7 @@ export const MyCollection: CollectionConfig = {
|
|||||||
tab: {
|
tab: {
|
||||||
label: 'Another Custom View',
|
label: 'Another Custom View',
|
||||||
href: '/another-custom-view',
|
href: '/another-custom-view',
|
||||||
}
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -134,14 +134,13 @@ export const MyCollection: CollectionConfig = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Note:**
|
**Note:** This applies to _both_ Collections _and_ Globals.
|
||||||
This applies to _both_ Collections _and_ Globals.
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
The following options are available for tabs:
|
The following options are available for tabs:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| ----------- | ----------------------------------------------------------------------------------------------------- |
|
| ----------- | ------------------------------------------------------------------------------------------------------------- |
|
||||||
| `label` | The label to display in the tab. |
|
| `label` | The label to display in the tab. |
|
||||||
| `href` | The URL to navigate to when the tab is clicked. This is optional and defaults to the tab's `path`. |
|
| `href` | The URL to navigate to when the tab is clicked. This is optional and defaults to the tab's `path`. |
|
||||||
| `Component` | The component to render in the tab. This can be a Server or Client component. [More details](#tab-components) |
|
| `Component` | The component to render in the tab. This can be a Server or Client component. [More details](#tab-components) |
|
||||||
@@ -161,9 +160,7 @@ import { Link } from '@payloadcms/ui'
|
|||||||
|
|
||||||
export function MyCustomTabComponent(props: DocumentTabServerProps) {
|
export function MyCustomTabComponent(props: DocumentTabServerProps) {
|
||||||
return (
|
return (
|
||||||
<Link href="/my-custom-tab">
|
<Link href="/my-custom-tab">This is a custom Document Tab (Server)</Link>
|
||||||
This is a custom Document Tab (Server)
|
|
||||||
</Link>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -178,9 +175,7 @@ import { Link } from '@payloadcms/ui'
|
|||||||
|
|
||||||
export function MyCustomTabComponent(props: DocumentTabClientProps) {
|
export function MyCustomTabComponent(props: DocumentTabClientProps) {
|
||||||
return (
|
return (
|
||||||
<Link href="/my-custom-tab">
|
<Link href="/my-custom-tab">This is a custom Document Tab (Client)</Link>
|
||||||
This is a custom Document Tab (Client)
|
|
||||||
</Link>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ The Edit View is where users interact with individual [Collection](../collection
|
|||||||
The Edit View can be swapped out in its entirety for a Custom View, or it can be injected with a number of Custom Components to add additional functionality or presentational elements without replacing the entire view.
|
The Edit View can be swapped out in its entirety for a Custom View, or it can be injected with a number of Custom Components to add additional functionality or presentational elements without replacing the entire view.
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Note:**
|
**Note:** The Edit View is one of many [Document Views](./document-views) in
|
||||||
The Edit View is one of many [Document Views](./document-views) in the Payload Admin Panel. Each Document View is responsible for a different aspect of the interacting with a single Document.
|
the Payload Admin Panel. Each Document View is responsible for a different
|
||||||
|
aspect of the interacting with a single Document.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Custom Edit View
|
## Custom Edit View
|
||||||
@@ -33,7 +34,7 @@ const config = buildConfig({
|
|||||||
Component: '/path/to/MyCustomEditViewComponent',
|
Component: '/path/to/MyCustomEditViewComponent',
|
||||||
},
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -49,11 +50,7 @@ import React from 'react'
|
|||||||
import type { DocumentViewServerProps } from 'payload'
|
import type { DocumentViewServerProps } from 'payload'
|
||||||
|
|
||||||
export function MyCustomServerEditView(props: DocumentViewServerProps) {
|
export function MyCustomServerEditView(props: DocumentViewServerProps) {
|
||||||
return (
|
return <div>This is a custom Edit View (Server)</div>
|
||||||
<div>
|
|
||||||
This is a custom Edit View (Server)
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -65,11 +62,7 @@ import React from 'react'
|
|||||||
import type { DocumentViewClientProps } from 'payload'
|
import type { DocumentViewClientProps } from 'payload'
|
||||||
|
|
||||||
export function MyCustomClientEditView(props: DocumentViewClientProps) {
|
export function MyCustomClientEditView(props: DocumentViewClientProps) {
|
||||||
return (
|
return <div>This is a custom Edit View (Client)</div>
|
||||||
<div>
|
|
||||||
This is a custom Edit View (Client)
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -80,8 +73,9 @@ _For details on how to build Custom Views, including all available props, see [B
|
|||||||
In addition to swapping out the entire Edit View with a [Custom View](./custom-views), you can also override individual components. This allows you to customize specific parts of the Edit View without swapping out the entire view.
|
In addition to swapping out the entire Edit View with a [Custom View](./custom-views), you can also override individual components. This allows you to customize specific parts of the Edit View without swapping out the entire view.
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Important:**
|
**Important:** Collection and Globals are keyed to a different property in the
|
||||||
Collection and Globals are keyed to a different property in the `admin.components` object have slightly different options. Be sure to use the correct key for the entity you are working with.
|
`admin.components` object have slightly different options. Be sure to use the
|
||||||
|
correct key for the entity you are working with.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
#### Collections
|
#### Collections
|
||||||
@@ -108,7 +102,7 @@ export const MyCollection: CollectionConfig = {
|
|||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Path | Description |
|
| Path | Description |
|
||||||
|-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ----------------- | -------------------------------------------------------------------------------------- |
|
||||||
| `SaveButton` | A button that saves the current document. [More details](#SaveButton). |
|
| `SaveButton` | A button that saves the current document. [More details](#SaveButton). |
|
||||||
| `SaveDraftButton` | A button that saves the current document as a draft. [More details](#SaveDraftButton). |
|
| `SaveDraftButton` | A button that saves the current document as a draft. [More details](#SaveDraftButton). |
|
||||||
| `PublishButton` | A button that publishes the current document. [More details](#PublishButton). |
|
| `PublishButton` | A button that publishes the current document. [More details](#PublishButton). |
|
||||||
@@ -140,7 +134,7 @@ export const MyGlobal: GlobalConfig = {
|
|||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Path | Description |
|
| Path | Description |
|
||||||
|-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ----------------- | -------------------------------------------------------------------------------------- |
|
||||||
| `SaveButton` | A button that saves the current document. [More details](#SaveButton). |
|
| `SaveButton` | A button that saves the current document. [More details](#SaveButton). |
|
||||||
| `SaveDraftButton` | A button that saves the current document as a draft. [More details](#SaveDraftButton). |
|
| `SaveDraftButton` | A button that saves the current document as a draft. [More details](#SaveDraftButton). |
|
||||||
| `PublishButton` | A button that publishes the current document. [More details](#PublishButton). |
|
| `PublishButton` | A button that publishes the current document. [More details](#PublishButton). |
|
||||||
@@ -164,7 +158,7 @@ export const MyCollection: CollectionConfig = {
|
|||||||
// highlight-start
|
// highlight-start
|
||||||
SaveButton: '/path/to/MySaveButton',
|
SaveButton: '/path/to/MySaveButton',
|
||||||
// highlight-end
|
// highlight-end
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -180,9 +174,7 @@ import { SaveButton } from '@payloadcms/ui'
|
|||||||
import type { SaveButtonServerProps } from 'payload'
|
import type { SaveButtonServerProps } from 'payload'
|
||||||
|
|
||||||
export function MySaveButton(props: SaveButtonServerProps) {
|
export function MySaveButton(props: SaveButtonServerProps) {
|
||||||
return (
|
return <SaveButton label="Save" />
|
||||||
<SaveButton label="Save" />
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -195,9 +187,7 @@ import { SaveButton } from '@payloadcms/ui'
|
|||||||
import type { SaveButtonClientProps } from 'payload'
|
import type { SaveButtonClientProps } from 'payload'
|
||||||
|
|
||||||
export function MySaveButton(props: SaveButtonClientProps) {
|
export function MySaveButton(props: SaveButtonClientProps) {
|
||||||
return (
|
return <SaveButton label="Save" />
|
||||||
<SaveButton label="Save" />
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -218,7 +208,7 @@ export const MyCollection: CollectionConfig = {
|
|||||||
// highlight-start
|
// highlight-start
|
||||||
SaveDraftButton: '/path/to/MySaveDraftButton',
|
SaveDraftButton: '/path/to/MySaveDraftButton',
|
||||||
// highlight-end
|
// highlight-end
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -234,9 +224,7 @@ import { SaveDraftButton } from '@payloadcms/ui'
|
|||||||
import type { SaveDraftButtonServerProps } from 'payload'
|
import type { SaveDraftButtonServerProps } from 'payload'
|
||||||
|
|
||||||
export function MySaveDraftButton(props: SaveDraftButtonServerProps) {
|
export function MySaveDraftButton(props: SaveDraftButtonServerProps) {
|
||||||
return (
|
return <SaveDraftButton />
|
||||||
<SaveDraftButton />
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -249,9 +237,7 @@ import { SaveDraftButton } from '@payloadcms/ui'
|
|||||||
import type { SaveDraftButtonClientProps } from 'payload'
|
import type { SaveDraftButtonClientProps } from 'payload'
|
||||||
|
|
||||||
export function MySaveDraftButton(props: SaveDraftButtonClientProps) {
|
export function MySaveDraftButton(props: SaveDraftButtonClientProps) {
|
||||||
return (
|
return <SaveDraftButton />
|
||||||
<SaveDraftButton />
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -272,7 +258,7 @@ export const MyCollection: CollectionConfig = {
|
|||||||
// highlight-start
|
// highlight-start
|
||||||
PublishButton: '/path/to/MyPublishButton',
|
PublishButton: '/path/to/MyPublishButton',
|
||||||
// highlight-end
|
// highlight-end
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -288,9 +274,7 @@ import { PublishButton } from '@payloadcms/ui'
|
|||||||
import type { PublishButtonClientProps } from 'payload'
|
import type { PublishButtonClientProps } from 'payload'
|
||||||
|
|
||||||
export function MyPublishButton(props: PublishButtonServerProps) {
|
export function MyPublishButton(props: PublishButtonServerProps) {
|
||||||
return (
|
return <PublishButton label="Publish" />
|
||||||
<PublishButton label="Publish" />
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -303,9 +287,7 @@ import { PublishButton } from '@payloadcms/ui'
|
|||||||
import type { PublishButtonClientProps } from 'payload'
|
import type { PublishButtonClientProps } from 'payload'
|
||||||
|
|
||||||
export function MyPublishButton(props: PublishButtonClientProps) {
|
export function MyPublishButton(props: PublishButtonClientProps) {
|
||||||
return (
|
return <PublishButton label="Publish" />
|
||||||
<PublishButton label="Publish" />
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -326,7 +308,7 @@ export const MyCollection: CollectionConfig = {
|
|||||||
// highlight-start
|
// highlight-start
|
||||||
PreviewButton: '/path/to/MyPreviewButton',
|
PreviewButton: '/path/to/MyPreviewButton',
|
||||||
// highlight-end
|
// highlight-end
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -342,9 +324,7 @@ import { PreviewButton } from '@payloadcms/ui'
|
|||||||
import type { PreviewButtonServerProps } from 'payload'
|
import type { PreviewButtonServerProps } from 'payload'
|
||||||
|
|
||||||
export function MyPreviewButton(props: PreviewButtonServerProps) {
|
export function MyPreviewButton(props: PreviewButtonServerProps) {
|
||||||
return (
|
return <PreviewButton />
|
||||||
<PreviewButton />
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -357,9 +337,7 @@ import { PreviewButton } from '@payloadcms/ui'
|
|||||||
import type { PreviewButtonClientProps } from 'payload'
|
import type { PreviewButtonClientProps } from 'payload'
|
||||||
|
|
||||||
export function MyPreviewButton(props: PreviewButtonClientProps) {
|
export function MyPreviewButton(props: PreviewButtonClientProps) {
|
||||||
return (
|
return <PreviewButton />
|
||||||
<PreviewButton />
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -385,8 +363,8 @@ export const MyCollection: CollectionConfig = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Note:**
|
**Note:** The `Description` component is shared between the Edit View and the
|
||||||
The `Description` component is shared between the Edit View and the [List View](./list-view).
|
[List View](./list-view).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
Here's an example of a custom `Description` component:
|
Here's an example of a custom `Description` component:
|
||||||
@@ -398,11 +376,7 @@ import React from 'react'
|
|||||||
import type { ViewDescriptionServerProps } from 'payload'
|
import type { ViewDescriptionServerProps } from 'payload'
|
||||||
|
|
||||||
export function MyDescriptionComponent(props: ViewDescriptionServerProps) {
|
export function MyDescriptionComponent(props: ViewDescriptionServerProps) {
|
||||||
return (
|
return <div>This is a custom description component (Server)</div>
|
||||||
<div>
|
|
||||||
This is a custom description component (Server)
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -414,11 +388,7 @@ import React from 'react'
|
|||||||
import type { ViewDescriptionClientProps } from 'payload'
|
import type { ViewDescriptionClientProps } from 'payload'
|
||||||
|
|
||||||
export function MyDescriptionComponent(props: ViewDescriptionClientProps) {
|
export function MyDescriptionComponent(props: ViewDescriptionClientProps) {
|
||||||
return (
|
return <div>This is a custom description component (Client)</div>
|
||||||
<div>
|
|
||||||
This is a custom description component (Client)
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -439,15 +409,14 @@ export const MyCollection: CollectionConfig = {
|
|||||||
// highlight-start
|
// highlight-start
|
||||||
Upload: '/path/to/MyUploadComponent',
|
Upload: '/path/to/MyUploadComponent',
|
||||||
// highlight-end
|
// highlight-end
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Note:**
|
**Note:** The Upload component is only available for Collections.
|
||||||
The Upload component is only available for Collections.
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
Here's an example of a custom `Upload` component:
|
Here's an example of a custom `Upload` component:
|
||||||
@@ -456,8 +425,6 @@ Here's an example of a custom `Upload` component:
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
export function MyUploadComponent() {
|
export function MyUploadComponent() {
|
||||||
return (
|
return <input type="file" />
|
||||||
<input type="file" />
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ The List View is where users interact with a list of [Collection](../collections
|
|||||||
The List View can be swapped out in its entirety for a Custom View, or it can be injected with a number of Custom Components to add additional functionality or presentational elements without replacing the entire view.
|
The List View can be swapped out in its entirety for a Custom View, or it can be injected with a number of Custom Components to add additional functionality or presentational elements without replacing the entire view.
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
**Note:**
|
**Note:** Only [Collections](../collections/overview) have a List View.
|
||||||
Only [Collections](../collections/overview) have a List View. [Globals](../globals/overview) do not have a List View as they are single documents.
|
[Globals](../globals/overview) do not have a List View as they are single
|
||||||
|
documents.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Custom List View
|
## Custom List View
|
||||||
@@ -46,11 +47,7 @@ import type { ListViewServerProps } from 'payload'
|
|||||||
import { DefaultListView } from '@payloadcms/ui'
|
import { DefaultListView } from '@payloadcms/ui'
|
||||||
|
|
||||||
export function MyCustomServerListView(props: ListViewServerProps) {
|
export function MyCustomServerListView(props: ListViewServerProps) {
|
||||||
return (
|
return <div>This is a custom List View (Server)</div>
|
||||||
<div>
|
|
||||||
This is a custom List View (Server)
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -62,11 +59,7 @@ import React from 'react'
|
|||||||
import type { ListViewClientProps } from 'payload'
|
import type { ListViewClientProps } from 'payload'
|
||||||
|
|
||||||
export function MyCustomClientListView(props: ListViewClientProps) {
|
export function MyCustomClientListView(props: ListViewClientProps) {
|
||||||
return (
|
return <div>This is a custom List View (Client)</div>
|
||||||
<div>
|
|
||||||
This is a custom List View (Client)
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -96,7 +89,7 @@ export const MyCollection: CollectionConfig = {
|
|||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Path | Description |
|
| Path | Description |
|
||||||
|-----------------------|----------------------------------------------------------------------------------------------------------------------------- |
|
| ----------------- | ------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `beforeList` | An array of custom components to inject before the list of documents in the List View. [More details](#beforeList). |
|
| `beforeList` | An array of custom components to inject before the list of documents in the List View. [More details](#beforeList). |
|
||||||
| `beforeListTable` | An array of custom components to inject before the table of documents in the List View. [More details](#beforeListTable). |
|
| `beforeListTable` | An array of custom components to inject before the table of documents in the List View. [More details](#beforeListTable). |
|
||||||
| `afterList` | An array of custom components to inject after the list of documents in the List View. [More details](#afterList). |
|
| `afterList` | An array of custom components to inject after the list of documents in the List View. [More details](#afterList). |
|
||||||
@@ -117,9 +110,7 @@ export const MyCollection: CollectionConfig = {
|
|||||||
admin: {
|
admin: {
|
||||||
components: {
|
components: {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
beforeList: [
|
beforeList: ['/path/to/MyBeforeListComponent'],
|
||||||
'/path/to/MyBeforeListComponent',
|
|
||||||
],
|
|
||||||
// highlight-end
|
// highlight-end
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -135,11 +126,7 @@ import React from 'react'
|
|||||||
import type { BeforeListServerProps } from 'payload'
|
import type { BeforeListServerProps } from 'payload'
|
||||||
|
|
||||||
export function MyBeforeListComponent(props: BeforeListServerProps) {
|
export function MyBeforeListComponent(props: BeforeListServerProps) {
|
||||||
return (
|
return <div>This is a custom beforeList component (Server)</div>
|
||||||
<div>
|
|
||||||
This is a custom beforeList component (Server)
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -151,11 +138,7 @@ import React from 'react'
|
|||||||
import type { BeforeListClientProps } from 'payload'
|
import type { BeforeListClientProps } from 'payload'
|
||||||
|
|
||||||
export function MyBeforeListComponent(props: BeforeListClientProps) {
|
export function MyBeforeListComponent(props: BeforeListClientProps) {
|
||||||
return (
|
return <div>This is a custom beforeList component (Client)</div>
|
||||||
<div>
|
|
||||||
This is a custom beforeList component (Client)
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -173,9 +156,7 @@ export const MyCollection: CollectionConfig = {
|
|||||||
admin: {
|
admin: {
|
||||||
components: {
|
components: {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
beforeListTable: [
|
beforeListTable: ['/path/to/MyBeforeListTableComponent'],
|
||||||
'/path/to/MyBeforeListTableComponent',
|
|
||||||
],
|
|
||||||
// highlight-end
|
// highlight-end
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -191,11 +172,7 @@ import React from 'react'
|
|||||||
import type { BeforeListTableServerProps } from 'payload'
|
import type { BeforeListTableServerProps } from 'payload'
|
||||||
|
|
||||||
export function MyBeforeListTableComponent(props: BeforeListTableServerProps) {
|
export function MyBeforeListTableComponent(props: BeforeListTableServerProps) {
|
||||||
return (
|
return <div>This is a custom beforeListTable component (Server)</div>
|
||||||
<div>
|
|
||||||
This is a custom beforeListTable component (Server)
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -207,11 +184,7 @@ import React from 'react'
|
|||||||
import type { BeforeListTableClientProps } from 'payload'
|
import type { BeforeListTableClientProps } from 'payload'
|
||||||
|
|
||||||
export function MyBeforeListTableComponent(props: BeforeListTableClientProps) {
|
export function MyBeforeListTableComponent(props: BeforeListTableClientProps) {
|
||||||
return (
|
return <div>This is a custom beforeListTable component (Client)</div>
|
||||||
<div>
|
|
||||||
This is a custom beforeListTable component (Client)
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -229,9 +202,7 @@ export const MyCollection: CollectionConfig = {
|
|||||||
admin: {
|
admin: {
|
||||||
components: {
|
components: {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
afterList: [
|
afterList: ['/path/to/MyAfterListComponent'],
|
||||||
'/path/to/MyAfterListComponent',
|
|
||||||
],
|
|
||||||
// highlight-end
|
// highlight-end
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -247,11 +218,7 @@ import React from 'react'
|
|||||||
import type { AfterListServerProps } from 'payload'
|
import type { AfterListServerProps } from 'payload'
|
||||||
|
|
||||||
export function MyAfterListComponent(props: AfterListServerProps) {
|
export function MyAfterListComponent(props: AfterListServerProps) {
|
||||||
return (
|
return <div>This is a custom afterList component (Server)</div>
|
||||||
<div>
|
|
||||||
This is a custom afterList component (Server)
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -263,11 +230,7 @@ import React from 'react'
|
|||||||
import type { AfterListClientProps } from 'payload'
|
import type { AfterListClientProps } from 'payload'
|
||||||
|
|
||||||
export function MyAfterListComponent(props: AfterListClientProps) {
|
export function MyAfterListComponent(props: AfterListClientProps) {
|
||||||
return (
|
return <div>This is a custom afterList component (Client)</div>
|
||||||
<div>
|
|
||||||
This is a custom afterList component (Client)
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -285,9 +248,7 @@ export const MyCollection: CollectionConfig = {
|
|||||||
admin: {
|
admin: {
|
||||||
components: {
|
components: {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
afterListTable: [
|
afterListTable: ['/path/to/MyAfterListTableComponent'],
|
||||||
'/path/to/MyAfterListTableComponent',
|
|
||||||
],
|
|
||||||
// highlight-end
|
// highlight-end
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -303,11 +264,7 @@ import React from 'react'
|
|||||||
import type { AfterListTableServerProps } from 'payload'
|
import type { AfterListTableServerProps } from 'payload'
|
||||||
|
|
||||||
export function MyAfterListTableComponent(props: AfterListTableServerProps) {
|
export function MyAfterListTableComponent(props: AfterListTableServerProps) {
|
||||||
return (
|
return <div>This is a custom afterListTable component (Server)</div>
|
||||||
<div>
|
|
||||||
This is a custom afterListTable component (Server)
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -319,11 +276,7 @@ import React from 'react'
|
|||||||
import type { AfterListTableClientProps } from 'payload'
|
import type { AfterListTableClientProps } from 'payload'
|
||||||
|
|
||||||
export function MyAfterListTableComponent(props: AfterListTableClientProps) {
|
export function MyAfterListTableComponent(props: AfterListTableClientProps) {
|
||||||
return (
|
return <div>This is a custom afterListTable component (Client)</div>
|
||||||
<div>
|
|
||||||
This is a custom afterListTable component (Client)
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -349,8 +302,8 @@ export const MyCollection: CollectionConfig = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Note:**
|
**Note:** The `Description` component is shared between the List View and the
|
||||||
The `Description` component is shared between the List View and the [Edit View](./edit-view).
|
[Edit View](./edit-view).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
Here's an example of a custom `Description` component:
|
Here's an example of a custom `Description` component:
|
||||||
@@ -362,11 +315,7 @@ import React from 'react'
|
|||||||
import type { ViewDescriptionServerProps } from 'payload'
|
import type { ViewDescriptionServerProps } from 'payload'
|
||||||
|
|
||||||
export function MyDescriptionComponent(props: ViewDescriptionServerProps) {
|
export function MyDescriptionComponent(props: ViewDescriptionServerProps) {
|
||||||
return (
|
return <div>This is a custom Collection description component (Server)</div>
|
||||||
<div>
|
|
||||||
This is a custom Collection description component (Server)
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -378,10 +327,6 @@ import React from 'react'
|
|||||||
import type { ViewDescriptionClientProps } from 'payload'
|
import type { ViewDescriptionClientProps } from 'payload'
|
||||||
|
|
||||||
export function MyDescriptionComponent(props: ViewDescriptionClientProps) {
|
export function MyDescriptionComponent(props: ViewDescriptionClientProps) {
|
||||||
return (
|
return <div>This is a custom Collection description component (Client)</div>
|
||||||
<div>
|
|
||||||
This is a custom Collection description component (Client)
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -11,8 +11,12 @@ The Payload [Admin Panel](../admin/overview) is designed to be as minimal and st
|
|||||||
All Custom Components in Payload are [React Server Components](https://react.dev/reference/rsc/server-components) by default. This enables the use of the [Local API](../local-api/overview) directly on the front-end. Custom Components are available for nearly every part of the Admin Panel for extreme granularity and control.
|
All Custom Components in Payload are [React Server Components](https://react.dev/reference/rsc/server-components) by default. This enables the use of the [Local API](../local-api/overview) directly on the front-end. Custom Components are available for nearly every part of the Admin Panel for extreme granularity and control.
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Note:**
|
**Note:** Client Components continue to be fully supported. To use Client
|
||||||
Client Components continue to be fully supported. To use Client Components in your app, simply include the `'use client'` directive. Payload will automatically detect and remove all [non-serializable](https://react.dev/reference/rsc/use-client#serializable-types) default props before rendering your component. [More details](#client-components).
|
Components in your app, simply include the `'use client'` directive. Payload
|
||||||
|
will automatically detect and remove all
|
||||||
|
[non-serializable](https://react.dev/reference/rsc/use-client#serializable-types)
|
||||||
|
default props before rendering your component. [More
|
||||||
|
details](#client-components).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
There are four main types of Custom Components in Payload:
|
There are four main types of Custom Components in Payload:
|
||||||
@@ -38,16 +42,17 @@ const config = buildConfig({
|
|||||||
admin: {
|
admin: {
|
||||||
components: {
|
components: {
|
||||||
logout: {
|
logout: {
|
||||||
Button: '/src/components/Logout#MyComponent' // highlight-line
|
Button: '/src/components/Logout#MyComponent', // highlight-line
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Note:**
|
**Note:** All Custom Components can be either Server Components or Client
|
||||||
All Custom Components can be either Server Components or Client Components, depending on the presence of the `'use client'` directive at the top of the file.
|
Components, depending on the presence of the `'use client'` directive at the
|
||||||
|
top of the file.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### Component Paths
|
### Component Paths
|
||||||
@@ -73,9 +78,9 @@ const config = buildConfig({
|
|||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
logout: {
|
logout: {
|
||||||
Button: '/components/Logout#MyComponent' // highlight-line
|
Button: '/components/Logout#MyComponent', // highlight-line
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
@@ -98,10 +103,10 @@ const config = buildConfig({
|
|||||||
Button: {
|
Button: {
|
||||||
path: '/src/components/Logout',
|
path: '/src/components/Logout',
|
||||||
exportName: 'MyComponent',
|
exportName: 'MyComponent',
|
||||||
}
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
@@ -109,7 +114,7 @@ const config = buildConfig({
|
|||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
|---------------|-------------------------------------------------------------------------------------------------------------------------------|
|
| ------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `clientProps` | Props to be passed to the Custom Components if it's a Client Component. [More details](#custom-props). |
|
| `clientProps` | Props to be passed to the Custom Components if it's a Client Component. [More details](#custom-props). |
|
||||||
| `exportName` | Instead of declaring named exports using `#` in the component path, you can also omit them from `path` and pass them in here. |
|
| `exportName` | Instead of declaring named exports using `#` in the component path, you can also omit them from `path` and pass them in here. |
|
||||||
| `path` | File path to the Custom Component. Named exports can be appended to the end of the path, separated by a `#`. |
|
| `path` | File path to the Custom Component. Named exports can be appended to the end of the path, separated by a `#`. |
|
||||||
@@ -139,7 +144,12 @@ const config = buildConfig({
|
|||||||
admin: {
|
admin: {
|
||||||
importMap: {
|
importMap: {
|
||||||
baseDir: path.resolve(dirname, 'src'),
|
baseDir: path.resolve(dirname, 'src'),
|
||||||
importMapFile: path.resolve(dirname, 'app', '(payload)', 'custom-import-map.js'), // highlight-line
|
importMapFile: path.resolve(
|
||||||
|
dirname,
|
||||||
|
'app',
|
||||||
|
'(payload)',
|
||||||
|
'custom-import-map.js',
|
||||||
|
), // highlight-line
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -159,7 +169,8 @@ export default buildConfig({
|
|||||||
admin: {
|
admin: {
|
||||||
// ...
|
// ...
|
||||||
dependencies: {
|
dependencies: {
|
||||||
myTestComponent: { // myTestComponent is the key - can be anything
|
myTestComponent: {
|
||||||
|
// myTestComponent is the key - can be anything
|
||||||
path: '/components/TestComponent.js#TestComponent',
|
path: '/components/TestComponent.js#TestComponent',
|
||||||
type: 'component',
|
type: 'component',
|
||||||
clientProps: {
|
clientProps: {
|
||||||
@@ -167,7 +178,7 @@ export default buildConfig({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -186,7 +197,7 @@ import React from 'react'
|
|||||||
import type { Payload } from 'payload'
|
import type { Payload } from 'payload'
|
||||||
|
|
||||||
async function MyServerComponent({
|
async function MyServerComponent({
|
||||||
payload // highlight-line
|
payload, // highlight-line
|
||||||
}: {
|
}: {
|
||||||
payload: Payload
|
payload: Payload
|
||||||
}) {
|
}) {
|
||||||
@@ -195,22 +206,25 @@ async function MyServerComponent({
|
|||||||
id: '123',
|
id: '123',
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return <p>{page.title}</p>
|
||||||
<p>{page.title}</p>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Each Custom Component receives the following props by default:
|
Each Custom Component receives the following props by default:
|
||||||
|
|
||||||
| Prop | Description |
|
| Prop | Description |
|
||||||
| ------------------------- | ----------------------------------------------------------------------------------------------------- |
|
| --------- | ------------------------------------------- |
|
||||||
| `payload` | The [Payload](../local-api/overview) class. |
|
| `payload` | The [Payload](../local-api/overview) class. |
|
||||||
| `i18n` | The [i18n](../configuration/i18n) object. |
|
| `i18n` | The [i18n](../configuration/i18n) object. |
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Reminder:**
|
**Reminder:** All Custom Components also receive various other props that are
|
||||||
All Custom Components also receive various other props that are specific to the component being rendered. See [Root Components](#root-components), [Collection Components](../configuration/collections#custom-components), [Global Components](../configuration/globals#custom-components), or [Field Components](../fields/overview#custom-components) for a complete list of all default props per component.
|
specific to the component being rendered. See [Root
|
||||||
|
Components](#root-components), [Collection
|
||||||
|
Components](../configuration/collections#custom-components), [Global
|
||||||
|
Components](../configuration/globals#custom-components), or [Field
|
||||||
|
Components](../fields/overview#custom-components) for a complete list of all
|
||||||
|
default props per component.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### Custom Props
|
### Custom Props
|
||||||
@@ -222,17 +236,18 @@ import { buildConfig } from 'payload'
|
|||||||
|
|
||||||
const config = buildConfig({
|
const config = buildConfig({
|
||||||
// ...
|
// ...
|
||||||
admin: { // highlight-line
|
admin: {
|
||||||
|
// highlight-line
|
||||||
components: {
|
components: {
|
||||||
logout: {
|
logout: {
|
||||||
Button: {
|
Button: {
|
||||||
path: '/src/components/Logout#MyComponent',
|
path: '/src/components/Logout#MyComponent',
|
||||||
clientProps: {
|
clientProps: {
|
||||||
myCustomProp: 'Hello, World!' // highlight-line
|
myCustomProp: 'Hello, World!', // highlight-line
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
@@ -244,9 +259,7 @@ import React from 'react'
|
|||||||
import { Link } from '@payloadcms/ui'
|
import { Link } from '@payloadcms/ui'
|
||||||
|
|
||||||
export function MyComponent({ myCustomProp }: { myCustomProp: string }) {
|
export function MyComponent({ myCustomProp }: { myCustomProp: string }) {
|
||||||
return (
|
return <Link href="/admin/logout">{myCustomProp}</Link>
|
||||||
<Link href="/admin/logout">{myCustomProp}</Link>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -264,16 +277,16 @@ export function MyClientComponent() {
|
|||||||
const [count, setCount] = useState(0)
|
const [count, setCount] = useState(0)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button onClick={() => setCount(count + 1)}>
|
<button onClick={() => setCount(count + 1)}>Clicked {count} times</button>
|
||||||
Clicked {count} times
|
|
||||||
</button>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Reminder:**
|
**Reminder:** Client Components cannot be passed [non-serializable
|
||||||
Client Components cannot be passed [non-serializable props](https://react.dev/reference/rsc/use-client#serializable-types). If you are rendering your Client Component _from within_ a Server Component, ensure that its props are serializable.
|
props](https://react.dev/reference/rsc/use-client#serializable-types). If you
|
||||||
|
are rendering your Client Component _from within_ a Server Component, ensure
|
||||||
|
that its props are serializable.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### Accessing the Payload Config
|
### Accessing the Payload Config
|
||||||
@@ -285,14 +298,10 @@ import React from 'react'
|
|||||||
|
|
||||||
export default async function MyServerComponent({
|
export default async function MyServerComponent({
|
||||||
payload: {
|
payload: {
|
||||||
config // highlight-line
|
config, // highlight-line
|
||||||
}
|
},
|
||||||
}) {
|
}) {
|
||||||
return (
|
return <Link href={config.serverURL}>Go Home</Link>
|
||||||
<Link href={config.serverURL}>
|
|
||||||
Go Home
|
|
||||||
</Link>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -307,14 +316,12 @@ import { useConfig } from '@payloadcms/ui'
|
|||||||
|
|
||||||
export function MyClientComponent() {
|
export function MyClientComponent() {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
const { config: { serverURL } } = useConfig()
|
const {
|
||||||
|
config: { serverURL },
|
||||||
|
} = useConfig()
|
||||||
// highlight-end
|
// highlight-end
|
||||||
|
|
||||||
return (
|
return <Link href={serverURL}>Go Home</Link>
|
||||||
<Link href={serverURL}>
|
|
||||||
Go Home
|
|
||||||
</Link>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -330,12 +337,10 @@ Within Server Components, this prop is named `field`:
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import type { TextFieldServerComponent } from 'payload'
|
import type { TextFieldServerComponent } from 'payload'
|
||||||
|
|
||||||
export const MyClientFieldComponent: TextFieldServerComponent = ({ field: { name } }) => {
|
export const MyClientFieldComponent: TextFieldServerComponent = ({
|
||||||
return (
|
field: { name },
|
||||||
<p>
|
}) => {
|
||||||
{`This field's name is ${name}`}
|
return <p>{`This field's name is ${name}`}</p>
|
||||||
</p>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -346,12 +351,10 @@ Within Client Components, this prop is named `clientField` because its non-seria
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import type { TextFieldClientComponent } from 'payload'
|
import type { TextFieldClientComponent } from 'payload'
|
||||||
|
|
||||||
export const MyClientFieldComponent: TextFieldClientComponent = ({ clientField: { name } }) => {
|
export const MyClientFieldComponent: TextFieldClientComponent = ({
|
||||||
return (
|
clientField: { name },
|
||||||
<p>
|
}) => {
|
||||||
{`This field's name is ${name}`}
|
return <p>{`This field's name is ${name}`}</p>
|
||||||
</p>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -370,9 +373,7 @@ import { getTranslation } from '@payloadcms/translations'
|
|||||||
export default async function MyServerComponent({ i18n }) {
|
export default async function MyServerComponent({ i18n }) {
|
||||||
const translatedTitle = getTranslation(myTranslation, i18n) // highlight-line
|
const translatedTitle = getTranslation(myTranslation, i18n) // highlight-line
|
||||||
|
|
||||||
return (
|
return <p>{translatedTitle}</p>
|
||||||
<p>{translatedTitle}</p>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -397,7 +398,8 @@ export function MyClientComponent() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
See the [Hooks](../admin/react-hooks) documentation for a full list of available hooks.
|
See the [Hooks](../admin/react-hooks) documentation for a full list of
|
||||||
|
available hooks.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### Getting the Current Locale
|
### Getting the Current Locale
|
||||||
@@ -416,9 +418,7 @@ export default async function MyServerComponent({ payload, locale }) {
|
|||||||
locale,
|
locale,
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return <p>{localizedPage.title}</p>
|
||||||
<p>{localizedPage.title}</p>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -437,14 +437,13 @@ function Greeting() {
|
|||||||
es: 'Hola',
|
es: 'Hola',
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return <span>{trans[locale.code]}</span>
|
||||||
<span>{trans[locale.code]}</span>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
See the [Hooks](../admin/react-hooks) documentation for a full list of available hooks.
|
See the [Hooks](../admin/react-hooks) documentation for a full list of
|
||||||
|
available hooks.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### Using Hooks
|
### Using Hooks
|
||||||
@@ -459,14 +458,13 @@ import { useDocumentInfo } from '@payloadcms/ui'
|
|||||||
export function MyClientComponent() {
|
export function MyClientComponent() {
|
||||||
const { slug } = useDocumentInfo() // highlight-line
|
const { slug } = useDocumentInfo() // highlight-line
|
||||||
|
|
||||||
return (
|
return <p>{`Entity slug: ${slug}`}</p>
|
||||||
<p>{`Entity slug: ${slug}`}</p>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
See the [Hooks](../admin/react-hooks) documentation for a full list of available hooks.
|
See the [Hooks](../admin/react-hooks) documentation for a full list of
|
||||||
|
available hooks.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### Adding Styles
|
### Adding Styles
|
||||||
@@ -479,11 +477,7 @@ To apply custom styles, simply import your own `.css` or `.scss` file into your
|
|||||||
import './index.scss'
|
import './index.scss'
|
||||||
|
|
||||||
export function MyComponent() {
|
export function MyComponent() {
|
||||||
return (
|
return <div className="my-component">My Custom Component</div>
|
||||||
<div className="my-component">
|
|
||||||
My Custom Component
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -508,6 +502,6 @@ Payload also exports its [SCSS](https://sass-lang.com) library for reuse which i
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Note:**
|
**Note:** You can also drill into Payload's own component styles, or easily
|
||||||
You can also drill into Payload's own component styles, or easily apply global, app-wide CSS. More on that [here](../admin/customizing-css).
|
apply global, app-wide CSS. More on that [here](../admin/customizing-css).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export default buildConfig({
|
|||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Path | Description |
|
| Path | Description |
|
||||||
|-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| `actions` | An array of Custom Components to be rendered _within_ the header of the Admin Panel, providing additional interactivity and functionality. [More details](#actions). |
|
| `actions` | An array of Custom Components to be rendered _within_ the header of the Admin Panel, providing additional interactivity and functionality. [More details](#actions). |
|
||||||
| `afterDashboard` | An array of Custom Components to inject into the built-in Dashboard, _after_ the default dashboard contents. [More details](#afterdashboard). |
|
| `afterDashboard` | An array of Custom Components to inject into the built-in Dashboard, _after_ the default dashboard contents. [More details](#afterdashboard). |
|
||||||
| `afterLogin` | An array of Custom Components to inject into the built-in Login, _after_ the default login form. [More details](#afterlogin). |
|
| `afterLogin` | An array of Custom Components to inject into the built-in Login, _after_ the default login form. [More details](#afterlogin). |
|
||||||
@@ -51,8 +51,10 @@ The following options are available:
|
|||||||
_For details on how to build Custom Components, see [Building Custom Components](./overview#building-custom-components)._
|
_For details on how to build Custom Components, see [Building Custom Components](./overview#building-custom-components)._
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Note:**
|
**Note:** You can also use set [Collection
|
||||||
You can also use set [Collection Components](../configuration/collections#custom-components) and [Global Components](../configuration/globals#custom-components) in their respective configs.
|
Components](../configuration/collections#custom-components) and [Global
|
||||||
|
Components](../configuration/globals#custom-components) in their respective
|
||||||
|
configs.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Components
|
## Components
|
||||||
@@ -71,9 +73,7 @@ export default buildConfig({
|
|||||||
admin: {
|
admin: {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
components: {
|
components: {
|
||||||
actions: [
|
actions: ['/path/to/your/component'],
|
||||||
'/path/to/your/component',
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
},
|
},
|
||||||
@@ -93,8 +93,8 @@ export default function MyCustomAction() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Note:**
|
**Note:** You can also use add Actions to the [Edit View](./edit-view) and
|
||||||
You can also use add Actions to the [Edit View](./edit-view) and [List View](./list-view) in their respective configs.
|
[List View](./list-view) in their respective configs.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### beforeDashboard
|
### beforeDashboard
|
||||||
@@ -111,9 +111,7 @@ export default buildConfig({
|
|||||||
admin: {
|
admin: {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
components: {
|
components: {
|
||||||
beforeDashboard: [
|
beforeDashboard: ['/path/to/your/component'],
|
||||||
'/path/to/your/component',
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
},
|
},
|
||||||
@@ -124,11 +122,7 @@ Here is an example of a simple `beforeDashboard` component:
|
|||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
export default function MyBeforeDashboardComponent() {
|
export default function MyBeforeDashboardComponent() {
|
||||||
return (
|
return <div>This is a custom component injected before the Dashboard.</div>
|
||||||
<div>
|
|
||||||
This is a custom component injected before the Dashboard.
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -146,9 +140,7 @@ export default buildConfig({
|
|||||||
admin: {
|
admin: {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
components: {
|
components: {
|
||||||
afterDashboard: [
|
afterDashboard: ['/path/to/your/component'],
|
||||||
'/path/to/your/component',
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
},
|
},
|
||||||
@@ -159,11 +151,7 @@ Here is an example of a simple `afterDashboard` component:
|
|||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
export default function MyAfterDashboardComponent() {
|
export default function MyAfterDashboardComponent() {
|
||||||
return (
|
return <div>This is a custom component injected after the Dashboard.</div>
|
||||||
<div>
|
|
||||||
This is a custom component injected after the Dashboard.
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -181,9 +169,7 @@ export default buildConfig({
|
|||||||
admin: {
|
admin: {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
components: {
|
components: {
|
||||||
beforeLogin: [
|
beforeLogin: ['/path/to/your/component'],
|
||||||
'/path/to/your/component',
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
},
|
},
|
||||||
@@ -194,11 +180,7 @@ Here is an example of a simple `beforeLogin` component:
|
|||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
export default function MyBeforeLoginComponent() {
|
export default function MyBeforeLoginComponent() {
|
||||||
return (
|
return <div>This is a custom component injected before the Login form.</div>
|
||||||
<div>
|
|
||||||
This is a custom component injected before the Login form.
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -216,9 +198,7 @@ export default buildConfig({
|
|||||||
admin: {
|
admin: {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
components: {
|
components: {
|
||||||
afterLogin: [
|
afterLogin: ['/path/to/your/component'],
|
||||||
'/path/to/your/component',
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
},
|
},
|
||||||
@@ -229,11 +209,7 @@ Here is an example of a simple `afterLogin` component:
|
|||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
export default function MyAfterLoginComponent() {
|
export default function MyAfterLoginComponent() {
|
||||||
return (
|
return <div>This is a custom component injected after the Login form.</div>
|
||||||
<div>
|
|
||||||
This is a custom component injected after the Login form.
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -251,9 +227,7 @@ export default buildConfig({
|
|||||||
admin: {
|
admin: {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
components: {
|
components: {
|
||||||
beforeNavLinks: [
|
beforeNavLinks: ['/path/to/your/component'],
|
||||||
'/path/to/your/component',
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
},
|
},
|
||||||
@@ -264,11 +238,7 @@ Here is an example of a simple `beforeNavLinks` component:
|
|||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
export default function MyBeforeNavLinksComponent() {
|
export default function MyBeforeNavLinksComponent() {
|
||||||
return (
|
return <div>This is a custom component injected before the Nav links.</div>
|
||||||
<div>
|
|
||||||
This is a custom component injected before the Nav links.
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -286,9 +256,7 @@ export default buildConfig({
|
|||||||
admin: {
|
admin: {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
components: {
|
components: {
|
||||||
afterNavLinks: [
|
afterNavLinks: ['/path/to/your/component'],
|
||||||
'/path/to/your/component',
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
},
|
},
|
||||||
@@ -299,9 +267,7 @@ Here is an example of a simple `afterNavLinks` component:
|
|||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
export default function MyAfterNavLinksComponent() {
|
export default function MyAfterNavLinksComponent() {
|
||||||
return (
|
return <p>This is a custom component injected after the Nav links.</p>
|
||||||
<p>This is a custom component injected after the Nav links.</p>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -336,9 +302,7 @@ export default function MyCustomNav() {
|
|||||||
<nav>
|
<nav>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<Link href="/dashboard">
|
<Link href="/dashboard">Dashboard</Link>
|
||||||
Dashboard
|
|
||||||
</Link>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
@@ -373,9 +337,7 @@ Here is an example of a simple `Icon` component:
|
|||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
export default function MyCustomIcon() {
|
export default function MyCustomIcon() {
|
||||||
return (
|
return <img src="/path/to/your/icon.png" alt="My Custom Icon" />
|
||||||
<img src="/path/to/your/icon.png" alt="My Custom Icon" />
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -406,9 +368,7 @@ Here is an example of a simple `Logo` component:
|
|||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
export default function MyCustomLogo() {
|
export default function MyCustomLogo() {
|
||||||
return (
|
return <img src="/path/to/your/logo.png" alt="My Custom Logo" />
|
||||||
<img src="/path/to/your/logo.png" alt="My Custom Logo" />
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -428,9 +388,7 @@ export default buildConfig({
|
|||||||
admin: {
|
admin: {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
components: {
|
components: {
|
||||||
Header: [
|
Header: ['/path/to/your/component'],
|
||||||
'/path/to/your/component'
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
},
|
},
|
||||||
@@ -465,7 +423,7 @@ export default buildConfig({
|
|||||||
components: {
|
components: {
|
||||||
logout: {
|
logout: {
|
||||||
Button: '/path/to/your/component',
|
Button: '/path/to/your/component',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
},
|
},
|
||||||
@@ -476,10 +434,6 @@ Here is an example of a simple `logout.Button` component:
|
|||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
export default function MyCustomLogoutButton() {
|
export default function MyCustomLogoutButton() {
|
||||||
return (
|
return <button onClick={() => alert('Logging out!')}>Log Out</button>
|
||||||
<button onClick={() => alert('Logging out!')}>
|
|
||||||
Log Out
|
|
||||||
</button>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -20,8 +20,9 @@ Ensure you have an npm script called "payload" in your `package.json` file.
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner>
|
<Banner>
|
||||||
Note that you need to run Payload migrations through the package manager that you are using,
|
Note that you need to run Payload migrations through the package manager that
|
||||||
because Payload should not be globally installed on your system.
|
you are using, because Payload should not be globally installed on your
|
||||||
|
system.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Migration file contents
|
## Migration file contents
|
||||||
@@ -62,15 +63,23 @@ transaction gets aborted. This way no change is made to the database if the migr
|
|||||||
Additionally, you can bypass Payload's layer entirely and perform operations directly on your underlying database within the active transaction:
|
Additionally, you can bypass Payload's layer entirely and perform operations directly on your underlying database within the active transaction:
|
||||||
|
|
||||||
### MongoDB:
|
### MongoDB:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { type MigrateUpArgs } from '@payloadcms/db-mongodb'
|
import { type MigrateUpArgs } from '@payloadcms/db-mongodb'
|
||||||
|
|
||||||
export async function up({ session, payload, req }: MigrateUpArgs): Promise<void> {
|
export async function up({
|
||||||
const posts = await payload.db.collections.posts.collection.find({ session }).toArray()
|
session,
|
||||||
|
payload,
|
||||||
|
req,
|
||||||
|
}: MigrateUpArgs): Promise<void> {
|
||||||
|
const posts = await payload.db.collections.posts.collection
|
||||||
|
.find({ session })
|
||||||
|
.toArray()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Postgres:
|
### Postgres:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { type MigrateUpArgs, sql } from '@payloadcms/db-postgres'
|
import { type MigrateUpArgs, sql } from '@payloadcms/db-postgres'
|
||||||
|
|
||||||
@@ -80,7 +89,9 @@ export async function up({ db, payload, req }: MigrateUpArgs): Promise<void> {
|
|||||||
```
|
```
|
||||||
|
|
||||||
### SQLite:
|
### SQLite:
|
||||||
|
|
||||||
In SQLite, transactions are disabled by default. [More](./transactions).
|
In SQLite, transactions are disabled by default. [More](./transactions).
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { type MigrateUpArgs, sql } from '@payloadcms/db-sqlite'
|
import { type MigrateUpArgs, sql } from '@payloadcms/db-sqlite'
|
||||||
|
|
||||||
@@ -119,8 +130,9 @@ npm run payload migrate:create optional-name-here
|
|||||||
```
|
```
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
* `--skip-empty`: with Postgres, it skips the "no schema changes detected. Would you like to create a blank migration file?" prompt which can be useful for generating migration in CI.
|
|
||||||
* `--force-accept-warning`: accepts any command prompts, creates a blank migration even if there weren't any changes to the schema.
|
- `--skip-empty`: with Postgres, it skips the "no schema changes detected. Would you like to create a blank migration file?" prompt which can be useful for generating migration in CI.
|
||||||
|
- `--force-accept-warning`: accepts any command prompts, creates a blank migration even if there weren't any changes to the schema.
|
||||||
|
|
||||||
### Status
|
### Status
|
||||||
|
|
||||||
@@ -200,9 +212,10 @@ The typical workflow in Payload is to build out your Payload configs, install pl
|
|||||||
But importantly, you do not need to run migrations against your development database, because Drizzle will have already pushed your changes to your database for you.
|
But importantly, you do not need to run migrations against your development database, because Drizzle will have already pushed your changes to your database for you.
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
Warning: do not mix "push" and migrations with your local development database. If you use "push"
|
Warning: do not mix "push" and migrations with your local development
|
||||||
locally, and then try to migrate, Payload will throw a warning, telling you that these two methods
|
database. If you use "push" locally, and then try to migrate, Payload will
|
||||||
are not meant to be used interchangeably.
|
throw a warning, telling you that these two methods are not meant to be used
|
||||||
|
interchangeably.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
**2 - create a migration**
|
**2 - create a migration**
|
||||||
@@ -217,7 +230,10 @@ But once you're ready, you can run `pnpm payload migrate:create`, which will per
|
|||||||
We won't immediately run this migration for you, however.
|
We won't immediately run this migration for you, however.
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
Tip: migrations created by Payload are relatively programmatic in nature, so there should not be any surprises, but before you check in the created migration it's a good idea to always double-check the contents of the migration files.
|
Tip: migrations created by Payload are relatively programmatic in nature, so
|
||||||
|
there should not be any surprises, but before you check in the created
|
||||||
|
migration it's a good idea to always double-check the contents of the
|
||||||
|
migration files.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
**3 - set up your build process to run migrations**
|
**3 - set up your build process to run migrations**
|
||||||
@@ -270,13 +286,15 @@ export default buildConfig({
|
|||||||
// your config here
|
// your config here
|
||||||
db: postgresAdapter({
|
db: postgresAdapter({
|
||||||
// your adapter config here
|
// your adapter config here
|
||||||
prodMigrations: migrations
|
prodMigrations: migrations,
|
||||||
})
|
}),
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
Passing your migrations as shown above will tell Payload, in production only, to execute any migrations that need to be run prior to completing the initialization of Payload. This is ideal for long-running services where Payload will only be initialized at startup.
|
Passing your migrations as shown above will tell Payload, in production only, to execute any migrations that need to be run prior to completing the initialization of Payload. This is ideal for long-running services where Payload will only be initialized at startup.
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Warning:** if Payload is instructed to run migrations in production, this may slow down serverless cold starts on platforms such as Vercel. Generally, this option should only be used for long-running servers / containers.
|
**Warning:** if Payload is instructed to run migrations in production, this
|
||||||
|
may slow down serverless cold starts on platforms such as Vercel. Generally,
|
||||||
|
this option should only be used for long-running servers / containers.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|||||||
@@ -53,9 +53,10 @@ You can access Mongoose models as follows:
|
|||||||
- Versions model (both collections and globals) - `payload.db.versions[myEntitySlug]`
|
- Versions model (both collections and globals) - `payload.db.versions[myEntitySlug]`
|
||||||
|
|
||||||
## Using other MongoDB implementations
|
## Using other MongoDB implementations
|
||||||
|
|
||||||
Limitations with [DocumentDB](https://aws.amazon.com/documentdb/) and [Azure Cosmos DB](https://azure.microsoft.com/en-us/products/cosmos-db):
|
Limitations with [DocumentDB](https://aws.amazon.com/documentdb/) and [Azure Cosmos DB](https://azure.microsoft.com/en-us/products/cosmos-db):
|
||||||
|
|
||||||
* For Azure Cosmos DB you must pass `transactionOptions: false` to the adapter options. Azure Cosmos DB does not support transactions that update two and more documents in different collections, which is a common case when using Payload (via hooks).
|
- For Azure Cosmos DB you must pass `transactionOptions: false` to the adapter options. Azure Cosmos DB does not support transactions that update two and more documents in different collections, which is a common case when using Payload (via hooks).
|
||||||
* For Azure Cosmos DB the root config property `indexSortableFields` must be set to `true`.
|
- For Azure Cosmos DB the root config property `indexSortableFields` must be set to `true`.
|
||||||
* The [Join Field](../fields/join) is not supported in DocumentDB and Azure Cosmos DB, as we internally use MongoDB aggregations to query data for that field, which are limited there. This can be changed in the future.
|
- The [Join Field](../fields/join) is not supported in DocumentDB and Azure Cosmos DB, as we internally use MongoDB aggregations to query data for that field, which are limited there. This can be changed in the future.
|
||||||
* For DocumentDB pass `disableIndexHints: true` to disable hinting to the DB to use `id` as index which can cause problems with DocumentDB.
|
- For DocumentDB pass `disableIndexHints: true` to disable hinting to the DB to use `id` as index which can cause problems with DocumentDB.
|
||||||
|
|||||||
@@ -31,8 +31,10 @@ export default buildConfig({
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Reminder:**
|
**Reminder:** The Database Adapter is an external dependency and must be
|
||||||
The Database Adapter is an external dependency and must be installed in your project separately from Payload. You can find the installation instructions for each Database Adapter in their respective documentation.
|
installed in your project separately from Payload. You can find the
|
||||||
|
installation instructions for each Database Adapter in their respective
|
||||||
|
documentation.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Selecting a Database
|
## Selecting a Database
|
||||||
|
|||||||
@@ -44,31 +44,38 @@ export default buildConfig({
|
|||||||
// Optionally, can accept the same options as the @vercel/postgres package.
|
// Optionally, can accept the same options as the @vercel/postgres package.
|
||||||
db: vercelPostgresAdapter({
|
db: vercelPostgresAdapter({
|
||||||
pool: {
|
pool: {
|
||||||
connectionString: process.env.DATABASE_URL
|
connectionString: process.env.DATABASE_URL,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
**Note:**
|
**Note:** If you're using `vercelPostgresAdapter` your
|
||||||
If you're using `vercelPostgresAdapter` your `process.env.POSTGRES_URL` or `pool.connectionString` points to a local database (e.g hostname has `localhost` or `127.0.0.1`) we use the `pg` module for pooling instead of `@vercel/postgres`. This is because `@vercel/postgres` doesn't work with local databases, if you want to disable that behavior, you can pass `forceUseVercelPostgres: true` to the adapter's args and follow [Vercel guide](https://vercel.com/docs/storage/vercel-postgres/local-development#option-2:-local-postgres-instance-with-docker) for a Docker Neon DB setup.
|
`process.env.POSTGRES_URL` or `pool.connectionString` points to a local
|
||||||
|
database (e.g hostname has `localhost` or `127.0.0.1`) we use the `pg` module
|
||||||
|
for pooling instead of `@vercel/postgres`. This is because `@vercel/postgres`
|
||||||
|
doesn't work with local databases, if you want to disable that behavior, you
|
||||||
|
can pass `forceUseVercelPostgres: true` to the adapter's args and follow
|
||||||
|
[Vercel
|
||||||
|
guide](https://vercel.com/docs/storage/vercel-postgres/local-development#option-2:-local-postgres-instance-with-docker)
|
||||||
|
for a Docker Neon DB setup.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `pool` * | [Pool connection options](https://orm.drizzle.team/docs/quick-postgresql/node-postgres) that will be passed to Drizzle and `node-postgres` or to `@vercel/postgres` |
|
| `pool` \* | [Pool connection options](https://orm.drizzle.team/docs/quick-postgresql/node-postgres) that will be passed to Drizzle and `node-postgres` or to `@vercel/postgres` |
|
||||||
| `push` | Disable Drizzle's [`db push`](https://orm.drizzle.team/kit-docs/overview#prototyping-with-db-push) in development mode. By default, `push` is enabled for development mode only. |
|
| `push` | Disable Drizzle's [`db push`](https://orm.drizzle.team/kit-docs/overview#prototyping-with-db-push) in development mode. By default, `push` is enabled for development mode only. |
|
||||||
| `migrationDir` | Customize the directory that migrations are stored. |
|
| `migrationDir` | Customize the directory that migrations are stored. |
|
||||||
| `schemaName` (experimental) | A string for the postgres schema to use, defaults to 'public'. |
|
| `schemaName` (experimental) | A string for the postgres schema to use, defaults to 'public'. |
|
||||||
| `idType` | A string of 'serial', or 'uuid' that is used for the data type given to id columns. |
|
| `idType` | A string of 'serial', or 'uuid' that is used for the data type given to id columns. |
|
||||||
| `transactionOptions` | A PgTransactionConfig object for transactions, or set to `false` to disable using transactions. [More details](https://orm.drizzle.team/docs/transactions) |
|
| `transactionOptions` | A PgTransactionConfig object for transactions, or set to `false` to disable using transactions. [More details](https://orm.drizzle.team/docs/transactions) |
|
||||||
| `disableCreateDatabase` | Pass `true` to disable auto database creation if it doesn't exist. Defaults to `false`. |
|
| `disableCreateDatabase` | Pass `true` to disable auto database creation if it doesn't exist. Defaults to `false`. |
|
||||||
| `localesSuffix` | A string appended to the end of table names for storing localized fields. Default is '_locales'. |
|
| `localesSuffix` | A string appended to the end of table names for storing localized fields. Default is '\_locales'. |
|
||||||
| `relationshipsSuffix` | A string appended to the end of table names for storing relationships. Default is '_rels'. |
|
| `relationshipsSuffix` | A string appended to the end of table names for storing relationships. Default is '\_rels'. |
|
||||||
| `versionsSuffix` | A string appended to the end of table names for storing versions. Defaults to '_v'. |
|
| `versionsSuffix` | A string appended to the end of table names for storing versions. Defaults to '\_v'. |
|
||||||
| `beforeSchemaInit` | Drizzle schema hook. Runs before the schema is built. [More Details](#beforeschemainit) |
|
| `beforeSchemaInit` | Drizzle schema hook. Runs before the schema is built. [More Details](#beforeschemainit) |
|
||||||
| `afterSchemaInit` | Drizzle schema hook. Runs after the schema is built. [More Details](#afterschemainit) |
|
| `afterSchemaInit` | Drizzle schema hook. Runs after the schema is built. [More Details](#afterschemainit) |
|
||||||
| `generateSchemaOutputFile` | Override generated schema from `payload generate:db-schema` file path. Defaults to `{CWD}/src/payload-generated.schema.ts` |
|
| `generateSchemaOutputFile` | Override generated schema from `payload generate:db-schema` file path. Defaults to `{CWD}/src/payload-generated.schema.ts` |
|
||||||
@@ -78,11 +85,13 @@ export default buildConfig({
|
|||||||
After Payload is initialized, this adapter will expose the full power of Drizzle to you for use if you need it.
|
After Payload is initialized, this adapter will expose the full power of Drizzle to you for use if you need it.
|
||||||
|
|
||||||
To ensure type-safety, you need to generate Drizzle schema first with:
|
To ensure type-safety, you need to generate Drizzle schema first with:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npx payload generate:db-schema
|
npx payload generate:db-schema
|
||||||
```
|
```
|
||||||
|
|
||||||
Then, you can access Drizzle as follows:
|
Then, you can access Drizzle as follows:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { posts } from './payload-generated-schema'
|
import { posts } from './payload-generated-schema'
|
||||||
// To avoid installing Drizzle, you can import everything that drizzle has from our re-export path.
|
// To avoid installing Drizzle, you can import everything that drizzle has from our re-export path.
|
||||||
@@ -91,7 +100,12 @@ import { eq, sql, and } from '@payloadcms/db-postgres/drizzle'
|
|||||||
// Drizzle's Querying API: https://orm.drizzle.team/docs/rqb
|
// Drizzle's Querying API: https://orm.drizzle.team/docs/rqb
|
||||||
const posts = await payload.db.drizzle.query.posts.findMany()
|
const posts = await payload.db.drizzle.query.posts.findMany()
|
||||||
// Drizzle's Select API https://orm.drizzle.team/docs/select
|
// Drizzle's Select API https://orm.drizzle.team/docs/select
|
||||||
const result = await payload.db.drizzle.select().from(posts).where(and(eq(posts.id, 50), sql`lower(${posts.title}) = 'example post title'`))
|
const result = await payload.db.drizzle
|
||||||
|
.select()
|
||||||
|
.from(posts)
|
||||||
|
.where(
|
||||||
|
and(eq(posts.id, 50), sql`lower(${posts.title}) = 'example post title'`),
|
||||||
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Tables, relations, and enums
|
## Tables, relations, and enums
|
||||||
@@ -126,7 +140,11 @@ Runs before the schema is built. You can use this hook to extend your database s
|
|||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { postgresAdapter } from '@payloadcms/db-postgres'
|
import { postgresAdapter } from '@payloadcms/db-postgres'
|
||||||
import { integer, pgTable, serial } from '@payloadcms/db-postgres/drizzle/pg-core'
|
import {
|
||||||
|
integer,
|
||||||
|
pgTable,
|
||||||
|
serial,
|
||||||
|
} from '@payloadcms/db-postgres/drizzle/pg-core'
|
||||||
|
|
||||||
postgresAdapter({
|
postgresAdapter({
|
||||||
beforeSchemaInit: [
|
beforeSchemaInit: [
|
||||||
@@ -150,7 +168,13 @@ To quickly generate the Drizzle schema from your database you can use [Drizzle I
|
|||||||
You should get the `schema.ts` file which may look like this:
|
You should get the `schema.ts` file which may look like this:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { pgTable, uniqueIndex, serial, varchar, text } from 'drizzle-orm/pg-core'
|
import {
|
||||||
|
pgTable,
|
||||||
|
uniqueIndex,
|
||||||
|
serial,
|
||||||
|
varchar,
|
||||||
|
text,
|
||||||
|
} from 'drizzle-orm/pg-core'
|
||||||
|
|
||||||
export const users = pgTable('users', {
|
export const users = pgTable('users', {
|
||||||
id: serial('id').primaryKey(),
|
id: serial('id').primaryKey(),
|
||||||
@@ -170,7 +194,6 @@ export const countries = pgTable(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
You can import them into your config and append to the schema with the `beforeSchemaInit` hook like this:
|
You can import them into your config and append to the schema with the `beforeSchemaInit` hook like this:
|
||||||
@@ -187,7 +210,7 @@ postgresAdapter({
|
|||||||
tables: {
|
tables: {
|
||||||
...schema.tables,
|
...schema.tables,
|
||||||
users,
|
users,
|
||||||
countries
|
countries,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -197,7 +220,6 @@ postgresAdapter({
|
|||||||
|
|
||||||
Make sure Payload doesn't overlap table names with its collections. For example, if you already have a collection with slug "users", you should either change the slug or `dbName` to change the table name for this collection.
|
Make sure Payload doesn't overlap table names with its collections. For example, if you already have a collection with slug "users", you should either change the slug or `dbName` to change the table name for this collection.
|
||||||
|
|
||||||
|
|
||||||
### afterSchemaInit
|
### afterSchemaInit
|
||||||
|
|
||||||
Runs after the Drizzle schema is built. You can use this hook to modify the schema with features that aren't supported by Payload, or if you want to add a column that you don't want to be in the Payload config.
|
Runs after the Drizzle schema is built. You can use this hook to modify the schema with features that aren't supported by Payload, or if you want to add a column that you don't want to be in the Payload config.
|
||||||
@@ -234,10 +256,9 @@ export default buildConfig({
|
|||||||
extraIntegerColumn: integer('extra_integer_column'),
|
extraIntegerColumn: integer('extra_integer_column'),
|
||||||
},
|
},
|
||||||
extraConfig: (table) => ({
|
extraConfig: (table) => ({
|
||||||
country_city_composite_index: index('country_city_composite_index').on(
|
country_city_composite_index: index(
|
||||||
table.country,
|
'country_city_composite_index',
|
||||||
table.city,
|
).on(table.country, table.city),
|
||||||
),
|
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -246,10 +267,10 @@ export default buildConfig({
|
|||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Note for generated schema:
|
### Note for generated schema:
|
||||||
|
|
||||||
Columns and tables, added in schema hooks won't be added to the generated via `payload generate:db-schema` Drizzle schema.
|
Columns and tables, added in schema hooks won't be added to the generated via `payload generate:db-schema` Drizzle schema.
|
||||||
If you want them to be there, you either have to edit this file manually or mutate the internal Payload "raw" SQL schema in the `beforeSchemaInit`:
|
If you want them to be there, you either have to edit this file manually or mutate the internal Payload "raw" SQL schema in the `beforeSchemaInit`:
|
||||||
|
|
||||||
@@ -266,9 +287,9 @@ postgresAdapter({
|
|||||||
my_id: {
|
my_id: {
|
||||||
name: 'my_id',
|
name: 'my_id',
|
||||||
type: 'serial',
|
type: 'serial',
|
||||||
primaryKey: true
|
primaryKey: true,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a new column to generated by Payload table:
|
// Add a new column to generated by Payload table:
|
||||||
@@ -276,13 +297,13 @@ postgresAdapter({
|
|||||||
name: 'custom_column',
|
name: 'custom_column',
|
||||||
// Note that Payload SQL doesn't support everything that Drizzle does.
|
// Note that Payload SQL doesn't support everything that Drizzle does.
|
||||||
type: 'integer',
|
type: 'integer',
|
||||||
notNull: true
|
notNull: true,
|
||||||
}
|
}
|
||||||
// Add a new index to generated by Payload table:
|
// Add a new index to generated by Payload table:
|
||||||
adapter.rawTables.posts.indexes.customColumnIdx = {
|
adapter.rawTables.posts.indexes.customColumnIdx = {
|
||||||
name: 'custom_column_idx',
|
name: 'custom_column_idx',
|
||||||
unique: true,
|
unique: true,
|
||||||
on: ['custom_column']
|
on: ['custom_column'],
|
||||||
}
|
}
|
||||||
|
|
||||||
return schema
|
return schema
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export default buildConfig({
|
|||||||
client: {
|
client: {
|
||||||
url: process.env.DATABASE_URL,
|
url: process.env.DATABASE_URL,
|
||||||
authToken: process.env.DATABASE_AUTH_TOKEN,
|
authToken: process.env.DATABASE_AUTH_TOKEN,
|
||||||
}
|
},
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
@@ -36,15 +36,15 @@ export default buildConfig({
|
|||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `client` * | [Client connection options](https://orm.drizzle.team/docs/get-started-sqlite#turso) that will be passed to `createClient` from `@libsql/client`. |
|
| `client` \* | [Client connection options](https://orm.drizzle.team/docs/get-started-sqlite#turso) that will be passed to `createClient` from `@libsql/client`. |
|
||||||
| `push` | Disable Drizzle's [`db push`](https://orm.drizzle.team/kit-docs/overview#prototyping-with-db-push) in development mode. By default, `push` is enabled for development mode only. |
|
| `push` | Disable Drizzle's [`db push`](https://orm.drizzle.team/kit-docs/overview#prototyping-with-db-push) in development mode. By default, `push` is enabled for development mode only. |
|
||||||
| `migrationDir` | Customize the directory that migrations are stored. |
|
| `migrationDir` | Customize the directory that migrations are stored. |
|
||||||
| `logger` | The instance of the logger to be passed to drizzle. By default Payload's will be used. |
|
| `logger` | The instance of the logger to be passed to drizzle. By default Payload's will be used. |
|
||||||
| `idType` | A string of 'number', or 'uuid' that is used for the data type given to id columns. |
|
| `idType` | A string of 'number', or 'uuid' that is used for the data type given to id columns. |
|
||||||
| `transactionOptions` | A SQLiteTransactionConfig object for transactions, or set to `false` to disable using transactions. [More details](https://orm.drizzle.team/docs/transactions) |
|
| `transactionOptions` | A SQLiteTransactionConfig object for transactions, or set to `false` to disable using transactions. [More details](https://orm.drizzle.team/docs/transactions) |
|
||||||
| `localesSuffix` | A string appended to the end of table names for storing localized fields. Default is '_locales'. |
|
| `localesSuffix` | A string appended to the end of table names for storing localized fields. Default is '\_locales'. |
|
||||||
| `relationshipsSuffix` | A string appended to the end of table names for storing relationships. Default is '_rels'. |
|
| `relationshipsSuffix` | A string appended to the end of table names for storing relationships. Default is '\_rels'. |
|
||||||
| `versionsSuffix` | A string appended to the end of table names for storing versions. Defaults to '_v'. |
|
| `versionsSuffix` | A string appended to the end of table names for storing versions. Defaults to '\_v'. |
|
||||||
| `beforeSchemaInit` | Drizzle schema hook. Runs before the schema is built. [More Details](#beforeschemainit) |
|
| `beforeSchemaInit` | Drizzle schema hook. Runs before the schema is built. [More Details](#beforeschemainit) |
|
||||||
| `afterSchemaInit` | Drizzle schema hook. Runs after the schema is built. [More Details](#afterschemainit) |
|
| `afterSchemaInit` | Drizzle schema hook. Runs after the schema is built. [More Details](#afterschemainit) |
|
||||||
| `generateSchemaOutputFile` | Override generated schema from `payload generate:db-schema` file path. Defaults to `{CWD}/src/payload-generated.schema.ts` |
|
| `generateSchemaOutputFile` | Override generated schema from `payload generate:db-schema` file path. Defaults to `{CWD}/src/payload-generated.schema.ts` |
|
||||||
@@ -55,11 +55,13 @@ export default buildConfig({
|
|||||||
After Payload is initialized, this adapter will expose the full power of Drizzle to you for use if you need it.
|
After Payload is initialized, this adapter will expose the full power of Drizzle to you for use if you need it.
|
||||||
|
|
||||||
To ensure type-safety, you need to generate Drizzle schema first with:
|
To ensure type-safety, you need to generate Drizzle schema first with:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npx payload generate:db-schema
|
npx payload generate:db-schema
|
||||||
```
|
```
|
||||||
|
|
||||||
Then, you can access Drizzle as follows:
|
Then, you can access Drizzle as follows:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
// Import table from the generated file
|
// Import table from the generated file
|
||||||
import { posts } from './payload-generated-schema'
|
import { posts } from './payload-generated-schema'
|
||||||
@@ -69,7 +71,12 @@ import { eq, sql, and } from '@payloadcms/db-sqlite/drizzle'
|
|||||||
// Drizzle's Querying API: https://orm.drizzle.team/docs/rqb
|
// Drizzle's Querying API: https://orm.drizzle.team/docs/rqb
|
||||||
const posts = await payload.db.drizzle.query.posts.findMany()
|
const posts = await payload.db.drizzle.query.posts.findMany()
|
||||||
// Drizzle's Select API https://orm.drizzle.team/docs/select
|
// Drizzle's Select API https://orm.drizzle.team/docs/select
|
||||||
const result = await payload.db.drizzle.select().from(posts).where(and(eq(posts.id, 50), sql`lower(${posts.title}) = 'example post title'`))
|
const result = await payload.db.drizzle
|
||||||
|
.select()
|
||||||
|
.from(posts)
|
||||||
|
.where(
|
||||||
|
and(eq(posts.id, 50), sql`lower(${posts.title}) = 'example post title'`),
|
||||||
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Tables and relations
|
## Tables and relations
|
||||||
@@ -127,12 +134,17 @@ To quickly generate the Drizzle schema from your database you can use [Drizzle I
|
|||||||
You should get the `schema.ts` file which may look like this:
|
You should get the `schema.ts` file which may look like this:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { sqliteTable, text, uniqueIndex, integer } from 'drizzle-orm/sqlite-core'
|
import {
|
||||||
|
sqliteTable,
|
||||||
|
text,
|
||||||
|
uniqueIndex,
|
||||||
|
integer,
|
||||||
|
} from 'drizzle-orm/sqlite-core'
|
||||||
|
|
||||||
export const users = sqliteTable('users', {
|
export const users = sqliteTable('users', {
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
id: integer('id').primaryKey({ autoIncrement: true }),
|
||||||
fullName: text('full_name'),
|
fullName: text('full_name'),
|
||||||
phone: text('phone', {length: 256}),
|
phone: text('phone', { length: 256 }),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const countries = sqliteTable(
|
export const countries = sqliteTable(
|
||||||
@@ -147,7 +159,6 @@ export const countries = sqliteTable(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
You can import them into your config and append to the schema with the `beforeSchemaInit` hook like this:
|
You can import them into your config and append to the schema with the `beforeSchemaInit` hook like this:
|
||||||
@@ -164,7 +175,7 @@ sqliteAdapter({
|
|||||||
tables: {
|
tables: {
|
||||||
...schema.tables,
|
...schema.tables,
|
||||||
users,
|
users,
|
||||||
countries
|
countries,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -174,7 +185,6 @@ sqliteAdapter({
|
|||||||
|
|
||||||
Make sure Payload doesn't overlap table names with its collections. For example, if you already have a collection with slug "users", you should either change the slug or `dbName` to change the table name for this collection.
|
Make sure Payload doesn't overlap table names with its collections. For example, if you already have a collection with slug "users", you should either change the slug or `dbName` to change the table name for this collection.
|
||||||
|
|
||||||
|
|
||||||
### afterSchemaInit
|
### afterSchemaInit
|
||||||
|
|
||||||
Runs after the Drizzle schema is built. You can use this hook to modify the schema with features that aren't supported by Payload, or if you want to add a column that you don't want to be in the Payload config.
|
Runs after the Drizzle schema is built. You can use this hook to modify the schema with features that aren't supported by Payload, or if you want to add a column that you don't want to be in the Payload config.
|
||||||
@@ -211,10 +221,9 @@ export default buildConfig({
|
|||||||
extraIntegerColumn: integer('extra_integer_column'),
|
extraIntegerColumn: integer('extra_integer_column'),
|
||||||
},
|
},
|
||||||
extraConfig: (table) => ({
|
extraConfig: (table) => ({
|
||||||
country_city_composite_index: index('country_city_composite_index').on(
|
country_city_composite_index: index(
|
||||||
table.country,
|
'country_city_composite_index',
|
||||||
table.city,
|
).on(table.country, table.city),
|
||||||
),
|
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -223,10 +232,10 @@ export default buildConfig({
|
|||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Note for generated schema:
|
### Note for generated schema:
|
||||||
|
|
||||||
Columns and tables, added in schema hooks won't be added to the generated via `payload generate:db-schema` Drizzle schema.
|
Columns and tables, added in schema hooks won't be added to the generated via `payload generate:db-schema` Drizzle schema.
|
||||||
If you want them to be there, you either have to edit this file manually or mutate the internal Payload "raw" SQL schema in the `beforeSchemaInit`:
|
If you want them to be there, you either have to edit this file manually or mutate the internal Payload "raw" SQL schema in the `beforeSchemaInit`:
|
||||||
|
|
||||||
@@ -243,9 +252,9 @@ sqliteAdapter({
|
|||||||
my_id: {
|
my_id: {
|
||||||
name: 'my_id',
|
name: 'my_id',
|
||||||
type: 'integer',
|
type: 'integer',
|
||||||
primaryKey: true
|
primaryKey: true,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a new column to generated by Payload table:
|
// Add a new column to generated by Payload table:
|
||||||
@@ -253,13 +262,13 @@ sqliteAdapter({
|
|||||||
name: 'custom_column',
|
name: 'custom_column',
|
||||||
// Note that Payload SQL doesn't support everything that Drizzle does.
|
// Note that Payload SQL doesn't support everything that Drizzle does.
|
||||||
type: 'integer',
|
type: 'integer',
|
||||||
notNull: true
|
notNull: true,
|
||||||
}
|
}
|
||||||
// Add a new index to generated by Payload table:
|
// Add a new index to generated by Payload table:
|
||||||
adapter.rawTables.posts.indexes.customColumnIdx = {
|
adapter.rawTables.posts.indexes.customColumnIdx = {
|
||||||
name: 'custom_column_idx',
|
name: 'custom_column_idx',
|
||||||
unique: true,
|
unique: true,
|
||||||
on: ['custom_column']
|
on: ['custom_column'],
|
||||||
}
|
}
|
||||||
|
|
||||||
return schema
|
return schema
|
||||||
|
|||||||
@@ -13,13 +13,15 @@ By default, Payload will use transactions for all data changing operations, as l
|
|||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
**Note:**
|
**Note:**
|
||||||
|
|
||||||
MongoDB requires a connection to a replicaset in order to make use of transactions.
|
MongoDB requires a connection to a replicaset in order to make use of transactions.
|
||||||
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
**Note:**
|
**Note:**
|
||||||
|
|
||||||
Transactions in SQLite are disabled by default. You need to pass `transactionOptions: {}` to enable them.
|
Transactions in SQLite are disabled by default. You need to pass `transactionOptions: {}` to enable them.
|
||||||
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
The initial request made to Payload will begin a new transaction and attach it to the `req.transactionID`. If you have a `hook` that interacts with the database, you can opt in to using the same transaction by passing the `req` in the arguments. For example:
|
The initial request made to Payload will begin a new transaction and attach it to the `req.transactionID`. If you have a `hook` that interacts with the database, you can opt in to using the same transaction by passing the `req` in the arguments. For example:
|
||||||
@@ -96,7 +98,7 @@ const standalonePayloadScript = async () => {
|
|||||||
some: 'data',
|
some: 'data',
|
||||||
},
|
},
|
||||||
where: {
|
where: {
|
||||||
slug: { equals: 'my-slug' }
|
slug: { equals: 'my-slug' },
|
||||||
},
|
},
|
||||||
req: { transactionID },
|
req: { transactionID },
|
||||||
})
|
})
|
||||||
@@ -130,7 +132,7 @@ await payload.update({
|
|||||||
some: 'data',
|
some: 'data',
|
||||||
},
|
},
|
||||||
where: {
|
where: {
|
||||||
slug: { equals: 'my-slug' }
|
slug: { equals: 'my-slug' },
|
||||||
},
|
},
|
||||||
disableTransaction: true,
|
disableTransaction: true,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -24,9 +24,8 @@ An email adapter will require at least the following fields:
|
|||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| --------------------------- | -------------------------------------------------------------------------------- |
|
| --------------------------- | -------------------------------------------------------------------------------- |
|
||||||
| **`defaultFromName`** * | The name part of the From field that will be seen on the delivered email |
|
| **`defaultFromName`** \* | The name part of the From field that will be seen on the delivered email |
|
||||||
| **`defaultFromAddress`** * | The email address part of the From field that will be used when delivering email |
|
| **`defaultFromAddress`** \* | The email address part of the From field that will be used when delivering email |
|
||||||
|
|
||||||
|
|
||||||
### Official Email Adapters
|
### Official Email Adapters
|
||||||
|
|
||||||
@@ -97,13 +96,11 @@ export default buildConfig({
|
|||||||
|
|
||||||
You also have the ability to bring your own nodemailer transport. This is an example of using the SendGrid nodemailer transport.
|
You also have the ability to bring your own nodemailer transport. This is an example of using the SendGrid nodemailer transport.
|
||||||
|
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { buildConfig } from 'payload'
|
import { buildConfig } from 'payload'
|
||||||
import { nodemailerAdapter } from '@payloadcms/email-nodemailer'
|
import { nodemailerAdapter } from '@payloadcms/email-nodemailer'
|
||||||
import nodemailerSendgrid from 'nodemailer-sendgrid'
|
import nodemailerSendgrid from 'nodemailer-sendgrid'
|
||||||
|
|
||||||
|
|
||||||
export default buildConfig({
|
export default buildConfig({
|
||||||
email: nodemailerAdapter({
|
email: nodemailerAdapter({
|
||||||
defaultFromAddress: 'info@payloadcms.com',
|
defaultFromAddress: 'info@payloadcms.com',
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ export const MyArrayField: Field = {
|
|||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||||
| **`label`** | Text used as the heading in the [Admin Panel](../admin/overview) or an object with keys for each language. Auto-generated from name if not defined. |
|
| **`label`** | Text used as the heading in the [Admin Panel](../admin/overview) or an object with keys for each language. Auto-generated from name if not defined. |
|
||||||
| **`fields`** * | Array of field types to correspond to each row of the Array. |
|
| **`fields`** \* | Array of field types to correspond to each row of the Array. |
|
||||||
| **`validate`** | Provide a custom validation function that will be executed on both the [Admin Panel](../admin/overview) and the backend. [More](/docs/fields/overview#validation) |
|
| **`validate`** | Provide a custom validation function that will be executed on both the [Admin Panel](../admin/overview) and the backend. [More](/docs/fields/overview#validation) |
|
||||||
| **`minRows`** | A number for the fewest allowed items during validation when a value is present. |
|
| **`minRows`** | A number for the fewest allowed items during validation when a value is present. |
|
||||||
| **`maxRows`** | A number for the most allowed items during validation when a value is present. |
|
| **`maxRows`** | A number for the most allowed items during validation when a value is present. |
|
||||||
@@ -62,7 +62,7 @@ export const MyArrayField: Field = {
|
|||||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
## Admin Options
|
## Admin Options
|
||||||
|
|
||||||
@@ -73,7 +73,8 @@ import type { Field } from 'payload'
|
|||||||
|
|
||||||
export const MyArrayField: Field = {
|
export const MyArrayField: Field = {
|
||||||
// ...
|
// ...
|
||||||
admin: { // highlight-line
|
admin: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -82,7 +83,7 @@ export const MyArrayField: Field = {
|
|||||||
The Array Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
|
The Array Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ------------------------- | ----------------------------------------------------------------------------------- |
|
||||||
| **`initCollapsed`** | Set the initial collapsed state |
|
| **`initCollapsed`** | Set the initial collapsed state |
|
||||||
| **`components.RowLabel`** | React component to be rendered as the label on the array row. [Example](#row-label) |
|
| **`components.RowLabel`** | React component to be rendered as the label on the array row. [Example](#row-label) |
|
||||||
| **`isSortable`** | Disable order sorting by setting this value to `false` |
|
| **`isSortable`** | Disable order sorting by setting this value to `false` |
|
||||||
@@ -145,7 +146,7 @@ export const CustomArrayFieldServer: ArrayFieldServerComponent = ({
|
|||||||
clientField,
|
clientField,
|
||||||
path,
|
path,
|
||||||
schemaPath,
|
schemaPath,
|
||||||
permissions
|
permissions,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<ArrayField
|
<ArrayField
|
||||||
@@ -205,7 +206,7 @@ import React from 'react'
|
|||||||
|
|
||||||
export const CustomArrayFieldLabelClient: ArrayFieldLabelClientComponent = ({
|
export const CustomArrayFieldLabelClient: ArrayFieldLabelClientComponent = ({
|
||||||
field,
|
field,
|
||||||
path
|
path,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<FieldLabel
|
<FieldLabel
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ export const MyBlocksField: Field = {
|
|||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||||
| **`label`** | Text used as the heading in the Admin Panel or an object with keys for each language. Auto-generated from name if not defined. |
|
| **`label`** | Text used as the heading in the Admin Panel or an object with keys for each language. Auto-generated from name if not defined. |
|
||||||
| **`blocks`** * | Array of [block configs](/docs/fields/blocks#block-configs) to be made available to this field. |
|
| **`blocks`** \* | Array of [block configs](/docs/fields/blocks#block-configs) to be made available to this field. |
|
||||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||||
| **`minRows`** | A number for the fewest allowed items during validation when a value is present. |
|
| **`minRows`** | A number for the fewest allowed items during validation when a value is present. |
|
||||||
| **`maxRows`** | A number for the most allowed items during validation when a value is present. |
|
| **`maxRows`** | A number for the most allowed items during validation when a value is present. |
|
||||||
@@ -60,7 +60,7 @@ export const MyBlocksField: Field = {
|
|||||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
## Admin Options
|
## Admin Options
|
||||||
|
|
||||||
@@ -71,7 +71,8 @@ import type { Field } from 'payload'
|
|||||||
|
|
||||||
export const MyBlocksField: Field = {
|
export const MyBlocksField: Field = {
|
||||||
// ...
|
// ...
|
||||||
admin: { // highlight-line
|
admin: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -80,7 +81,7 @@ export const MyBlocksField: Field = {
|
|||||||
The Blocks Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
|
The Blocks Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------- | -------------------------------------------------------------------------- |
|
| ---------------------- | -------------------------------------------------------------------------- |
|
||||||
| **`group`** | Text or localization object used to group this Block in the Blocks Drawer. |
|
| **`group`** | Text or localization object used to group this Block in the Blocks Drawer. |
|
||||||
| **`initCollapsed`** | Set the initial collapsed state |
|
| **`initCollapsed`** | Set the initial collapsed state |
|
||||||
| **`isSortable`** | Disable order sorting by setting this value to `false` |
|
| **`isSortable`** | Disable order sorting by setting this value to `false` |
|
||||||
@@ -98,8 +99,9 @@ This is super handy if you'd like to present your editors with a very deliberate
|
|||||||
For example, if you have a `gallery` block, you might want to actually render the gallery of images directly in your Lexical block. With the `admin.components.Block` property, you can do exactly that!
|
For example, if you have a `gallery` block, you might want to actually render the gallery of images directly in your Lexical block. With the `admin.components.Block` property, you can do exactly that!
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Tip:**
|
**Tip:** If you customize the way your block is rendered in Lexical, you can
|
||||||
If you customize the way your block is rendered in Lexical, you can import utility components to easily edit / remove your block - so that you don't have to build all of this yourself.
|
import utility components to easily edit / remove your block - so that you
|
||||||
|
don't have to build all of this yourself.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
To import these utility components for one of your custom blocks, you can import the following:
|
To import these utility components for one of your custom blocks, you can import the following:
|
||||||
@@ -127,7 +129,6 @@ import {
|
|||||||
// The default "collapsible" UI that is rendered for a regular block
|
// The default "collapsible" UI that is rendered for a regular block
|
||||||
// if you want to re-use it
|
// if you want to re-use it
|
||||||
BlockCollapsible,
|
BlockCollapsible,
|
||||||
|
|
||||||
} from '@payloadcms/richtext-lexical/client'
|
} from '@payloadcms/richtext-lexical/client'
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -136,18 +137,18 @@ import {
|
|||||||
Blocks are defined as separate configs of their own.
|
Blocks are defined as separate configs of their own.
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Tip:**
|
**Tip:** Best practice is to define each block config in its own file, and
|
||||||
Best practice is to define each block config in its own file, and then import them into your
|
then import them into your Blocks field as necessary. This way each block
|
||||||
Blocks field as necessary. This way each block config can be easily shared between fields. For
|
config can be easily shared between fields. For instance, using the "layout
|
||||||
instance, using the "layout builder" example, you might want to feature a few of the same blocks
|
builder" example, you might want to feature a few of the same blocks in a Post
|
||||||
in a Post collection as well as a Page collection. Abstracting into their own files trivializes
|
collection as well as a Page collection. Abstracting into their own files
|
||||||
their reusability.
|
trivializes their reusability.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`slug`** * | Identifier for this block type. Will be saved on each block as the `blockType` property. |
|
| **`slug`** \* | Identifier for this block type. Will be saved on each block as the `blockType` property. |
|
||||||
| **`fields`** * | Array of fields to be stored in this block. |
|
| **`fields`** \* | Array of fields to be stored in this block. |
|
||||||
| **`labels`** | Customize the block labels that appear in the Admin dashboard. Auto-generated from slug if not defined. |
|
| **`labels`** | Customize the block labels that appear in the Admin dashboard. Auto-generated from slug if not defined. |
|
||||||
| **`imageURL`** | Provide a custom image thumbnail to help editors identify this block in the Admin UI. |
|
| **`imageURL`** | Provide a custom image thumbnail to help editors identify this block in the Admin UI. |
|
||||||
| **`imageAltText`** | Customize this block's image thumbnail alt text. |
|
| **`imageAltText`** | Customize this block's image thumbnail alt text. |
|
||||||
@@ -226,10 +227,11 @@ export const CustomBlocksFieldServer: BlocksFieldServerComponent = ({
|
|||||||
clientField,
|
clientField,
|
||||||
path,
|
path,
|
||||||
schemaPath,
|
schemaPath,
|
||||||
permissions
|
permissions,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<BlocksField field={clientField}
|
<BlocksField
|
||||||
|
field={clientField}
|
||||||
path={path}
|
path={path}
|
||||||
schemaPath={schemaPath}
|
schemaPath={schemaPath}
|
||||||
permissions={permissions}
|
permissions={permissions}
|
||||||
@@ -373,9 +375,9 @@ const config = buildConfig({
|
|||||||
**Reminder:**
|
**Reminder:**
|
||||||
Blocks referenced in the `blockReferences` array are treated as isolated from the collection / global config. This has the following implications:
|
Blocks referenced in the `blockReferences` array are treated as isolated from the collection / global config. This has the following implications:
|
||||||
|
|
||||||
1. The block config cannot be modified or extended in the collection config. It will be identical everywhere it's referenced.
|
1. The block config cannot be modified or extended in the collection config. It will be identical everywhere it's referenced.
|
||||||
2. Access control for blocks referenced in the `blockReferences` are run only once - data from the collection will not be available in the block's access control.
|
2. Access control for blocks referenced in the `blockReferences` are run only once - data from the collection will not be available in the block's access control.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## TypeScript
|
## TypeScript
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export const MyCheckboxField: Field = {
|
|||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||||
@@ -46,7 +46,7 @@ export const MyCheckboxField: Field = {
|
|||||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
@@ -104,7 +104,9 @@ import React from 'react'
|
|||||||
import { CheckboxField } from '@payloadcms/ui'
|
import { CheckboxField } from '@payloadcms/ui'
|
||||||
import type { CheckboxFieldClientComponent } from 'payload'
|
import type { CheckboxFieldClientComponent } from 'payload'
|
||||||
|
|
||||||
export const CustomCheckboxFieldClient: CheckboxFieldClientComponent = (props) => {
|
export const CustomCheckboxFieldClient: CheckboxFieldClientComponent = (
|
||||||
|
props,
|
||||||
|
) => {
|
||||||
return <CheckboxField {...props} />
|
return <CheckboxField {...props} />
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -118,10 +120,8 @@ import React from 'react'
|
|||||||
import { FieldLabel } from '@payloadcms/ui'
|
import { FieldLabel } from '@payloadcms/ui'
|
||||||
import type { CheckboxFieldLabelServerComponent } from 'payload'
|
import type { CheckboxFieldLabelServerComponent } from 'payload'
|
||||||
|
|
||||||
export const CustomCheckboxFieldLabelServer: CheckboxFieldLabelServerComponent = ({
|
export const CustomCheckboxFieldLabelServer: CheckboxFieldLabelServerComponent =
|
||||||
clientField,
|
({ clientField, path }) => {
|
||||||
path,
|
|
||||||
}) => {
|
|
||||||
return (
|
return (
|
||||||
<FieldLabel
|
<FieldLabel
|
||||||
label={clientField?.label || clientField?.name}
|
label={clientField?.label || clientField?.name}
|
||||||
@@ -129,7 +129,7 @@ export const CustomCheckboxFieldLabelServer: CheckboxFieldLabelServerComponent =
|
|||||||
required={clientField?.required}
|
required={clientField?.required}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Client Component
|
#### Client Component
|
||||||
@@ -140,17 +140,14 @@ import React from 'react'
|
|||||||
import { FieldLabel } from '@payloadcms/ui'
|
import { FieldLabel } from '@payloadcms/ui'
|
||||||
import type { CheckboxFieldLabelClientComponent } from 'payload'
|
import type { CheckboxFieldLabelClientComponent } from 'payload'
|
||||||
|
|
||||||
export const CustomCheckboxFieldLabelClient: CheckboxFieldLabelClientComponent = ({
|
export const CustomCheckboxFieldLabelClient: CheckboxFieldLabelClientComponent =
|
||||||
label,
|
({ label, path, required }) => {
|
||||||
path,
|
|
||||||
required,
|
|
||||||
}) => {
|
|
||||||
return (
|
return (
|
||||||
<FieldLabel
|
<FieldLabel
|
||||||
label={field?.label || field?.name}
|
label={field?.label || field?.name}
|
||||||
path={path}
|
path={path}
|
||||||
required={field?.required}
|
required={field?.required}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export const MyBlocksField: Field = {
|
|||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||||
@@ -50,7 +50,7 @@ export const MyBlocksField: Field = {
|
|||||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
## Admin Options
|
## Admin Options
|
||||||
|
|
||||||
@@ -61,7 +61,8 @@ import type { Field } from 'payload'
|
|||||||
|
|
||||||
export const MyCodeField: Field = {
|
export const MyCodeField: Field = {
|
||||||
// ...
|
// ...
|
||||||
admin: { // highlight-line
|
admin: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -114,7 +115,12 @@ export const CustomCodeFieldServer: CodeFieldServerComponent = ({
|
|||||||
permissions,
|
permissions,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<CodeField field={clientField} path={path} schemaPath={schemaPath} permissions={permissions} />
|
<CodeField
|
||||||
|
field={clientField}
|
||||||
|
path={path}
|
||||||
|
schemaPath={schemaPath}
|
||||||
|
permissions={permissions}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -176,4 +182,3 @@ export const CustomCodeFieldLabelClient: CodeFieldLabelClientComponent = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -35,12 +35,12 @@ export const MyCollapsibleField: Field = {
|
|||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`label`** * | A label to render within the header of the collapsible component. This can be a string, function or react component. Function/components receive `({ data, path })` as args. |
|
| **`label`** \* | A label to render within the header of the collapsible component. This can be a string, function or react component. Function/components receive `({ data, path })` as args. |
|
||||||
| **`fields`** * | Array of field types to nest within this Collapsible. |
|
| **`fields`** \* | Array of field types to nest within this Collapsible. |
|
||||||
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
||||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
## Admin Options
|
## Admin Options
|
||||||
|
|
||||||
@@ -51,7 +51,8 @@ import type { Field } from 'payload'
|
|||||||
|
|
||||||
export const MyCollapsibleField: Field = {
|
export const MyCollapsibleField: Field = {
|
||||||
// ...
|
// ...
|
||||||
admin: { // highlight-line
|
admin: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export const MyDateField: Field = {
|
|||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||||
@@ -43,11 +43,11 @@ export const MyDateField: Field = {
|
|||||||
| **`required`** | Require this field to have a value. |
|
| **`required`** | Require this field to have a value. |
|
||||||
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
||||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||||
| **`timezone`** * | Set to `true` to enable timezone selection on this field. [More details](#timezones). |
|
| **`timezone`** \* | Set to `true` to enable timezone selection on this field. [More details](#timezones). |
|
||||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
## Admin Options
|
## Admin Options
|
||||||
|
|
||||||
@@ -58,7 +58,8 @@ import type { Field } from 'payload'
|
|||||||
|
|
||||||
export const MyDateField: Field = {
|
export const MyDateField: Field = {
|
||||||
// ...
|
// ...
|
||||||
admin: { // highlight-line
|
admin: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -71,17 +72,17 @@ The Date Field inherits all of the default options from the base [Field Admin Co
|
|||||||
| **`placeholder`** | Placeholder text for the field. |
|
| **`placeholder`** | Placeholder text for the field. |
|
||||||
| **`date`** | Pass options to customize date field appearance. |
|
| **`date`** | Pass options to customize date field appearance. |
|
||||||
| **`date.displayFormat`** | Format date to be shown in field **cell**. |
|
| **`date.displayFormat`** | Format date to be shown in field **cell**. |
|
||||||
| **`date.pickerAppearance`** * | Determines the appearance of the datepicker: `dayAndTime` `timeOnly` `dayOnly` `monthOnly`. |
|
| **`date.pickerAppearance`** \* | Determines the appearance of the datepicker: `dayAndTime` `timeOnly` `dayOnly` `monthOnly`. |
|
||||||
| **`date.monthsToShow`** * | Number of months to display max is 2. Defaults to 1. |
|
| **`date.monthsToShow`** \* | Number of months to display max is 2. Defaults to 1. |
|
||||||
| **`date.minDate`** * | Min date value to allow. |
|
| **`date.minDate`** \* | Min date value to allow. |
|
||||||
| **`date.maxDate`** * | Max date value to allow. |
|
| **`date.maxDate`** \* | Max date value to allow. |
|
||||||
| **`date.minTime`** * | Min time value to allow. |
|
| **`date.minTime`** \* | Min time value to allow. |
|
||||||
| **`date.maxTime`** * | Max date value to allow. |
|
| **`date.maxTime`** \* | Max date value to allow. |
|
||||||
| **`date.overrides`** * | Pass any valid props directly to the [react-datepicker](https://github.com/Hacker0x01/react-datepicker/blob/master/docs/datepicker.md) |
|
| **`date.overrides`** \* | Pass any valid props directly to the [react-datepicker](https://github.com/Hacker0x01/react-datepicker/blob/master/docs/datepicker.md) |
|
||||||
| **`date.timeIntervals`** * | Time intervals to display. Defaults to 30 minutes. |
|
| **`date.timeIntervals`** \* | Time intervals to display. Defaults to 30 minutes. |
|
||||||
| **`date.timeFormat`** * | Determines time format. Defaults to `'h:mm aa'`. |
|
| **`date.timeFormat`** \* | Determines time format. Defaults to `'h:mm aa'`. |
|
||||||
|
|
||||||
_* This property is passed directly to [react-datepicker](https://github.com/Hacker0x01/react-datepicker/blob/master/docs/datepicker.md)._
|
_\* This property is passed directly to [react-datepicker](https://github.com/Hacker0x01/react-datepicker/blob/master/docs/datepicker.md)._
|
||||||
|
|
||||||
### Display Format and Picker Appearance
|
### Display Format and Picker Appearance
|
||||||
|
|
||||||
@@ -243,5 +244,6 @@ You can customise the available list of timezones in the [global admin config](.
|
|||||||
**Good to know:**
|
**Good to know:**
|
||||||
The date itself will be stored in UTC so it's up to you to handle the conversion to the user's timezone when displaying the date in your frontend.
|
The date itself will be stored in UTC so it's up to you to handle the conversion to the user's timezone when displaying the date in your frontend.
|
||||||
|
|
||||||
Dates without a specific time are normalised to 12:00 in the selected timezone.
|
Dates without a specific time are normalised to 12:00 in the selected timezone.
|
||||||
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export const MyEmailField: Field = {
|
|||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||||
@@ -47,7 +47,7 @@ export const MyEmailField: Field = {
|
|||||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
## Admin Options
|
## Admin Options
|
||||||
|
|
||||||
@@ -58,7 +58,8 @@ import type { Field } from 'payload'
|
|||||||
|
|
||||||
export const MyEmailField: Field = {
|
export const MyEmailField: Field = {
|
||||||
// ...
|
// ...
|
||||||
admin: { // highlight-line
|
admin: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -67,7 +68,7 @@ export const MyEmailField: Field = {
|
|||||||
The Email Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
|
The Email Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
|
| ------------------ | ------------------------------------------------------------------------- |
|
||||||
| **`placeholder`** | Set this property to define a placeholder string for the field. |
|
| **`placeholder`** | Set this property to define a placeholder string for the field. |
|
||||||
| **`autoComplete`** | Set this property to a string that will be used for browser autocomplete. |
|
| **`autoComplete`** | Set this property to a string that will be used for browser autocomplete. |
|
||||||
|
|
||||||
@@ -109,7 +110,12 @@ export const CustomEmailFieldServer: EmailFieldServerComponent = ({
|
|||||||
permissions,
|
permissions,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<EmailField field={clientField} path={path} schemaPath={schemaPath} permissions={permissions} />
|
<EmailField
|
||||||
|
field={clientField}
|
||||||
|
path={path}
|
||||||
|
schemaPath={schemaPath}
|
||||||
|
permissions={permissions}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -168,5 +174,6 @@ export const CustomEmailFieldLabelClient: EmailFieldLabelClientComponent = ({
|
|||||||
path={path}
|
path={path}
|
||||||
required={field?.required}
|
required={field?.required}
|
||||||
/>
|
/>
|
||||||
)}
|
)
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ export const MyGroupField: Field = {
|
|||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||||
| **`fields`** * | Array of field types to nest within this Group. |
|
| **`fields`** \* | Array of field types to nest within this Group. |
|
||||||
| **`label`** | Used as a heading in the Admin Panel and to name the generated GraphQL type. |
|
| **`label`** | Used as a heading in the Admin Panel and to name the generated GraphQL type. |
|
||||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||||
@@ -51,7 +51,7 @@ export const MyGroupField: Field = {
|
|||||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
## Admin Options
|
## Admin Options
|
||||||
|
|
||||||
@@ -62,7 +62,8 @@ import type { Field } from 'payload'
|
|||||||
|
|
||||||
export const MyGroupField: Field = {
|
export const MyGroupField: Field = {
|
||||||
// ...
|
// ...
|
||||||
admin: { // highlight-line
|
admin: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -71,7 +72,7 @@ export const MyGroupField: Field = {
|
|||||||
The Group Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
|
The Group Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| **`hideGutter`** | Set this property to `true` to hide this field's gutter within the Admin Panel. The field gutter is rendered as a vertical line and padding, but often if this field is nested within a Group, Block, or Array, you may want to hide the gutter. |
|
| **`hideGutter`** | Set this property to `true` to hide this field's gutter within the Admin Panel. The field gutter is rendered as a vertical line and padding, but often if this field is nested within a Group, Block, or Array, you may want to hide the gutter. |
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ The Join field is useful in scenarios including:
|
|||||||
- Displaying where a document or upload is used in other documents
|
- Displaying where a document or upload is used in other documents
|
||||||
|
|
||||||
<LightDarkImage
|
<LightDarkImage
|
||||||
srcLight="https://payloadcms.com/images/docs/fields/join.png"
|
srcLight="https://payloadcms.com/images/docs/fields/join.png"
|
||||||
srcDark="https://payloadcms.com/images/docs/fields/join-dark.png"
|
srcDark="https://payloadcms.com/images/docs/fields/join-dark.png"
|
||||||
alt="Shows Join field in the Payload Admin Panel"
|
alt="Shows Join field in the Payload Admin Panel"
|
||||||
caption="Admin Panel screenshot of Join field"
|
caption="Admin Panel screenshot of Join field"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
For the Join field to work, you must have an existing [relationship](./relationship) or [upload](./upload) field in the
|
For the Join field to work, you must have an existing [relationship](./relationship) or [upload](./upload) field in the
|
||||||
@@ -59,11 +59,18 @@ are related to the Category are populated for you. This is extremely powerful an
|
|||||||
of relationship types in an easy manner.
|
of relationship types in an easy manner.
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
The Join field is extremely performant and does not add additional query overhead to your API responses until you add depth of 1 or above. It works in all database adapters. In MongoDB, we use **aggregations** to automatically join in related documents, and in relational databases, we use joins.
|
The Join field is extremely performant and does not add additional query
|
||||||
|
overhead to your API responses until you add depth of 1 or above. It works in
|
||||||
|
all database adapters. In MongoDB, we use **aggregations** to automatically
|
||||||
|
join in related documents, and in relational databases, we use joins.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
The Join Field is not supported in [DocumentDB](https://aws.amazon.com/documentdb/) and [Azure Cosmos DB](https://azure.microsoft.com/en-us/products/cosmos-db), as we internally use MongoDB aggregations to query data for that field, which are limited there. This can be changed in the future.
|
The Join Field is not supported in
|
||||||
|
[DocumentDB](https://aws.amazon.com/documentdb/) and [Azure Cosmos
|
||||||
|
DB](https://azure.microsoft.com/en-us/products/cosmos-db), as we internally
|
||||||
|
use MongoDB aggregations to query data for that field, which are limited
|
||||||
|
there. This can be changed in the future.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### Schema advice
|
### Schema advice
|
||||||
@@ -99,7 +106,8 @@ architecture. You might not want to have that `_rels` table, and would prefer to
|
|||||||
table design.
|
table design.
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
With the Join field, you can control your own junction table design, and avoid Payload's automatic _rels table creation.
|
With the Join field, you can control your own junction table design, and avoid
|
||||||
|
Payload's automatic _rels table creation.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
The `join` field can be used in conjunction with _any_ collection - and if you wanted to define your own "junction"
|
The `join` field can be used in conjunction with _any_ collection - and if you wanted to define your own "junction"
|
||||||
@@ -127,9 +135,9 @@ powerful Admin UI.
|
|||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`name`** * | To be used as the property name when retrieved from the database. [More](./overview#field-names) |
|
| **`name`** \* | To be used as the property name when retrieved from the database. [More](./overview#field-names) |
|
||||||
| **`collection`** * | The `slug`s having the relationship field or an array of collection slugs. |
|
| **`collection`** \* | The `slug`s having the relationship field or an array of collection slugs. |
|
||||||
| **`on`** * | The name of the relationship or upload field that relates to the collection document. Use dot notation for nested paths, like 'myGroup.relationName'. If `collection` is an array, this field must exist for all specified collections |
|
| **`on`** \* | The name of the relationship or upload field that relates to the collection document. Use dot notation for nested paths, like 'myGroup.relationName'. If `collection` is an array, this field must exist for all specified collections |
|
||||||
| **`where`** | A `Where` query to hide related documents from appearing. Will be merged with any `where` specified in the request. |
|
| **`where`** | A `Where` query to hide related documents from appearing. Will be merged with any `where` specified in the request. |
|
||||||
| **`maxDepth`** | Default is 1, Sets a maximum population depth for this field, regardless of the remaining depth when this field is reached. [Max Depth](../queries/depth#max-depth). |
|
| **`maxDepth`** | Default is 1, Sets a maximum population depth for this field, regardless of the remaining depth when this field is reached. [Max Depth](../queries/depth#max-depth). |
|
||||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||||
@@ -142,15 +150,14 @@ powerful Admin UI.
|
|||||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema. |
|
| **`typescriptSchema`** | Override field type generation with providing a JSON schema. |
|
||||||
| **`graphQL`** | Custom graphQL configuration for the field. [More details](/docs/graphql/overview#field-complexity) |
|
| **`graphQL`** | Custom graphQL configuration for the field. [More details](/docs/graphql/overview#field-complexity) |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
|
|
||||||
## Admin Config Options
|
## Admin Config Options
|
||||||
|
|
||||||
You can control the user experience of the join field using the `admin` config properties. The following options are supported:
|
You can control the user experience of the join field using the `admin` config properties. The following options are supported:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
|------------------------|---------------------------------------------------------------------------------------------------------------------------|
|
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`defaultColumns`** | Array of field names that correspond to which columns to show in the relationship table. Default is the collection config. |
|
| **`defaultColumns`** | Array of field names that correspond to which columns to show in the relationship table. Default is the collection config. |
|
||||||
| **`allowCreate`** | Set to `false` to remove the controls for making new related documents from this field. |
|
| **`allowCreate`** | Set to `false` to remove the controls for making new related documents from this field. |
|
||||||
| **`components.Label`** | Override the default Label of the Field Component. [More details](./overview#label) |
|
| **`components.Label`** | Override the default Label of the Field Component. [More details](./overview#label) |
|
||||||
@@ -177,7 +184,7 @@ object with:
|
|||||||
// { ... }
|
// { ... }
|
||||||
],
|
],
|
||||||
"hasNextPage": false,
|
"hasNextPage": false,
|
||||||
"totalDocs": 10, // if count: true is passed
|
"totalDocs": 10 // if count: true is passed
|
||||||
}
|
}
|
||||||
// other fields...
|
// other fields...
|
||||||
}
|
}
|
||||||
@@ -208,7 +215,7 @@ object with:
|
|||||||
// { ... }
|
// { ... }
|
||||||
],
|
],
|
||||||
"hasNextPage": false,
|
"hasNextPage": false,
|
||||||
"totalDocs": 10, // if count: true is passed
|
"totalDocs": 10 // if count: true is passed
|
||||||
}
|
}
|
||||||
// other fields...
|
// other fields...
|
||||||
}
|
}
|
||||||
@@ -240,25 +247,27 @@ const result = await payload.find({
|
|||||||
collection: 'categories',
|
collection: 'categories',
|
||||||
where: {
|
where: {
|
||||||
title: {
|
title: {
|
||||||
equals: 'My Category'
|
equals: 'My Category',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
joins: {
|
joins: {
|
||||||
relatedPosts: {
|
relatedPosts: {
|
||||||
limit: 5,
|
limit: 5,
|
||||||
where: {
|
where: {
|
||||||
title: {
|
title: {
|
||||||
equals: 'My Post'
|
equals: 'My Post',
|
||||||
}
|
},
|
||||||
|
},
|
||||||
|
sort: 'title',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
sort: 'title'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
Currently, `Where` query support on joined documents for join fields with an array of `collection` is limited and not supported for fields inside arrays and blocks.
|
Currently, `Where` query support on joined documents for join fields with an
|
||||||
|
array of `collection` is limited and not supported for fields inside arrays
|
||||||
|
and blocks.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
@@ -300,11 +309,7 @@ query {
|
|||||||
relatedPosts(
|
relatedPosts(
|
||||||
sort: "createdAt"
|
sort: "createdAt"
|
||||||
limit: 5
|
limit: 5
|
||||||
where: {
|
where: { author: { equals: "66e3431a3f23e684075aaeb9" } }
|
||||||
author: {
|
|
||||||
equals: "66e3431a3f23e684075aaeb9"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
) {
|
) {
|
||||||
docs {
|
docs {
|
||||||
title
|
title
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export const MyJSONField: Field = {
|
|||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||||
@@ -49,7 +49,7 @@ export const MyJSONField: Field = {
|
|||||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
## Admin Options
|
## Admin Options
|
||||||
|
|
||||||
@@ -60,7 +60,8 @@ import type { Field } from 'payload'
|
|||||||
|
|
||||||
export const MyJSONField: Field = {
|
export const MyJSONField: Field = {
|
||||||
// ...
|
// ...
|
||||||
admin: { // highlight-line
|
admin: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -90,13 +91,13 @@ export const ExampleCollection: CollectionConfig = {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## JSON Schema Validation
|
## JSON Schema Validation
|
||||||
|
|
||||||
Payload JSON fields fully support the [JSON schema](https://json-schema.org/) standard. By providing a schema in your field config, the editor will be guided in the admin UI, getting typeahead for properties and their formats automatically. When the document is saved, the default validation will prevent saving any invalid data in the field according to the schema in your config.
|
Payload JSON fields fully support the [JSON schema](https://json-schema.org/) standard. By providing a schema in your field config, the editor will be guided in the admin UI, getting typeahead for properties and their formats automatically. When the document is saved, the default validation will prevent saving any invalid data in the field according to the schema in your config.
|
||||||
|
|
||||||
If you only provide a URL to a schema, Payload will fetch the desired schema if it is publicly available. If not, it is recommended to add the schema directly to your config or import it from another file so that it can be implemented consistently in your project.
|
If you only provide a URL to a schema, Payload will fetch the desired schema if it is publicly available. If not, it is recommended to add the schema directly to your config or import it from another file so that it can be implemented consistently in your project.
|
||||||
|
|
||||||
|
|
||||||
### Local JSON Schema
|
### Local JSON Schema
|
||||||
|
|
||||||
`collections/ExampleCollection.ts`
|
`collections/ExampleCollection.ts`
|
||||||
@@ -118,11 +119,10 @@ export const ExampleCollection: CollectionConfig = {
|
|||||||
properties: {
|
properties: {
|
||||||
foo: {
|
foo: {
|
||||||
enum: ['bar', 'foobar'],
|
enum: ['bar', 'foobar'],
|
||||||
}
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export const MyNumberField: Field = {
|
|||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||||
| **`min`** | Minimum value accepted. Used in the default `validation` function. |
|
| **`min`** | Minimum value accepted. Used in the default `validation` function. |
|
||||||
| **`max`** | Maximum value accepted. Used in the default `validation` function. |
|
| **`max`** | Maximum value accepted. Used in the default `validation` function. |
|
||||||
@@ -52,7 +52,7 @@ export const MyNumberField: Field = {
|
|||||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
## Admin Options
|
## Admin Options
|
||||||
|
|
||||||
@@ -63,7 +63,8 @@ import type { Field } from 'payload'
|
|||||||
|
|
||||||
export const MyNumberField: Field = {
|
export const MyNumberField: Field = {
|
||||||
// ...
|
// ...
|
||||||
admin: { // highlight-line
|
admin: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -72,7 +73,7 @@ export const MyNumberField: Field = {
|
|||||||
The Number Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
|
The Number Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
|
| ------------------ | --------------------------------------------------------------------------------- |
|
||||||
| **`step`** | Set a value for the number field to increment / decrement using browser controls. |
|
| **`step`** | Set a value for the number field to increment / decrement using browser controls. |
|
||||||
| **`placeholder`** | Set this property to define a placeholder string for the field. |
|
| **`placeholder`** | Set this property to define a placeholder string for the field. |
|
||||||
| **`autoComplete`** | Set this property to a string that will be used for browser autocomplete. |
|
| **`autoComplete`** | Set this property to a string that will be used for browser autocomplete. |
|
||||||
|
|||||||
@@ -19,9 +19,10 @@ import type { CollectionConfig } from 'payload'
|
|||||||
|
|
||||||
export const Page: CollectionConfig = {
|
export const Page: CollectionConfig = {
|
||||||
// ...
|
// ...
|
||||||
fields: [ // highlight-line
|
fields: [
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -41,14 +42,16 @@ export const Page: CollectionConfig = {
|
|||||||
{
|
{
|
||||||
name: 'field',
|
name: 'field',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
// highlight-end
|
// highlight-end
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Reminder:** Each field is an object with at least the `type` property. This matches the field to its corresponding Field Type. [More details](#field-options).
|
**Reminder:** Each field is an object with at least the `type` property. This
|
||||||
|
matches the field to its corresponding Field Type. [More
|
||||||
|
details](#field-options).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
There are three main categories of fields in Payload:
|
There are three main categories of fields in Payload:
|
||||||
@@ -104,7 +107,11 @@ Here are the available Virtual Fields:
|
|||||||
- [Join](../fields/join) - achieves two-way data binding between fields
|
- [Join](../fields/join) - achieves two-way data binding between fields
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Tip:** Don't see a built-in field type that you need? Build it! Using a combination of [Field Validations](#validation) and [Custom Components](../custom-components/overview), you can override the entirety of how a component functions within the [Admin Panel](../admin/overview) to effectively create your own field type.
|
**Tip:** Don't see a built-in field type that you need? Build it! Using a
|
||||||
|
combination of [Field Validations](#validation) and [Custom
|
||||||
|
Components](../custom-components/overview), you can override the entirety of
|
||||||
|
how a component functions within the [Admin Panel](../admin/overview) to
|
||||||
|
effectively create your own field type.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Field Options
|
## Field Options
|
||||||
@@ -123,7 +130,8 @@ export const MyField: Field = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
For a full list of configuration options, see the documentation for each [Field Type](#field-types).
|
For a full list of configuration options, see the documentation for each
|
||||||
|
[Field Type](#field-types).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### Field Names
|
### Field Names
|
||||||
@@ -165,7 +173,7 @@ export const MyField: Field = {
|
|||||||
// highlight-start
|
// highlight-start
|
||||||
hooks: {
|
hooks: {
|
||||||
// ...
|
// ...
|
||||||
}
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -187,7 +195,7 @@ export const MyField: Field = {
|
|||||||
// highlight-start
|
// highlight-start
|
||||||
access: {
|
access: {
|
||||||
// ...
|
// ...
|
||||||
}
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -239,7 +247,8 @@ export const myField: Field = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Tip:** You can use async `defaultValue` functions to fill fields with data from API requests or Local API using `req.payload`.
|
**Tip:** You can use async `defaultValue` functions to fill fields with data
|
||||||
|
from API requests or Local API using `req.payload`.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### Validation
|
### Validation
|
||||||
@@ -254,7 +263,7 @@ import type { Field } from 'payload'
|
|||||||
export const MyField: Field = {
|
export const MyField: Field = {
|
||||||
type: 'text',
|
type: 'text',
|
||||||
name: 'myField',
|
name: 'myField',
|
||||||
validate: value => Boolean(value) || 'This field is required' // highlight-line
|
validate: (value) => Boolean(value) || 'This field is required', // highlight-line
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -263,7 +272,7 @@ Custom validation functions should return either `true` or a `string` representi
|
|||||||
The following arguments are provided to the `validate` function:
|
The following arguments are provided to the `validate` function:
|
||||||
|
|
||||||
| Argument | Description |
|
| Argument | Description |
|
||||||
| --- | --- |
|
| -------- | ------------------------------------------------------------------------------- |
|
||||||
| `value` | The value of the field being validated. |
|
| `value` | The value of the field being validated. |
|
||||||
| `ctx` | An object with additional data and context. [More details](#validation-context) |
|
| `ctx` | An object with additional data and context. [More details](#validation-context) |
|
||||||
|
|
||||||
@@ -287,7 +296,7 @@ export const MyField: Field = {
|
|||||||
The following additional properties are provided in the `ctx` object:
|
The following additional properties are provided in the `ctx` object:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| --- | --- |
|
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| `data` | An object containing the full collection or global document currently being edited. |
|
| `data` | An object containing the full collection or global document currently being edited. |
|
||||||
| `siblingData` | An object containing document data that is scoped to only fields within the same parent of this field. |
|
| `siblingData` | An object containing document data that is scoped to only fields within the same parent of this field. |
|
||||||
| `operation` | Will be `create` or `update` depending on the UI action or API call. |
|
| `operation` | Will be `create` or `update` depending on the UI action or API call. |
|
||||||
@@ -400,7 +409,9 @@ export const MyCollection: CollectionConfig = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Reminder:** The Custom ID Fields can only be of type [`Number`](./number) or [`Text`](./text). Custom ID fields with type `text` must not contain `/` or `.` characters.
|
**Reminder:** The Custom ID Fields can only be of type [`Number`](./number) or
|
||||||
|
[`Text`](./text). Custom ID fields with type `text` must not contain `/` or
|
||||||
|
`.` characters.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Admin Options
|
## Admin Options
|
||||||
@@ -417,18 +428,19 @@ export const CollectionConfig: CollectionConfig = {
|
|||||||
{
|
{
|
||||||
name: 'myField',
|
name: 'myField',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
admin: { // highlight-line
|
admin: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| --- | --- |
|
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`condition`** | Programmatically show / hide fields based on other fields. [More details](#conditional-logic). |
|
| **`condition`** | Programmatically show / hide fields based on other fields. [More details](#conditional-logic). |
|
||||||
| **`components`** | All Field Components can be swapped out for [Custom Components](../custom-components/overview) that you define. |
|
| **`components`** | All Field Components can be swapped out for [Custom Components](../custom-components/overview) that you define. |
|
||||||
| **`description`** | Helper text to display alongside the field to provide more information for the editor. [More details](#description). |
|
| **`description`** | Helper text to display alongside the field to provide more information for the editor. [More details](#description). |
|
||||||
@@ -466,22 +478,24 @@ export const MyCollectionConfig: CollectionConfig = {
|
|||||||
name: 'myField',
|
name: 'myField',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
admin: {
|
admin: {
|
||||||
description: 'Hello, world!' // highlight-line
|
description: 'Hello, world!', // highlight-line
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Reminder:** To replace the Field Description with a [Custom Component](../custom-components/overview), use the `admin.components.Description` property. [More details](#description).
|
**Reminder:** To replace the Field Description with a [Custom
|
||||||
|
Component](../custom-components/overview), use the
|
||||||
|
`admin.components.Description` property. [More details](#description).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
#### Description Functions
|
#### Description Functions
|
||||||
|
|
||||||
Custom Descriptions can also be defined as a function. Description Functions are executed on the server and can be used to format simple descriptions based on the user's current [Locale](../configuration/localization).
|
Custom Descriptions can also be defined as a function. Description Functions are executed on the server and can be used to format simple descriptions based on the user's current [Locale](../configuration/localization).
|
||||||
|
|
||||||
To add a Description Function to a field, set the `admin.description` property to a *function* in your Field Config:
|
To add a Description Function to a field, set the `admin.description` property to a _function_ in your Field Config:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import type { CollectionConfig } from 'payload'
|
import type { CollectionConfig } from 'payload'
|
||||||
@@ -494,21 +508,22 @@ export const MyCollectionConfig: CollectionConfig = {
|
|||||||
name: 'myField',
|
name: 'myField',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
admin: {
|
admin: {
|
||||||
description: ({ t }) => `${t('Hello, world!')}` // highlight-line
|
description: ({ t }) => `${t('Hello, world!')}`, // highlight-line
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
All Description Functions receive the following arguments:
|
All Description Functions receive the following arguments:
|
||||||
|
|
||||||
| Argument | Description |
|
| Argument | Description |
|
||||||
| --- | --- |
|
| -------- | ------------------------------------------------------------------------------------------------ |
|
||||||
| **`t`** | The `t` function used to internationalize the Admin Panel. [More details](../configuration/i18n) |
|
| **`t`** | The `t` function used to internationalize the Admin Panel. [More details](../configuration/i18n) |
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
**Note:** If you need to subscribe to live updates within your form, use a Description Component instead. [More details](#description).
|
**Note:** If you need to subscribe to live updates within your form, use a
|
||||||
|
Description Component instead. [More details](#description).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### Conditional Logic
|
### Conditional Logic
|
||||||
@@ -516,7 +531,7 @@ All Description Functions receive the following arguments:
|
|||||||
You can show and hide fields based on what other fields are doing by utilizing conditional logic on a field by field basis. The `condition` property on a field's admin config accepts a function which takes the following arguments:
|
You can show and hide fields based on what other fields are doing by utilizing conditional logic on a field by field basis. The `condition` property on a field's admin config accepts a function which takes the following arguments:
|
||||||
|
|
||||||
| Argument | Description |
|
| Argument | Description |
|
||||||
| --- | --- |
|
| ----------------- | -------------------------------------------------------------------------------- |
|
||||||
| **`data`** | The entire document's data that is currently being edited. |
|
| **`data`** | The entire document's data that is currently being edited. |
|
||||||
| **`siblingData`** | Only the fields that are direct siblings to the field with the condition. |
|
| **`siblingData`** | Only the fields that are direct siblings to the field with the condition. |
|
||||||
| **`ctx`** | An object containing additional information about the field’s location and user. |
|
| **`ctx`** | An object containing additional information about the field’s location and user. |
|
||||||
@@ -524,7 +539,7 @@ You can show and hide fields based on what other fields are doing by utilizing c
|
|||||||
The `ctx` object:
|
The `ctx` object:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| --- | --- |
|
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| **`blockData`** | The nearest parent block's data. If the field is not inside a block, this will be `undefined`. |
|
| **`blockData`** | The nearest parent block's data. If the field is not inside a block, this will be `undefined`. |
|
||||||
| **`path`** | The full path to the field in the schema, represented as an array of string segments, including array indexes. I.e `['group', 'myArray', '1', 'textField']`. |
|
| **`path`** | The full path to the field in the schema, represented as an array of string segments, including array indexes. I.e `['group', 'myArray', '1', 'textField']`. |
|
||||||
| **`user`** | The currently authenticated user object. |
|
| **`user`** | The currently authenticated user object. |
|
||||||
@@ -581,19 +596,20 @@ export const CollectionConfig: CollectionConfig = {
|
|||||||
{
|
{
|
||||||
// ...
|
// ...
|
||||||
admin: {
|
admin: {
|
||||||
components: { // highlight-line
|
components: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Component | Description |
|
| Component | Description |
|
||||||
| --- | --- |
|
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`Field`** | The form field rendered of the Edit View. [More details](#field). |
|
| **`Field`** | The form field rendered of the Edit View. [More details](#field). |
|
||||||
| **`Cell`** | The table cell rendered of the List View. [More details](#cell). |
|
| **`Cell`** | The table cell rendered of the List View. [More details](#cell). |
|
||||||
| **`Filter`** | The filter component rendered in the List View. [More details](#filter). |
|
| **`Filter`** | The filter component rendered in the List View. [More details](#filter). |
|
||||||
@@ -624,15 +640,18 @@ export const CollectionConfig: CollectionConfig = {
|
|||||||
Field: '/path/to/MyFieldComponent', // highlight-line
|
Field: '/path/to/MyFieldComponent', // highlight-line
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
*For details on how to build Custom Components, see [Building Custom Components](../custom-components/overview#building-custom-components).*
|
_For details on how to build Custom Components, see [Building Custom Components](../custom-components/overview#building-custom-components)._
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
Instead of replacing the entire Field Component, you can alternately replace or slot-in only specific parts by using the [`Label`](#label), [`Error`](#error), [`beforeInput`](#afterinput-and-beforinput), and [`afterInput`](#afterinput-and-beforinput) properties.
|
Instead of replacing the entire Field Component, you can alternately replace
|
||||||
|
or slot-in only specific parts by using the [`Label`](#label),
|
||||||
|
[`Error`](#error), [`beforeInput`](#afterinput-and-beforinput), and
|
||||||
|
[`afterInput`](#afterinput-and-beforinput) properties.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
##### Default Props
|
##### Default Props
|
||||||
@@ -640,7 +659,7 @@ export const CollectionConfig: CollectionConfig = {
|
|||||||
All Field Components receive the following props by default:
|
All Field Components receive the following props by default:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| --- | --- |
|
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`docPreferences`** | An object that contains the [Preferences](../admin/preferences) for the document. |
|
| **`docPreferences`** | An object that contains the [Preferences](../admin/preferences) for the document. |
|
||||||
| **`field`** | In Client Components, this is the sanitized Client Field Config. In Server Components, this is the original Field Config. Server Components will also receive the sanitized field config through the`clientField` prop (see below). |
|
| **`field`** | In Client Components, this is the sanitized Client Field Config. In Server Components, this is the original Field Config. Server Components will also receive the sanitized field config through the`clientField` prop (see below). |
|
||||||
| **`locale`** | The locale of the field. [More details](../configuration/localization). |
|
| **`locale`** | The locale of the field. [More details](../configuration/localization). |
|
||||||
@@ -649,12 +668,12 @@ All Field Components receive the following props by default:
|
|||||||
| **`validate`** | A function that can be used to validate the field. |
|
| **`validate`** | A function that can be used to validate the field. |
|
||||||
| **`path`** | A string representing the direct, dynamic path to the field at runtime, i.e. `myGroup.myArray.0.myField`. |
|
| **`path`** | A string representing the direct, dynamic path to the field at runtime, i.e. `myGroup.myArray.0.myField`. |
|
||||||
| **`schemaPath`** | A string representing the direct, static path to the Field Config, i.e. `posts.myGroup.myArray.myField`. |
|
| **`schemaPath`** | A string representing the direct, static path to the Field Config, i.e. `posts.myGroup.myArray.myField`. |
|
||||||
| **`indexPath`** | A hyphen-notated string representing the path to the field *within the nearest named ancestor field*, i.e. `0-0` |
|
| **`indexPath`** | A hyphen-notated string representing the path to the field _within the nearest named ancestor field_, i.e. `0-0` |
|
||||||
|
|
||||||
In addition to the above props, all Server Components will also receive the following props:
|
In addition to the above props, all Server Components will also receive the following props:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| --- | --- |
|
| ----------------- | ----------------------------------------------------------------------------- |
|
||||||
| **`clientField`** | The serializable Client Field Config. |
|
| **`clientField`** | The serializable Client Field Config. |
|
||||||
| **`field`** | The Field Config. |
|
| **`field`** | The Field Config. |
|
||||||
| **`data`** | The current document being edited. |
|
| **`data`** | The current document being edited. |
|
||||||
@@ -678,17 +697,14 @@ import { useField } from '@payloadcms/ui'
|
|||||||
export const CustomTextField: React.FC = () => {
|
export const CustomTextField: React.FC = () => {
|
||||||
const { value, setValue } = useField() // highlight-line
|
const { value, setValue } = useField() // highlight-line
|
||||||
|
|
||||||
return (
|
return <input onChange={(e) => setValue(e.target.value)} value={value} />
|
||||||
<input
|
|
||||||
onChange={(e) => setValue(e.target.value)}
|
|
||||||
value={value}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
For a complete list of all available React hooks, see the [Payload React Hooks](../admin/react-hooks) documentation. For additional help, see [Building Custom Components](../custom-components/overview#building-custom-components).
|
For a complete list of all available React hooks, see the [Payload React
|
||||||
|
Hooks](../admin/react-hooks) documentation. For additional help, see [Building
|
||||||
|
Custom Components](../custom-components/overview#building-custom-components).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
##### TypeScript#field-component-types
|
##### TypeScript#field-component-types
|
||||||
@@ -730,7 +746,7 @@ export const myField: Field = {
|
|||||||
All Cell Components receive the same [Default Field Component Props](#field), plus the following:
|
All Cell Components receive the same [Default Field Component Props](#field), plus the following:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| --- | --- |
|
| ------------- | --------------------------------------------------------------------- |
|
||||||
| **`link`** | A boolean representing whether this cell should be wrapped in a link. |
|
| **`link`** | A boolean representing whether this cell should be wrapped in a link. |
|
||||||
| **`onClick`** | A function that is called when the cell is clicked. |
|
| **`onClick`** | A function that is called when the cell is clicked. |
|
||||||
|
|
||||||
@@ -815,10 +831,10 @@ export const MyCollectionConfig: CollectionConfig = {
|
|||||||
admin: {
|
admin: {
|
||||||
components: {
|
components: {
|
||||||
Description: '/path/to/MyCustomDescriptionComponent', // highlight-line
|
Description: '/path/to/MyCustomDescriptionComponent', // highlight-line
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -912,7 +928,7 @@ import type {
|
|||||||
|
|
||||||
#### afterInput and beforeInput
|
#### afterInput and beforeInput
|
||||||
|
|
||||||
With these properties you can add multiple components *before* and *after* the input element, as their name suggests. This is useful when you need to render additional elements alongside the field without replacing the entire field component.
|
With these properties you can add multiple components _before_ and _after_ the input element, as their name suggests. This is useful when you need to render additional elements alongside the field without replacing the entire field component.
|
||||||
|
|
||||||
To add components before and after the input element, use the `admin.components.beforeInput` and `admin.components.afterInput` properties in your Field Config:
|
To add components before and after the input element, use the `admin.components.beforeInput` and `admin.components.afterInput` properties in your Field Config:
|
||||||
|
|
||||||
@@ -932,10 +948,10 @@ export const MyCollectionConfig: CollectionConfig = {
|
|||||||
beforeInput: ['/path/to/MyCustomComponent'],
|
beforeInput: ['/path/to/MyCustomComponent'],
|
||||||
afterInput: ['/path/to/MyOtherCustomComponent'],
|
afterInput: ['/path/to/MyOtherCustomComponent'],
|
||||||
// highlight-end
|
// highlight-end
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -27,15 +27,14 @@ export const MyPointField: Field = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Important:**
|
**Important:** The Point Field currently is not supported in SQLite.
|
||||||
The Point Field currently is not supported in SQLite.
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Config
|
## Config
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||||
| **`label`** | Used as a field label in the Admin Panel and to name the generated GraphQL type. |
|
| **`label`** | Used as a field label in the Admin Panel and to name the generated GraphQL type. |
|
||||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. To support location queries, point index defaults to `2dsphere`, to disable the index set to `false`. |
|
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. To support location queries, point index defaults to `2dsphere`, to disable the index set to `false`. |
|
||||||
@@ -52,7 +51,7 @@ export const MyPointField: Field = {
|
|||||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
@@ -81,6 +80,7 @@ In order to do query based on the distance to another point, you can use the `ne
|
|||||||
|
|
||||||
In order to do query based on whether points are within a specific area defined in GeoJSON, you can use the `within` operator.
|
In order to do query based on whether points are within a specific area defined in GeoJSON, you can use the `within` operator.
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const polygon: Point[] = [
|
const polygon: Point[] = [
|
||||||
[9.0, 19.0], // bottom-left
|
[9.0, 19.0], // bottom-left
|
||||||
@@ -91,7 +91,7 @@ const polygon: Point[] = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
payload.find({
|
payload.find({
|
||||||
collection: "points",
|
collection: 'points',
|
||||||
where: {
|
where: {
|
||||||
point: {
|
point: {
|
||||||
within: {
|
within: {
|
||||||
@@ -103,11 +103,11 @@ payload.find({
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Querying - intersects
|
## Querying - intersects
|
||||||
|
|
||||||
In order to do query based on whether points intersect a specific area defined in GeoJSON, you can use the `intersects` operator.
|
In order to do query based on whether points intersect a specific area defined in GeoJSON, you can use the `intersects` operator.
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const polygon: Point[] = [
|
const polygon: Point[] = [
|
||||||
[9.0, 19.0], // bottom-left
|
[9.0, 19.0], // bottom-left
|
||||||
@@ -118,7 +118,7 @@ const polygon: Point[] = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
payload.find({
|
payload.find({
|
||||||
collection: "points",
|
collection: 'points',
|
||||||
where: {
|
where: {
|
||||||
point: {
|
point: {
|
||||||
intersects: {
|
intersects: {
|
||||||
@@ -148,7 +148,12 @@ export const CustomPointFieldServer: PointFieldServerComponent = ({
|
|||||||
permissions,
|
permissions,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<PointField field={clientField} path={path} schemaPath={schemaPath} permissions={permissions} />
|
<PointField
|
||||||
|
field={clientField}
|
||||||
|
path={path}
|
||||||
|
schemaPath={schemaPath}
|
||||||
|
permissions={permissions}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export const MyRadioField: Field = {
|
|||||||
type: 'radio',
|
type: 'radio',
|
||||||
options: [
|
options: [
|
||||||
// ...
|
// ...
|
||||||
]
|
],
|
||||||
// highlight-end
|
// highlight-end
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -34,9 +34,9 @@ export const MyRadioField: Field = {
|
|||||||
## Config Options
|
## Config Options
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||||
| **`options`** * | Array of options to allow the field to store. Can either be an array of strings, or an array of objects containing an `label` string and a `value` string. |
|
| **`options`** \* | Array of options to allow the field to store. Can either be an array of strings, or an array of objects containing an `label` string and a `value` string. |
|
||||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||||
@@ -54,15 +54,16 @@ export const MyRadioField: Field = {
|
|||||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Important:**
|
**Important:**
|
||||||
|
|
||||||
Option values should be strings that do not contain hyphens or special characters due to GraphQL
|
Option values should be strings that do not contain hyphens or special characters due to GraphQL
|
||||||
enumeration naming constraints. Underscores are allowed. If you determine you need your option
|
enumeration naming constraints. Underscores are allowed. If you determine you need your option
|
||||||
values to be non-strings or contain special characters, they will be formatted accordingly before
|
values to be non-strings or contain special characters, they will be formatted accordingly before
|
||||||
being used as a GraphQL enum.
|
being used as a GraphQL enum.
|
||||||
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Admin Options
|
## Admin Options
|
||||||
@@ -74,7 +75,8 @@ import type { Field } from 'payload'
|
|||||||
|
|
||||||
export const MyRadioField: Field = {
|
export const MyRadioField: Field = {
|
||||||
// ...
|
// ...
|
||||||
admin: { // highlight-line
|
admin: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -83,7 +85,7 @@ export const MyRadioField: Field = {
|
|||||||
The Radio Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
|
The Radio Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
|
| ------------ | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`layout`** | Allows for the radio group to be styled as a horizontally or vertically distributed list. The default value is `horizontal`. |
|
| **`layout`** | Allows for the radio group to be styled as a horizontally or vertically distributed list. The default value is `horizontal`. |
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|||||||
@@ -38,9 +38,9 @@ export const MyRelationshipField: Field = {
|
|||||||
## Config Options
|
## Config Options
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||||
| **`relationTo`** * | Provide one or many collection `slug`s to be able to assign relationships to. |
|
| **`relationTo`** \* | Provide one or many collection `slug`s to be able to assign relationships to. |
|
||||||
| **`filterOptions`** | A query to filter which options appear in the UI and validate against. [More](#filtering-relationship-options). |
|
| **`filterOptions`** | A query to filter which options appear in the UI and validate against. [More](#filtering-relationship-options). |
|
||||||
| **`hasMany`** | Boolean when, if set to `true`, allows this field to have many relations instead of only one. |
|
| **`hasMany`** | Boolean when, if set to `true`, allows this field to have many relations instead of only one. |
|
||||||
| **`minRows`** | A number for the fewest allowed items during validation when a value is present. Used with `hasMany`. |
|
| **`minRows`** | A number for the fewest allowed items during validation when a value is present. Used with `hasMany`. |
|
||||||
@@ -63,14 +63,15 @@ export const MyRelationshipField: Field = {
|
|||||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||||
| **`graphQL`** | Custom graphQL configuration for the field. [More details](/docs/graphql/overview#field-complexity) |
|
| **`graphQL`** | Custom graphQL configuration for the field. [More details](/docs/graphql/overview#field-complexity) |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Tip:**
|
**Tip:** The [Depth](../queries/depth) parameter can be used to automatically
|
||||||
The [Depth](../queries/depth) parameter can be used to automatically populate related documents that are returned by the API.
|
populate related documents that are returned by the API.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Admin Options
|
## Admin Options
|
||||||
|
|
||||||
To the appearance and behavior of the Relationship Field in the [Admin Panel](../admin/overview), you can use the `admin` option:
|
To the appearance and behavior of the Relationship Field in the [Admin Panel](../admin/overview), you can use the `admin` option:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
@@ -78,7 +79,8 @@ import type { Field } from 'payload'
|
|||||||
|
|
||||||
export const MyRelationshipField: Field = {
|
export const MyRelationshipField: Field = {
|
||||||
// ...
|
// ...
|
||||||
admin: { // highlight-line
|
admin: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -87,7 +89,7 @@ export const MyRelationshipField: Field = {
|
|||||||
The Relationship Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
|
The Relationship Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`isSortable`** | Set to `true` if you'd like this field to be sortable within the Admin UI using drag and drop (only works when `hasMany` is set to `true`). |
|
| **`isSortable`** | Set to `true` if you'd like this field to be sortable within the Admin UI using drag and drop (only works when `hasMany` is set to `true`). |
|
||||||
| **`allowCreate`** | Set to `false` if you'd like to disable the ability to create new documents from within the relationship field. |
|
| **`allowCreate`** | Set to `false` if you'd like to disable the ability to create new documents from within the relationship field. |
|
||||||
| **`allowEdit`** | Set to `false` if you'd like to disable the ability to edit documents from within the relationship field. |
|
| **`allowEdit`** | Set to `false` if you'd like to disable the ability to edit documents from within the relationship field. |
|
||||||
@@ -185,10 +187,11 @@ You can learn more about writing queries [here](/docs/queries/overview).
|
|||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Note:**
|
**Note:**
|
||||||
|
|
||||||
When a relationship field has both **filterOptions** and a custom
|
When a relationship field has both **filterOptions** and a custom
|
||||||
**validate** function, the api will not validate **filterOptions**
|
**validate** function, the api will not validate **filterOptions**
|
||||||
unless you call the default relationship field validation function imported from
|
unless you call the default relationship field validation function imported from
|
||||||
**payload/shared** in your validate function.
|
**payload/shared** in your validate function.
|
||||||
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Bi-directional relationships
|
## Bi-directional relationships
|
||||||
@@ -367,8 +370,9 @@ Since we are referencing multiple collections, the field you are querying on may
|
|||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Note:**
|
**Note:**
|
||||||
|
|
||||||
You **cannot** query on a field within a polymorphic relationship as you would with a
|
You **cannot** query on a field within a polymorphic relationship as you would with a
|
||||||
non-polymorphic relationship.
|
non-polymorphic relationship.
|
||||||
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Custom Components
|
## Custom Components
|
||||||
@@ -382,12 +386,8 @@ import type React from 'react'
|
|||||||
import { RelationshipField } from '@payloadcms/ui'
|
import { RelationshipField } from '@payloadcms/ui'
|
||||||
import type { RelationshipFieldServerComponent } from 'payload'
|
import type { RelationshipFieldServerComponent } from 'payload'
|
||||||
|
|
||||||
export const CustomRelationshipFieldServer: RelationshipFieldServerComponent = ({
|
export const CustomRelationshipFieldServer: RelationshipFieldServerComponent =
|
||||||
clientField,
|
({ clientField, path, schemaPath, permissions }) => {
|
||||||
path,
|
|
||||||
schemaPath,
|
|
||||||
permissions,
|
|
||||||
}) => {
|
|
||||||
return (
|
return (
|
||||||
<RelationshipField
|
<RelationshipField
|
||||||
field={clientField}
|
field={clientField}
|
||||||
@@ -396,7 +396,7 @@ export const CustomRelationshipFieldServer: RelationshipFieldServerComponent = (
|
|||||||
permissions={permissions}
|
permissions={permissions}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Client Component
|
#### Client Component
|
||||||
@@ -407,7 +407,9 @@ import React from 'react'
|
|||||||
import { RelationshipField } from '@payloadcms/ui'
|
import { RelationshipField } from '@payloadcms/ui'
|
||||||
import type { RelationshipFieldClientComponent } from 'payload'
|
import type { RelationshipFieldClientComponent } from 'payload'
|
||||||
|
|
||||||
export const CustomRelationshipFieldClient: RelationshipFieldClientComponent = (props) => {
|
export const CustomRelationshipFieldClient: RelationshipFieldClientComponent = (
|
||||||
|
props,
|
||||||
|
) => {
|
||||||
return <RelationshipField {...props} />
|
return <RelationshipField {...props} />
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -421,10 +423,8 @@ import React from 'react'
|
|||||||
import { FieldLabel } from '@payloadcms/ui'
|
import { FieldLabel } from '@payloadcms/ui'
|
||||||
import type { RelationshipFieldLabelServerComponent } from 'payload'
|
import type { RelationshipFieldLabelServerComponent } from 'payload'
|
||||||
|
|
||||||
export const CustomRelationshipFieldLabelServer: RelationshipFieldLabelServerComponent = (
|
export const CustomRelationshipFieldLabelServer: RelationshipFieldLabelServerComponent =
|
||||||
clientField,
|
(clientField, path) => {
|
||||||
path
|
|
||||||
) => {
|
|
||||||
return (
|
return (
|
||||||
<FieldLabel
|
<FieldLabel
|
||||||
label={clientField?.label || clientField?.name}
|
label={clientField?.label || clientField?.name}
|
||||||
@@ -432,7 +432,7 @@ export const CustomRelationshipFieldLabelServer: RelationshipFieldLabelServerCom
|
|||||||
required={clientField?.required}
|
required={clientField?.required}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Client Component
|
#### Client Component
|
||||||
@@ -443,10 +443,8 @@ import React from 'react'
|
|||||||
import { FieldLabel } from '@payloadcms/ui'
|
import { FieldLabel } from '@payloadcms/ui'
|
||||||
import type { RelationshipFieldLabelClientComponent } from 'payload'
|
import type { RelationshipFieldLabelClientComponent } from 'payload'
|
||||||
|
|
||||||
export const CustomRelationshipFieldLabelClient: RelationshipFieldLabelClientComponent = ({
|
export const CustomRelationshipFieldLabelClient: RelationshipFieldLabelClientComponent =
|
||||||
field,
|
({ field, path }) => {
|
||||||
path,
|
|
||||||
}) => {
|
|
||||||
return (
|
return (
|
||||||
<FieldLabel
|
<FieldLabel
|
||||||
label={field?.label || field?.name}
|
label={field?.label || field?.name}
|
||||||
@@ -454,5 +452,5 @@ export const CustomRelationshipFieldLabelClient: RelationshipFieldLabelClientCom
|
|||||||
required={field?.required}
|
required={field?.required}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -12,13 +12,18 @@ Consistent with Payload's goal of making you learn as little of Payload as possi
|
|||||||
|
|
||||||
Instead, you can invest your time and effort into learning the underlying open-source tools that will allow you to apply your learnings elsewhere as well.
|
Instead, you can invest your time and effort into learning the underlying open-source tools that will allow you to apply your learnings elsewhere as well.
|
||||||
|
|
||||||
<LightDarkImage alt="Shows a Rich Text field in the Payload Admin Panel" caption="Admin Panel screenshot of a Rich Text field" srcDark="https://payloadcms.com/images/docs/fields/richtext-dark.png" srcLight="https://payloadcms.com/images/docs/fields/richtext.png"/>
|
<LightDarkImage
|
||||||
|
alt="Shows a Rich Text field in the Payload Admin Panel"
|
||||||
|
caption="Admin Panel screenshot of a Rich Text field"
|
||||||
|
srcDark="https://payloadcms.com/images/docs/fields/richtext-dark.png"
|
||||||
|
srcLight="https://payloadcms.com/images/docs/fields/richtext.png"
|
||||||
|
/>
|
||||||
|
|
||||||
## Config Options
|
## Config Options
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| --- | --- |
|
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](./overview#field-names) |
|
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](./overview#field-names) |
|
||||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](./overview#validation) |
|
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](./overview#validation) |
|
||||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](../authentication/overview), include its data in the user JWT. |
|
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](../authentication/overview), include its data in the user JWT. |
|
||||||
@@ -34,7 +39,7 @@ Instead, you can invest your time and effort into learning the underlying open-s
|
|||||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||||
|
|
||||||
** An asterisk denotes that a property is required.*
|
\*_ An asterisk denotes that a property is required._
|
||||||
|
|
||||||
## Admin Options
|
## Admin Options
|
||||||
|
|
||||||
@@ -45,7 +50,8 @@ import type { Field } from 'payload'
|
|||||||
|
|
||||||
export const MyRichTextField: Field = {
|
export const MyRichTextField: Field = {
|
||||||
// ...
|
// ...
|
||||||
admin: { // highlight-line
|
admin: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export const MyRowField: Field = {
|
|||||||
type: 'row',
|
type: 'row',
|
||||||
fields: [
|
fields: [
|
||||||
// ...
|
// ...
|
||||||
]
|
],
|
||||||
// highlight-end
|
// highlight-end
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -34,12 +34,12 @@ export const MyRowField: Field = {
|
|||||||
## Config Options
|
## Config Options
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| --------------- | ------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`fields`** * | Array of field types to nest within this Row. |
|
| **`fields`** \* | Array of field types to nest within this Row. |
|
||||||
| **`admin`** | Admin-specific configuration excluding `description`, `readOnly`, and `hidden`. [More details](./overview#admin-options). |
|
| **`admin`** | Admin-specific configuration excluding `description`, `readOnly`, and `hidden`. [More details](./overview#admin-options). |
|
||||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export const MySelectField: Field = {
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
options: [
|
options: [
|
||||||
// ...
|
// ...
|
||||||
]
|
],
|
||||||
// highlight-end
|
// highlight-end
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -34,9 +34,9 @@ export const MySelectField: Field = {
|
|||||||
## Config Options
|
## Config Options
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||||
| **`options`** * | Array of options to allow the field to store. Can either be an array of strings, or an array of objects containing a `label` string and a `value` string. |
|
| **`options`** \* | Array of options to allow the field to store. Can either be an array of strings, or an array of objects containing a `label` string and a `value` string. |
|
||||||
| **`hasMany`** | Boolean when, if set to `true`, allows this field to have many selections instead of only one. |
|
| **`hasMany`** | Boolean when, if set to `true`, allows this field to have many selections instead of only one. |
|
||||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||||
@@ -57,14 +57,14 @@ export const MySelectField: Field = {
|
|||||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Important:**
|
**Important:** Option values should be strings that do not contain hyphens or
|
||||||
Option values should be strings that do not contain hyphens or special characters due to GraphQL
|
special characters due to GraphQL enumeration naming constraints. Underscores
|
||||||
enumeration naming constraints. Underscores are allowed. If you determine you need your option
|
are allowed. If you determine you need your option values to be non-strings or
|
||||||
values to be non-strings or contain special characters, they will be formatted accordingly before
|
contain special characters, they will be formatted accordingly before being
|
||||||
being used as a GraphQL enum.
|
used as a GraphQL enum.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Admin Options
|
## Admin Options
|
||||||
@@ -76,7 +76,8 @@ import type { Field } from 'payload'
|
|||||||
|
|
||||||
export const MySelectField: Field = {
|
export const MySelectField: Field = {
|
||||||
// ...
|
// ...
|
||||||
admin: { // highlight-line
|
admin: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -85,7 +86,7 @@ export const MySelectField: Field = {
|
|||||||
The Select Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
|
The Select Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`isClearable`** | Set to `true` if you'd like this field to be clearable within the Admin UI. |
|
| **`isClearable`** | Set to `true` if you'd like this field to be clearable within the Admin UI. |
|
||||||
| **`isSortable`** | Set to `true` if you'd like this field to be sortable within the Admin UI using drag and drop. (Only works when `hasMany` is set to `true`) |
|
| **`isSortable`** | Set to `true` if you'd like this field to be sortable within the Admin UI using drag and drop. (Only works when `hasMany` is set to `true`) |
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export const MyTabsField: Field = {
|
|||||||
type: 'tabs',
|
type: 'tabs',
|
||||||
tabs: [
|
tabs: [
|
||||||
// ...
|
// ...
|
||||||
]
|
],
|
||||||
// highlight-end
|
// highlight-end
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -34,8 +34,8 @@ export const MyTabsField: Field = {
|
|||||||
## Config Options
|
## Config Options
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
| ------------- | ----------------------------------------------------------------------- |
|
||||||
| **`tabs`** * | Array of tabs to render within this Tabs field. |
|
| **`tabs`** \* | Array of tabs to render within this Tabs field. |
|
||||||
| **`admin`** | Admin-specific configuration. [More details](./overview#admin-options). |
|
| **`admin`** | Admin-specific configuration. [More details](./overview#admin-options). |
|
||||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||||
|
|
||||||
@@ -47,12 +47,12 @@ Each tab must have either a `name` or `label` and the required `fields` array. Y
|
|||||||
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| **`name`** | Groups field data into an object when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
| **`name`** | Groups field data into an object when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||||
| **`label`** | The label to render on the tab itself. Required when name is undefined, defaults to name converted to words. |
|
| **`label`** | The label to render on the tab itself. Required when name is undefined, defaults to name converted to words. |
|
||||||
| **`fields`** * | The fields to render within this tab. |
|
| **`fields`** \* | The fields to render within this tab. |
|
||||||
| **`description`** | Optionally render a description within this tab to describe the contents of the tab itself. |
|
| **`description`** | Optionally render a description within this tab to describe the contents of the tab itself. |
|
||||||
| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). (`name` must be present) |
|
| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). (`name` must be present) |
|
||||||
| **`virtual`** | Provide `true` to disable field in the database (`name` must be present). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
| **`virtual`** | Provide `true` to disable field in the database (`name` must be present). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export const MyTextField: Field = {
|
|||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||||
| **`minLength`** | Used by the default validation function to ensure values are of a minimum character length. |
|
| **`minLength`** | Used by the default validation function to ensure values are of a minimum character length. |
|
||||||
@@ -52,7 +52,7 @@ export const MyTextField: Field = {
|
|||||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
## Admin Options
|
## Admin Options
|
||||||
|
|
||||||
@@ -63,7 +63,8 @@ import type { Field } from 'payload'
|
|||||||
|
|
||||||
export const MyTextField: Field = {
|
export const MyTextField: Field = {
|
||||||
// ...
|
// ...
|
||||||
admin: { // highlight-line
|
admin: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -72,7 +73,7 @@ export const MyTextField: Field = {
|
|||||||
The Text Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
|
The Text Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| -------------- | ---------------------------------------------------------------------------------------------------------------- |
|
| ------------------ | --------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`placeholder`** | Set this property to define a placeholder string in the text input. |
|
| **`placeholder`** | Set this property to define a placeholder string in the text input. |
|
||||||
| **`autoComplete`** | Set this property to a string that will be used for browser autocomplete. |
|
| **`autoComplete`** | Set this property to a string that will be used for browser autocomplete. |
|
||||||
| **`rtl`** | Override the default text direction of the Admin Panel for this field. Set to `true` to force right-to-left text direction. |
|
| **`rtl`** | Override the default text direction of the Admin Panel for this field. Set to `true` to force right-to-left text direction. |
|
||||||
@@ -114,7 +115,12 @@ export const CustomTextFieldServer: TextFieldServerComponent = ({
|
|||||||
permissions,
|
permissions,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<TextField field={clientField} path={path} schemaPath={schemaPath} permissions={permissions} />
|
<TextField
|
||||||
|
field={clientField}
|
||||||
|
path={path}
|
||||||
|
schemaPath={schemaPath}
|
||||||
|
permissions={permissions}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export const MyTextareaField: Field = {
|
|||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||||
| **`minLength`** | Used by the default validation function to ensure values are of a minimum character length. |
|
| **`minLength`** | Used by the default validation function to ensure values are of a minimum character length. |
|
||||||
@@ -49,7 +49,7 @@ export const MyTextareaField: Field = {
|
|||||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
## Admin Options
|
## Admin Options
|
||||||
|
|
||||||
@@ -60,7 +60,8 @@ import type { Field } from 'payload'
|
|||||||
|
|
||||||
export const MyTextareaField: Field = {
|
export const MyTextareaField: Field = {
|
||||||
// ...
|
// ...
|
||||||
admin: { // highlight-line
|
admin: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -130,7 +131,9 @@ import React from 'react'
|
|||||||
import { TextareaField } from '@payloadcms/ui'
|
import { TextareaField } from '@payloadcms/ui'
|
||||||
import type { TextareaFieldClientComponent } from 'payload'
|
import type { TextareaFieldClientComponent } from 'payload'
|
||||||
|
|
||||||
export const CustomTextareaFieldClient: TextareaFieldClientComponent = (props) => {
|
export const CustomTextareaFieldClient: TextareaFieldClientComponent = (
|
||||||
|
props,
|
||||||
|
) => {
|
||||||
return <TextareaField {...props} />
|
return <TextareaField {...props} />
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -144,10 +147,8 @@ import React from 'react'
|
|||||||
import { FieldLabel } from '@payloadcms/ui'
|
import { FieldLabel } from '@payloadcms/ui'
|
||||||
import type { TextareaFieldLabelServerComponent } from 'payload'
|
import type { TextareaFieldLabelServerComponent } from 'payload'
|
||||||
|
|
||||||
export const CustomTextareaFieldLabelServer: TextareaFieldLabelServerComponent = ({
|
export const CustomTextareaFieldLabelServer: TextareaFieldLabelServerComponent =
|
||||||
clientField,
|
({ clientField, path }) => {
|
||||||
path,
|
|
||||||
}) => {
|
|
||||||
return (
|
return (
|
||||||
<FieldLabel
|
<FieldLabel
|
||||||
label={clientField?.label || clientField?.name}
|
label={clientField?.label || clientField?.name}
|
||||||
@@ -155,7 +156,7 @@ export const CustomTextareaFieldLabelServer: TextareaFieldLabelServerComponent =
|
|||||||
required={clientField?.required}
|
required={clientField?.required}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Client Component
|
#### Client Component
|
||||||
@@ -166,10 +167,8 @@ import React from 'react'
|
|||||||
import { FieldLabel } from '@payloadcms/ui'
|
import { FieldLabel } from '@payloadcms/ui'
|
||||||
import type { TextareaFieldLabelClientComponent } from 'payload'
|
import type { TextareaFieldLabelClientComponent } from 'payload'
|
||||||
|
|
||||||
export const CustomTextareaFieldLabelClient: TextareaFieldLabelClientComponent = ({
|
export const CustomTextareaFieldLabelClient: TextareaFieldLabelClientComponent =
|
||||||
field,
|
({ field, path }) => {
|
||||||
path,
|
|
||||||
}) => {
|
|
||||||
return (
|
return (
|
||||||
<FieldLabel
|
<FieldLabel
|
||||||
label={field?.label || field?.name}
|
label={field?.label || field?.name}
|
||||||
@@ -177,5 +176,5 @@ export const CustomTextareaFieldLabelClient: TextareaFieldLabelClientComponent =
|
|||||||
required={field?.required}
|
required={field?.required}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -29,15 +29,15 @@ export const MyUIField: Field = {
|
|||||||
## Config Options
|
## Config Options
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
| ------------------------------- | ---------------------------------------------------------------------------------------------------------- |
|
||||||
| **`name`** * | A unique identifier for this field. |
|
| **`name`** \* | A unique identifier for this field. |
|
||||||
| **`label`** | Human-readable label for this UI field. |
|
| **`label`** | Human-readable label for this UI field. |
|
||||||
| **`admin.components.Field`** * | React component to be rendered for this field within the Edit View. [More](./overview#field) |
|
| **`admin.components.Field`** \* | React component to be rendered for this field within the Edit View. [More](./overview#field) |
|
||||||
| **`admin.components.Cell`** | React component to be rendered as a Cell within collection List views. [More](./overview#cell) |
|
| **`admin.components.Cell`** | React component to be rendered as a Cell within collection List views. [More](./overview#cell) |
|
||||||
| **`admin.disableListColumn`** | Set `disableListColumn` to `true` to prevent the UI field from appearing in the list view column selector. |
|
| **`admin.disableListColumn`** | Set `disableListColumn` to `true` to prevent the UI field from appearing in the list view column selector. |
|
||||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
|
|||||||
@@ -16,10 +16,10 @@ Upload fields are useful for a variety of use cases, such as:
|
|||||||
- To give a layout building block the ability to feature a background image
|
- To give a layout building block the ability to feature a background image
|
||||||
|
|
||||||
<LightDarkImage
|
<LightDarkImage
|
||||||
srcLight="https://payloadcms.com/images/docs/fields/upload.png"
|
srcLight="https://payloadcms.com/images/docs/fields/upload.png"
|
||||||
srcDark="https://payloadcms.com/images/docs/fields/upload-dark.png"
|
srcDark="https://payloadcms.com/images/docs/fields/upload-dark.png"
|
||||||
alt="Shows an upload field in the Payload Admin Panel"
|
alt="Shows an upload field in the Payload Admin Panel"
|
||||||
caption="Admin Panel screenshot of an Upload field"
|
caption="Admin Panel screenshot of an Upload field"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
To create an Upload Field, set the `type` to `upload` in your [Field Config](./overview):
|
To create an Upload Field, set the `type` to `upload` in your [Field Config](./overview):
|
||||||
@@ -37,16 +37,17 @@ export const MyUploadField: Field = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Important:**
|
**Important:** To use the Upload Field, you must have a
|
||||||
To use the Upload Field, you must have a [Collection](../configuration/collections) configured to allow [Uploads](../upload/overview).
|
[Collection](../configuration/collections) configured to allow
|
||||||
|
[Uploads](../upload/overview).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Config Options
|
## Config Options
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
|------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||||
| **`relationTo`** * | Provide a single collection `slug` to allow this field to accept a relation to. **Note: the related collection must be configured to support Uploads.** |
|
| **`relationTo`** \* | Provide a single collection `slug` to allow this field to accept a relation to. **Note: the related collection must be configured to support Uploads.** |
|
||||||
| **`filterOptions`** | A query to filter which options appear in the UI and validate against. [More](#filtering-upload-options). |
|
| **`filterOptions`** | A query to filter which options appear in the UI and validate against. [More](#filtering-upload-options). |
|
||||||
| **`hasMany`** | Boolean which, if set to true, allows this field to have many relations instead of only one. |
|
| **`hasMany`** | Boolean which, if set to true, allows this field to have many relations instead of only one. |
|
||||||
| **`minRows`** | A number for the fewest allowed items during validation when a value is present. Used with hasMany. |
|
| **`minRows`** | A number for the fewest allowed items during validation when a value is present. Used with hasMany. |
|
||||||
@@ -70,7 +71,7 @@ export const MyUploadField: Field = {
|
|||||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||||
| **`graphQL`** | Custom graphQL configuration for the field. [More details](/docs/graphql/overview#field-complexity) |
|
| **`graphQL`** | Custom graphQL configuration for the field. [More details](/docs/graphql/overview#field-complexity) |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
@@ -102,7 +103,7 @@ prevent all, or a `Where` query. When using a function, it will be
|
|||||||
called with an argument object with the following properties:
|
called with an argument object with the following properties:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
|---------------|-------------------------------------------------------------------------------------------------------|
|
| ------------- | ----------------------------------------------------------------------------------------------------- |
|
||||||
| `relationTo` | The collection `slug` to filter against, limited to this field's `relationTo` property |
|
| `relationTo` | The collection `slug` to filter against, limited to this field's `relationTo` property |
|
||||||
| `data` | An object containing the full collection or global document currently being edited |
|
| `data` | An object containing the full collection or global document currently being edited |
|
||||||
| `siblingData` | An object containing document data that is scoped to only fields within the same parent of this field |
|
| `siblingData` | An object containing document data that is scoped to only fields within the same parent of this field |
|
||||||
@@ -128,10 +129,11 @@ You can learn more about writing queries [here](/docs/queries/overview).
|
|||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Note:**
|
**Note:**
|
||||||
|
|
||||||
When an upload field has both **filterOptions** and a custom
|
When an upload field has both **filterOptions** and a custom
|
||||||
**validate** function, the api will not validate **filterOptions**
|
**validate** function, the api will not validate **filterOptions**
|
||||||
unless you call the default upload field validation function imported from
|
unless you call the default upload field validation function imported from
|
||||||
**payload/shared** in your validate function.
|
**payload/shared** in your validate function.
|
||||||
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Bi-directional relationships
|
## Bi-directional relationships
|
||||||
|
|||||||
@@ -53,8 +53,8 @@ Everything Payload does (create, read, update, delete, login, logout, etc.) is e
|
|||||||
- [GraphQL](#graphql-api) - A full GraphQL API with a GraphQL Playground
|
- [GraphQL](#graphql-api) - A full GraphQL API with a GraphQL Playground
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Note:**
|
**Note:** All of these APIs share the exact same query language. [More
|
||||||
All of these APIs share the exact same query language. [More details](../queries/overview).
|
details](../queries/overview).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### Local API
|
### Local API
|
||||||
@@ -127,8 +127,9 @@ You can use any GraphQL client with Payload's GraphQL endpoint. Here are a few p
|
|||||||
Payload is abstracted into a set of dedicated packages to keep the core `payload` package as lightweight as possible. This allows you to only install the parts of Payload based on your unique project requirements.
|
Payload is abstracted into a set of dedicated packages to keep the core `payload` package as lightweight as possible. This allows you to only install the parts of Payload based on your unique project requirements.
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Important:**
|
**Important:** Version numbers of all official Payload packages are always
|
||||||
Version numbers of all official Payload packages are always published in sync. You should make sure that you always use matching versions for all official Payload packages.
|
published in sync. You should make sure that you always use matching versions
|
||||||
|
for all official Payload packages.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
`payload`
|
`payload`
|
||||||
@@ -166,6 +167,6 @@ You can choose which Database Adapter you'd like to use for your project, and no
|
|||||||
Payload's Rich Text functionality is abstracted into separate packages and if you want to enable Rich Text in your project, you'll need to install one of these packages. We recommend Lexical for all new projects, and this is where Payload will focus its efforts on from this point, but Slate is still supported if you have already built with it.
|
Payload's Rich Text functionality is abstracted into separate packages and if you want to enable Rich Text in your project, you'll need to install one of these packages. We recommend Lexical for all new projects, and this is where Payload will focus its efforts on from this point, but Slate is still supported if you have already built with it.
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
**Note:**
|
**Note:** Rich Text is entirely optional and you may not need it for your
|
||||||
Rich Text is entirely optional and you may not need it for your project.
|
project.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ Payload requires the following software:
|
|||||||
- Any [compatible database](/docs/database/overview) (MongoDB, Postgres or SQLite)
|
- Any [compatible database](/docs/database/overview) (MongoDB, Postgres or SQLite)
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Important:**
|
**Important:** Before proceeding any further, please ensure that you have the
|
||||||
Before proceeding any further, please ensure that you have the above requirements met.
|
above requirements met.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Quickstart with create-payload-app
|
## Quickstart with create-payload-app
|
||||||
@@ -48,8 +48,8 @@ pnpm i payload @payloadcms/next @payloadcms/richtext-lexical sharp graphql
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Note:**
|
**Note:** Swap out `pnpm` for your package manager. If you are using npm, you
|
||||||
Swap out `pnpm` for your package manager. If you are using npm, you might need to install using legacy peer deps: `npm i --legacy-peer-deps`.
|
might need to install using legacy peer deps: `npm i --legacy-peer-deps`.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
Next, install a [Database Adapter](/docs/database/overview). Payload requires a Database Adapter to establish a database connection. Payload works with all types of databases, but the most common are MongoDB and Postgres.
|
Next, install a [Database Adapter](/docs/database/overview). Payload requires a Database Adapter to establish a database connection. Payload works with all types of databases, but the most common are MongoDB and Postgres.
|
||||||
@@ -57,6 +57,7 @@ Next, install a [Database Adapter](/docs/database/overview). Payload requires a
|
|||||||
To install a Database Adapter, you can run **one** of the following commands:
|
To install a Database Adapter, you can run **one** of the following commands:
|
||||||
|
|
||||||
- To install the [MongoDB Adapter](../database/mongodb), run:
|
- To install the [MongoDB Adapter](../database/mongodb), run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm i @payloadcms/db-mongodb
|
pnpm i @payloadcms/db-mongodb
|
||||||
```
|
```
|
||||||
@@ -67,13 +68,14 @@ To install a Database Adapter, you can run **one** of the following commands:
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Note:**
|
**Note:** New [Database Adapters](/docs/database/overview) are becoming
|
||||||
New [Database Adapters](/docs/database/overview) are becoming available every day. Check the docs for the most up-to-date list of what's available.
|
available every day. Check the docs for the most up-to-date list of what's
|
||||||
|
available.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
#### 2. Copy Payload files into your Next.js app folder
|
#### 2. Copy Payload files into your Next.js app folder
|
||||||
|
|
||||||
Payload installs directly in your Next.js `/app` folder, and you'll need to place some files into that folder for Payload to run. You can copy these files from the [Blank Template](https://github.com/payloadcms/payload/tree/main/templates/blank/src/app/(payload)) on GitHub. Once you have the required Payload files in place in your `/app` folder, you should have something like this:
|
Payload installs directly in your Next.js `/app` folder, and you'll need to place some files into that folder for Payload to run. You can copy these files from the [Blank Template](<https://github.com/payloadcms/payload/tree/main/templates/blank/src/app/(payload)>) on GitHub. Once you have the required Payload files in place in your `/app` folder, you should have something like this:
|
||||||
|
|
||||||
```plaintext
|
```plaintext
|
||||||
app/
|
app/
|
||||||
@@ -86,7 +88,10 @@ app/
|
|||||||
_For an exact reference of the `(payload)` directory, see [Project Structure](../admin/overview#project-structure)._
|
_For an exact reference of the `(payload)` directory, see [Project Structure](../admin/overview#project-structure)._
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
You may need to copy all of your existing frontend files, including your existing root layout, into its own newly created [Route Group](https://nextjs.org/docs/app/building-your-application/routing/route-groups), i.e. `(my-app)`.
|
You may need to copy all of your existing frontend files, including your
|
||||||
|
existing root layout, into its own newly created [Route
|
||||||
|
Group](https://nextjs.org/docs/app/building-your-application/routing/route-groups),
|
||||||
|
i.e. `(my-app)`.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
The files that Payload needs to have in your `/app` folder do not regenerate, and will never change. Once you slot them in, you never have to revisit them. They are not meant to be edited and simply import Payload dependencies from `@payloadcms/next` for the REST / GraphQL API and Admin Panel.
|
The files that Payload needs to have in your `/app` folder do not regenerate, and will never change. Once you slot them in, you never have to revisit them. They are not meant to be edited and simply import Payload dependencies from `@payloadcms/next` for the REST / GraphQL API and Admin Panel.
|
||||||
@@ -106,8 +111,8 @@ import { withPayload } from '@payloadcms/next/withPayload'
|
|||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
// Your Next.js config here
|
// Your Next.js config here
|
||||||
experimental: {
|
experimental: {
|
||||||
reactCompiler: false
|
reactCompiler: false,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure you wrap your `nextConfig`
|
// Make sure you wrap your `nextConfig`
|
||||||
@@ -116,8 +121,8 @@ export default withPayload(nextConfig) // highlight-line
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Important:**
|
**Important:** Payload is a fully ESM project, and that means the
|
||||||
Payload is a fully ESM project, and that means the `withPayload` function is an ECMAScript module.
|
`withPayload` function is an ECMAScript module.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
To import the Payload Plugin, you need to make sure your `next.config` file is set up to use ESM.
|
To import the Payload Plugin, you need to make sure your `next.config` file is set up to use ESM.
|
||||||
@@ -171,11 +176,9 @@ Once you have a Payload Config, update your `tsconfig` to include a `path` that
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"paths": {
|
"paths": {
|
||||||
"@payload-config": [
|
"@payload-config": ["./payload.config.ts"]
|
||||||
"./payload.config.ts"
|
}
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,10 @@ Payload has restored a little love back into the dev / marketer equation with fe
|
|||||||
If you're building a website and your frontend is on Next.js, then Payload is a no-brainer.
|
If you're building a website and your frontend is on Next.js, then Payload is a no-brainer.
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
Instead of going out and signing up for a SaaS vendor that makes it so you have to manage two completely separate concerns, with little to no native connection back and forth, just install Payload in your existing Next.js repo and instantly get a full CMS.
|
Instead of going out and signing up for a SaaS vendor that makes it so you
|
||||||
|
have to manage two completely separate concerns, with little to no native
|
||||||
|
connection back and forth, just install Payload in your existing Next.js repo
|
||||||
|
and instantly get a full CMS.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
Get started with Payload as a CMS using our official Website template:
|
Get started with Payload as a CMS using our official Website template:
|
||||||
|
|||||||
@@ -115,10 +115,10 @@ import { GraphQL } from '@payloadcms/graphql/types'
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
For queries, mutations and handlers make sure you use the `GraphQL` and `payload` instances provided via arguments.
|
For queries, mutations and handlers make sure you use the `GraphQL` and
|
||||||
|
`payload` instances provided via arguments.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
|
|
||||||
**`buildPaginatedListType`**
|
**`buildPaginatedListType`**
|
||||||
|
|
||||||
This is a utility function that allows you to build a new GraphQL type for a paginated result similar to the Payload's generated schema.
|
This is a utility function that allows you to build a new GraphQL type for a paginated result similar to the Payload's generated schema.
|
||||||
@@ -134,7 +134,10 @@ export const getMyPosts = (GraphQL, payload) => {
|
|||||||
args: {},
|
args: {},
|
||||||
resolve: Resolver,
|
resolve: Resolver,
|
||||||
// The name of your new type has to be unique
|
// The name of your new type has to be unique
|
||||||
type: buildPaginatedListType('AuthorPosts', payload.collections['posts'].graphQL?.type),
|
type: buildPaginatedListType(
|
||||||
|
'AuthorPosts',
|
||||||
|
payload.collections['posts'].graphQL?.type,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -67,7 +67,8 @@ The above example outputs all your definitions to a file relative from your payl
|
|||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Important**
|
**Important**
|
||||||
|
|
||||||
Payload needs to be able to find your config to generate your GraphQL schema.
|
Payload needs to be able to find your config to generate your GraphQL schema.
|
||||||
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
Payload will automatically try and locate your config, but might not always be able to find it. For example, if you are working in a `/src` directory or similar, you need to tell Payload where to find your config manually by using an environment variable.
|
Payload will automatically try and locate your config, but might not always be able to find it. For example, if you are working in a `/src` directory or similar, you need to tell Payload where to find your config manually by using an environment variable.
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export const PublicUser: CollectionConfig = {
|
|||||||
**Payload will automatically open up the following queries:**
|
**Payload will automatically open up the following queries:**
|
||||||
|
|
||||||
| Query Name | Operation |
|
| Query Name | Operation |
|
||||||
| ------------------- | ------------------- |
|
| ------------------ | ------------------- |
|
||||||
| `PublicUser` | `findByID` |
|
| `PublicUser` | `findByID` |
|
||||||
| `PublicUsers` | `find` |
|
| `PublicUsers` | `find` |
|
||||||
| `countPublicUsers` | `count` |
|
| `countPublicUsers` | `count` |
|
||||||
@@ -53,7 +53,7 @@ export const PublicUser: CollectionConfig = {
|
|||||||
**And the following mutations:**
|
**And the following mutations:**
|
||||||
|
|
||||||
| Query Name | Operation |
|
| Query Name | Operation |
|
||||||
| ------------------------------ | ------------------------------- |
|
| -------------------------- | ------------------------------- |
|
||||||
| `createPublicUser` | `create` |
|
| `createPublicUser` | `create` |
|
||||||
| `updatePublicUser` | `update` |
|
| `updatePublicUser` | `update` |
|
||||||
| `deletePublicUser` | `delete` |
|
| `deletePublicUser` | `delete` |
|
||||||
@@ -83,13 +83,13 @@ const Header: GlobalConfig = {
|
|||||||
**Payload will open the following query:**
|
**Payload will open the following query:**
|
||||||
|
|
||||||
| Query Name | Operation |
|
| Query Name | Operation |
|
||||||
| ------------ | --------- |
|
| ---------- | --------- |
|
||||||
| `Header` | `findOne` |
|
| `Header` | `findOne` |
|
||||||
|
|
||||||
**And the following mutation:**
|
**And the following mutation:**
|
||||||
|
|
||||||
| Query Name | Operation |
|
| Query Name | Operation |
|
||||||
| ------------------ | --------- |
|
| -------------- | --------- |
|
||||||
| `updateHeader` | `update` |
|
| `updateHeader` | `update` |
|
||||||
|
|
||||||
## Preferences
|
## Preferences
|
||||||
@@ -99,13 +99,13 @@ User [preferences](../admin/preferences) for the [Admin Panel](../admin/overview
|
|||||||
**Payload will open the following query:**
|
**Payload will open the following query:**
|
||||||
|
|
||||||
| Query Name | Operation |
|
| Query Name | Operation |
|
||||||
| ---------------- | --------- |
|
| ------------ | --------- |
|
||||||
| `Preference` | `findOne` |
|
| `Preference` | `findOne` |
|
||||||
|
|
||||||
**And the following mutations:**
|
**And the following mutations:**
|
||||||
|
|
||||||
| Query Name | Operation |
|
| Query Name | Operation |
|
||||||
| ---------------------- | --------- |
|
| ------------------ | --------- |
|
||||||
| `updatePreference` | `update` |
|
| `updatePreference` | `update` |
|
||||||
| `deletePreference` | `delete` |
|
| `deletePreference` | `delete` |
|
||||||
|
|
||||||
@@ -118,11 +118,12 @@ You can even log in using the `login[collection-singular-label-here]` mutation t
|
|||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Tip:**
|
**Tip:**
|
||||||
|
|
||||||
To see more regarding how the above queries and mutations are used, visit your GraphQL playground
|
To see more regarding how the above queries and mutations are used, visit your GraphQL playground
|
||||||
(by default at
|
(by default at
|
||||||
[`${SERVER_URL}/api/graphql-playground`](http://localhost:3000/api/graphql-playground))
|
[`${SERVER_URL}/api/graphql-playground`](http://localhost:3000/api/graphql-playground))
|
||||||
while your server is running. There, you can use the "Schema" and "Docs" buttons on the right to
|
while your server is running. There, you can use the "Schema" and "Docs" buttons on the right to
|
||||||
see a ton of detail about how GraphQL operates within Payload.
|
see a ton of detail about how GraphQL operates within Payload.
|
||||||
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Custom Validation Rules
|
## Custom Validation Rules
|
||||||
@@ -136,9 +137,7 @@ import { buildConfig } from 'payload'
|
|||||||
export default buildConfig({
|
export default buildConfig({
|
||||||
// ...
|
// ...
|
||||||
graphQL: {
|
graphQL: {
|
||||||
validationRules: (args) => [
|
validationRules: (args) => [NoProductionIntrospection],
|
||||||
NoProductionIntrospection
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
// ...
|
// ...
|
||||||
})
|
})
|
||||||
@@ -150,12 +149,12 @@ const NoProductionIntrospection: GraphQL.ValidationRule = (context) => ({
|
|||||||
context.reportError(
|
context.reportError(
|
||||||
new GraphQL.GraphQLError(
|
new GraphQL.GraphQLError(
|
||||||
'GraphQL introspection is not allowed, but the query contained __schema or __type',
|
'GraphQL introspection is not allowed, but the query contained __schema or __type',
|
||||||
{ nodes: [node] }
|
{ nodes: [node] },
|
||||||
|
),
|
||||||
)
|
)
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -174,6 +173,6 @@ const fieldWithComplexity = {
|
|||||||
relationship: 'authors',
|
relationship: 'authors',
|
||||||
graphQL: {
|
graphQL: {
|
||||||
complexity: 100, // highlight-line
|
complexity: 100, // highlight-line
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -11,19 +11,20 @@ Collection Hooks are [Hooks](./overview) that run on Documents within a specific
|
|||||||
To add Hooks to a Collection, use the `hooks` property in your [Collection Config](../configuration/collections):
|
To add Hooks to a Collection, use the `hooks` property in your [Collection Config](../configuration/collections):
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import type { CollectionConfig } from 'payload';
|
import type { CollectionConfig } from 'payload'
|
||||||
|
|
||||||
export const CollectionWithHooks: CollectionConfig = {
|
export const CollectionWithHooks: CollectionConfig = {
|
||||||
// ...
|
// ...
|
||||||
hooks: { // highlight-line
|
hooks: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
**Tip:**
|
**Tip:** You can also set hooks on the field-level to isolate hook logic to
|
||||||
You can also set hooks on the field-level to isolate hook logic to specific fields. [More details](./fields).
|
specific fields. [More details](./fields).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Config Options
|
## Config Options
|
||||||
@@ -83,7 +84,7 @@ const beforeOperationHook: CollectionBeforeOperationHook = async ({
|
|||||||
The following arguments are provided to the `beforeOperation` hook:
|
The following arguments are provided to the `beforeOperation` hook:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
||||||
| **`context`** | Custom context passed between Hooks. [More details](./context). |
|
| **`context`** | Custom context passed between Hooks. [More details](./context). |
|
||||||
| **`operation`** | The name of the operation that this hook is running within. |
|
| **`operation`** | The name of the operation that this hook is running within. |
|
||||||
@@ -102,9 +103,7 @@ Please do note that this does not run before client-side validation. If you rend
|
|||||||
```ts
|
```ts
|
||||||
import type { CollectionBeforeValidateHook } from 'payload'
|
import type { CollectionBeforeValidateHook } from 'payload'
|
||||||
|
|
||||||
const beforeValidateHook: CollectionBeforeValidateHook = async ({
|
const beforeValidateHook: CollectionBeforeValidateHook = async ({ data }) => {
|
||||||
data,
|
|
||||||
}) => {
|
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -112,7 +111,7 @@ const beforeValidateHook: CollectionBeforeValidateHook = async ({
|
|||||||
The following arguments are provided to the `beforeValidate` hook:
|
The following arguments are provided to the `beforeValidate` hook:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
||||||
| **`context`** | Custom context passed between Hooks. [More details](./context). |
|
| **`context`** | Custom context passed between Hooks. [More details](./context). |
|
||||||
| **`data`** | The incoming data passed through the operation. |
|
| **`data`** | The incoming data passed through the operation. |
|
||||||
@@ -127,9 +126,7 @@ Immediately following validation, `beforeChange` hooks will run within `create`
|
|||||||
```ts
|
```ts
|
||||||
import type { CollectionBeforeChangeHook } from 'payload'
|
import type { CollectionBeforeChangeHook } from 'payload'
|
||||||
|
|
||||||
const beforeChangeHook: CollectionBeforeChangeHook = async ({
|
const beforeChangeHook: CollectionBeforeChangeHook = async ({ data }) => {
|
||||||
data,
|
|
||||||
}) => {
|
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -137,7 +134,7 @@ const beforeChangeHook: CollectionBeforeChangeHook = async ({
|
|||||||
The following arguments are provided to the `beforeChange` hook:
|
The following arguments are provided to the `beforeChange` hook:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
||||||
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
||||||
| **`data`** | The incoming data passed through the operation. |
|
| **`data`** | The incoming data passed through the operation. |
|
||||||
@@ -152,9 +149,7 @@ After a document is created or updated, the `afterChange` hook runs. This hook i
|
|||||||
```ts
|
```ts
|
||||||
import type { CollectionAfterChangeHook } from 'payload'
|
import type { CollectionAfterChangeHook } from 'payload'
|
||||||
|
|
||||||
const afterChangeHook: CollectionAfterChangeHook = async ({
|
const afterChangeHook: CollectionAfterChangeHook = async ({ doc }) => {
|
||||||
doc,
|
|
||||||
}) => {
|
|
||||||
return doc
|
return doc
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -162,7 +157,7 @@ const afterChangeHook: CollectionAfterChangeHook = async ({
|
|||||||
The following arguments are provided to the `afterChange` hook:
|
The following arguments are provided to the `afterChange` hook:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
||||||
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
||||||
| **`doc`** | The resulting Document after changes are applied. |
|
| **`doc`** | The resulting Document after changes are applied. |
|
||||||
@@ -177,9 +172,7 @@ Runs before `find` and `findByID` operations are transformed for output by `afte
|
|||||||
```ts
|
```ts
|
||||||
import type { CollectionBeforeReadHook } from 'payload'
|
import type { CollectionBeforeReadHook } from 'payload'
|
||||||
|
|
||||||
const beforeReadHook: CollectionBeforeReadHook = async ({
|
const beforeReadHook: CollectionBeforeReadHook = async ({ doc }) => {
|
||||||
doc,
|
|
||||||
}) => {
|
|
||||||
return doc
|
return doc
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -201,9 +194,7 @@ Runs as the last step before documents are returned. Flattens locales, hides pro
|
|||||||
```ts
|
```ts
|
||||||
import type { CollectionAfterReadHook } from 'payload'
|
import type { CollectionAfterReadHook } from 'payload'
|
||||||
|
|
||||||
const afterReadHook: CollectionAfterReadHook = async ({
|
const afterReadHook: CollectionAfterReadHook = async ({ doc }) => {
|
||||||
doc,
|
|
||||||
}) => {
|
|
||||||
return doc
|
return doc
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -234,7 +225,7 @@ const beforeDeleteHook: CollectionBeforeDeleteHook = async ({
|
|||||||
The following arguments are provided to the `beforeDelete` hook:
|
The following arguments are provided to the `beforeDelete` hook:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
||||||
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
||||||
| **`id`** | The ID of the Document being deleted. |
|
| **`id`** | The ID of the Document being deleted. |
|
||||||
@@ -257,7 +248,7 @@ const afterDeleteHook: CollectionAfterDeleteHook = async ({
|
|||||||
The following arguments are provided to the `afterDelete` hook:
|
The following arguments are provided to the `afterDelete` hook:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
||||||
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
||||||
| **`doc`** | The resulting Document after changes are applied. |
|
| **`doc`** | The resulting Document after changes are applied. |
|
||||||
@@ -273,9 +264,7 @@ Available Collection operations include `create`, `find`, `findByID`, `update`,
|
|||||||
```ts
|
```ts
|
||||||
import type { CollectionAfterOperationHook } from 'payload'
|
import type { CollectionAfterOperationHook } from 'payload'
|
||||||
|
|
||||||
const afterOperationHook: CollectionAfterOperationHook = async ({
|
const afterOperationHook: CollectionAfterOperationHook = async ({ result }) => {
|
||||||
result,
|
|
||||||
}) => {
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -283,7 +272,7 @@ const afterOperationHook: CollectionAfterOperationHook = async ({
|
|||||||
The following arguments are provided to the `afterOperation` hook:
|
The following arguments are provided to the `afterOperation` hook:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`args`** | The arguments passed into the operation. |
|
| **`args`** | The arguments passed into the operation. |
|
||||||
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
||||||
| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
|
| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
|
||||||
@@ -303,6 +292,7 @@ const afterDeleteHook: CollectionAfterErrorHook = async ({
|
|||||||
doc,
|
doc,
|
||||||
}) => {...}
|
}) => {...}
|
||||||
```
|
```
|
||||||
|
|
||||||
The following arguments are provided to the `afterError` Hook:
|
The following arguments are provided to the `afterError` Hook:
|
||||||
|
|
||||||
| Argument | Description |
|
| Argument | Description |
|
||||||
@@ -321,9 +311,7 @@ For [Auth-enabled Collections](../authentication/overview), this hook runs durin
|
|||||||
```ts
|
```ts
|
||||||
import type { CollectionBeforeLoginHook } from 'payload'
|
import type { CollectionBeforeLoginHook } from 'payload'
|
||||||
|
|
||||||
const beforeLoginHook: CollectionBeforeLoginHook = async ({
|
const beforeLoginHook: CollectionBeforeLoginHook = async ({ user }) => {
|
||||||
user,
|
|
||||||
}) => {
|
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -331,7 +319,7 @@ const beforeLoginHook: CollectionBeforeLoginHook = async ({
|
|||||||
The following arguments are provided to the `beforeLogin` hook:
|
The following arguments are provided to the `beforeLogin` hook:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
||||||
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
||||||
| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
|
| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
|
||||||
@@ -353,7 +341,7 @@ const afterLoginHook: CollectionAfterLoginHook = async ({
|
|||||||
The following arguments are provided to the `afterLogin` hook:
|
The following arguments are provided to the `afterLogin` hook:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
||||||
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
||||||
| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
|
| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
|
||||||
@@ -375,7 +363,7 @@ const afterLogoutHook: CollectionAfterLogoutHook = async ({
|
|||||||
The following arguments are provided to the `afterLogout` hook:
|
The following arguments are provided to the `afterLogout` hook:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
||||||
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
||||||
| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
|
| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
|
||||||
@@ -396,7 +384,7 @@ const afterMeHook: CollectionAfterMeHook = async ({
|
|||||||
The following arguments are provided to the `afterMe` hook:
|
The following arguments are provided to the `afterMe` hook:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
||||||
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
||||||
| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
|
| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
|
||||||
@@ -417,7 +405,7 @@ const afterRefreshHook: CollectionAfterRefreshHook = async ({
|
|||||||
The following arguments are provided to the `afterRefresh` hook:
|
The following arguments are provided to the `afterRefresh` hook:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
||||||
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
||||||
| **`exp`** | The expiration time of the token. |
|
| **`exp`** | The expiration time of the token. |
|
||||||
@@ -441,7 +429,7 @@ const afterForgotPasswordHook: CollectionAfterForgotPasswordHook = async ({
|
|||||||
The following arguments are provided to the `afterForgotPassword` hook:
|
The following arguments are provided to the `afterForgotPassword` hook:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------- | ------------------------------------------------------------------------------------- |
|
||||||
| **`args`** | The arguments passed into the operation. |
|
| **`args`** | The arguments passed into the operation. |
|
||||||
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
|
||||||
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
||||||
@@ -462,7 +450,7 @@ const myRefreshHook: CollectionRefreshHook = async ({
|
|||||||
The following arguments are provided to the `afterRefresh` hook:
|
The following arguments are provided to the `afterRefresh` hook:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------- | ---------------------------------------- |
|
||||||
| **`args`** | The arguments passed into the operation. |
|
| **`args`** | The arguments passed into the operation. |
|
||||||
| **`user`** | The user being logged in. |
|
| **`user`** | The user being logged in. |
|
||||||
|
|
||||||
@@ -482,7 +470,7 @@ const meHook: CollectionMeHook = async ({
|
|||||||
The following arguments are provided to the `me` hook:
|
The following arguments are provided to the `me` hook:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------- | ---------------------------------------- |
|
||||||
| **`args`** | The arguments passed into the operation. |
|
| **`args`** | The arguments passed into the operation. |
|
||||||
| **`user`** | The user being logged in. |
|
| **`user`** | The user being logged in. |
|
||||||
|
|
||||||
|
|||||||
@@ -11,11 +11,12 @@ Field Hooks are [Hooks](./overview) that run on Documents on a per-field basis.
|
|||||||
To add Hooks to a Field, use the `hooks` property in your [Field Config](../fields/overview):
|
To add Hooks to a Field, use the `hooks` property in your [Field Config](../fields/overview):
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import type { Field } from 'payload';
|
import type { Field } from 'payload'
|
||||||
|
|
||||||
export const FieldWithHooks: Field = {
|
export const FieldWithHooks: Field = {
|
||||||
// ...
|
// ...
|
||||||
hooks: { // highlight-line
|
hooks: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -26,8 +27,11 @@ export const FieldWithHooks: Field = {
|
|||||||
All Field Hooks accept an array of synchronous or asynchronous functions. These functions can optionally modify the return value of the field before the operation continues. All Field Hooks are formatted to accept the same arguments, although some arguments may be `undefined` based the specific hook type.
|
All Field Hooks accept an array of synchronous or asynchronous functions. These functions can optionally modify the return value of the field before the operation continues. All Field Hooks are formatted to accept the same arguments, although some arguments may be `undefined` based the specific hook type.
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Important:**
|
**Important:** Due to GraphQL's typed nature, changing the type of data that
|
||||||
Due to GraphQL's typed nature, changing the type of data that you return from a field will produce errors in the [GraphQL API](../graphql/overview). If you need to change the shape or type of data, consider [Collection Hooks](./collections) or [Global Hooks](./globals) instead.
|
you return from a field will produce errors in the [GraphQL
|
||||||
|
API](../graphql/overview). If you need to change the shape or type of data,
|
||||||
|
consider [Collection Hooks](./collections) or [Global Hooks](./globals)
|
||||||
|
instead.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
To add hooks to a Field, use the `hooks` property in your [Field Config](../fields/overview):
|
To add hooks to a Field, use the `hooks` property in your [Field Config](../fields/overview):
|
||||||
@@ -53,7 +57,7 @@ const FieldWithHooks: Field = {
|
|||||||
The following arguments are provided to all Field Hooks:
|
The following arguments are provided to all Field Hooks:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. If the field belongs to a Global, this will be `null`. |
|
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. If the field belongs to a Global, this will be `null`. |
|
||||||
| **`context`** | Custom context passed between Hooks. [More details](./context). |
|
| **`context`** | Custom context passed between Hooks. [More details](./context). |
|
||||||
| **`data`** | In the `afterRead` hook this is the full Document. In the `create` and `update` operations, this is the incoming data passed through the operation. |
|
| **`data`** | In the `afterRead` hook this is the full Document. In the `create` and `update` operations, this is the incoming data passed through the operation. |
|
||||||
@@ -75,8 +79,10 @@ The following arguments are provided to all Field Hooks:
|
|||||||
| **`value`** | The value of the [Field](../fields/overview). |
|
| **`value`** | The value of the [Field](../fields/overview). |
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Tip:**
|
**Tip:** It's a good idea to conditionally scope your logic based on which
|
||||||
It's a good idea to conditionally scope your logic based on which operation is executing. For example, if you are writing a `beforeChange` hook, you may want to perform different logic based on if the current `operation` is `create` or `update`.
|
operation is executing. For example, if you are writing a `beforeChange` hook,
|
||||||
|
you may want to perform different logic based on if the current `operation` is
|
||||||
|
`create` or `update`.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### beforeValidate
|
### beforeValidate
|
||||||
@@ -220,10 +226,12 @@ const numberField: Field = {
|
|||||||
type: 'number',
|
type: 'number',
|
||||||
hooks: {
|
hooks: {
|
||||||
// increment existing value by 1
|
// increment existing value by 1
|
||||||
beforeDuplicate: [({ value }) => {
|
beforeDuplicate: [
|
||||||
|
({ value }) => {
|
||||||
return (value ?? 0) + 1
|
return (value ?? 0) + 1
|
||||||
}],
|
},
|
||||||
}
|
],
|
||||||
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -11,19 +11,20 @@ Global Hooks are [Hooks](./overview) that run on [Global](../configuration/globa
|
|||||||
To add Hooks to a Global, use the `hooks` property in your [Global Config](../configuration/globals):
|
To add Hooks to a Global, use the `hooks` property in your [Global Config](../configuration/globals):
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import type { GlobalConfig } from 'payload';
|
import type { GlobalConfig } from 'payload'
|
||||||
|
|
||||||
export const GlobalWithHooks: GlobalConfig = {
|
export const GlobalWithHooks: GlobalConfig = {
|
||||||
// ...
|
// ...
|
||||||
hooks: { // highlight-line
|
hooks: {
|
||||||
|
// highlight-line
|
||||||
// ...
|
// ...
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
**Tip:**
|
**Tip:** You can also set hooks on the field-level to isolate hook logic to
|
||||||
You can also set hooks on the field-level to isolate hook logic to specific fields. [More details](./fields).
|
specific fields. [More details](./fields).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Config Options
|
## Config Options
|
||||||
@@ -72,7 +73,7 @@ const beforeValidateHook: GlobalBeforeValidateHook = async ({
|
|||||||
The following arguments are provided to the `beforeValidate` hook:
|
The following arguments are provided to the `beforeValidate` hook:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`global`** | The [Global](../configuration/globals) in which this Hook is running against. |
|
| **`global`** | The [Global](../configuration/globals) in which this Hook is running against. |
|
||||||
| **`context`** | Custom context passed between Hooks. [More details](./context). |
|
| **`context`** | Custom context passed between Hooks. [More details](./context). |
|
||||||
| **`data`** | The incoming data passed through the operation. |
|
| **`data`** | The incoming data passed through the operation. |
|
||||||
@@ -98,7 +99,7 @@ const beforeChangeHook: GlobalBeforeChangeHook = async ({
|
|||||||
The following arguments are provided to the `beforeChange` hook:
|
The following arguments are provided to the `beforeChange` hook:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`global`** | The [Global](../configuration/globals) in which this Hook is running against. |
|
| **`global`** | The [Global](../configuration/globals) in which this Hook is running against. |
|
||||||
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
||||||
| **`data`** | The incoming data passed through the operation. |
|
| **`data`** | The incoming data passed through the operation. |
|
||||||
@@ -124,7 +125,7 @@ const afterChangeHook: GlobalAfterChangeHook = async ({
|
|||||||
The following arguments are provided to the `afterChange` hook:
|
The following arguments are provided to the `afterChange` hook:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`global`** | The [Global](../configuration/globals) in which this Hook is running against. |
|
| **`global`** | The [Global](../configuration/globals) in which this Hook is running against. |
|
||||||
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
||||||
| **`doc`** | The resulting Document after changes are applied. |
|
| **`doc`** | The resulting Document after changes are applied. |
|
||||||
@@ -147,7 +148,7 @@ const beforeReadHook: GlobalBeforeReadHook = async ({
|
|||||||
The following arguments are provided to the `beforeRead` hook:
|
The following arguments are provided to the `beforeRead` hook:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`global`** | The [Global](../configuration/globals) in which this Hook is running against. |
|
| **`global`** | The [Global](../configuration/globals) in which this Hook is running against. |
|
||||||
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
| **`context`** | Custom context passed between hooks. [More details](./context). |
|
||||||
| **`doc`** | The resulting Document after changes are applied. |
|
| **`doc`** | The resulting Document after changes are applied. |
|
||||||
|
|||||||
@@ -26,8 +26,10 @@ There are four main types of Hooks in Payload:
|
|||||||
- [Field Hooks](/docs/hooks/fields)
|
- [Field Hooks](/docs/hooks/fields)
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Reminder:**
|
**Reminder:** Payload also ships a set of _React_ hooks that you can use in
|
||||||
Payload also ships a set of _React_ hooks that you can use in your frontend application. Although they share a common name, these are very different things and should not be confused. [More details](../admin/react-hooks).
|
your frontend application. Although they share a common name, these are very
|
||||||
|
different things and should not be confused. [More
|
||||||
|
details](../admin/react-hooks).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Root Hooks
|
## Root Hooks
|
||||||
@@ -52,7 +54,7 @@ export default buildConfig({
|
|||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
|--------------|-----------------------------------------------------------------------------------------------|
|
| ---------------- | ------------------------------------------------------ |
|
||||||
| **`afterError`** | Runs after an error occurs in the Payload application. |
|
| **`afterError`** | Runs after an error occurs in the Payload application. |
|
||||||
|
|
||||||
### afterError
|
### afterError
|
||||||
@@ -65,9 +67,11 @@ import { buildConfig } from 'payload'
|
|||||||
export default buildConfig({
|
export default buildConfig({
|
||||||
// ...
|
// ...
|
||||||
hooks: {
|
hooks: {
|
||||||
afterError: [async ({ error }) => {
|
afterError: [
|
||||||
|
async ({ error }) => {
|
||||||
// Do something
|
// Do something
|
||||||
}]
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
@@ -82,6 +86,7 @@ The following arguments are provided to the `afterError` Hook:
|
|||||||
| **`req`** | The `PayloadRequest` object that extends [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request). Contains currently authenticated `user` and the Local API instance `payload`. |
|
| **`req`** | The `PayloadRequest` object that extends [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request). Contains currently authenticated `user` and the Local API instance `payload`. |
|
||||||
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. This will be `undefined` if the hook is executed from a non-collection endpoint or GraphQL. |
|
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. This will be `undefined` if the hook is executed from a non-collection endpoint or GraphQL. |
|
||||||
| **`result`** | The formatted error result object, available if the hook is executed from a REST context. |
|
| **`result`** | The formatted error result object, available if the hook is executed from a REST context. |
|
||||||
|
|
||||||
## Async vs. Synchronous
|
## Async vs. Synchronous
|
||||||
|
|
||||||
All Hooks can be written as either synchronous or asynchronous functions. Choosing the right type depends on your use case, but switching between the two is as simple as adding or removing the `async` keyword.
|
All Hooks can be written as either synchronous or asynchronous functions. Choosing the right type depends on your use case, but switching between the two is as simple as adding or removing the `async` keyword.
|
||||||
|
|||||||
@@ -11,9 +11,10 @@ keywords: vercel, vercel content link, content link, visual editing, content sou
|
|||||||

|

|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
Vercel Content Link is an enterprise-only feature and only available for deployments hosted on
|
Vercel Content Link is an enterprise-only feature and only available for
|
||||||
Vercel. If you are an existing enterprise customer, [contact our sales
|
deployments hosted on Vercel. If you are an existing enterprise customer,
|
||||||
team](https://payloadcms.com/for-enterprise) for help with your integration.
|
[contact our sales team](https://payloadcms.com/for-enterprise) for help with
|
||||||
|
your integration.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## How it works
|
## How it works
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ keywords: jobs queue, application framework, typescript, node, react, nextjs
|
|||||||
Now that we have covered Tasks and Workflows, we can tie them together with a concept called a Job.
|
Now that we have covered Tasks and Workflows, we can tie them together with a concept called a Job.
|
||||||
|
|
||||||
<Banner type="default">
|
<Banner type="default">
|
||||||
Whereas you define Workflows and Tasks, which control your business logic, a **Job** is an individual instance of either a Task or a Workflow which contains many tasks.
|
Whereas you define Workflows and Tasks, which control your business logic, a
|
||||||
|
**Job** is an individual instance of either a Task or a Workflow which
|
||||||
|
contains many tasks.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
For example, let's say we have a Workflow or Task that describes the logic to sync information from Payload to a third-party system. This is how you'd declare how to sync that info, but it wouldn't do anything on its own. In order to run that task or workflow, you'd create a Job that references the corresponding Task or Workflow.
|
For example, let's say we have a Workflow or Task that describes the logic to sync information from Payload to a third-party system. This is how you'd declare how to sync that info, but it wouldn't do anything on its own. In order to run that task or workflow, you'd create a Job that references the corresponding Task or Workflow.
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ keywords: jobs queue, application framework, typescript, node, react, nextjs
|
|||||||
Queues are the final aspect of Payload's Jobs Queue and deal with how to _run your jobs_. Up to this point, all we've covered is how to queue up jobs to run, but so far, we aren't actually running any jobs.
|
Queues are the final aspect of Payload's Jobs Queue and deal with how to _run your jobs_. Up to this point, all we've covered is how to queue up jobs to run, but so far, we aren't actually running any jobs.
|
||||||
|
|
||||||
<Banner type="default">
|
<Banner type="default">
|
||||||
A **Queue** is a grouping of jobs that should be executed in order of when they were added.
|
A **Queue** is a grouping of jobs that should be executed in order of when
|
||||||
|
they were added.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
When you go to run jobs, Payload will query for any jobs that are added to the queue and then run them. By default, all queued jobs are added to the `default` queue.
|
When you go to run jobs, Payload will query for any jobs that are added to the queue and then run them. By default, all queued jobs are added to the `default` queue.
|
||||||
@@ -52,12 +53,15 @@ export default buildConfig({
|
|||||||
// This function will be invoked each time Payload goes to pick up and run jobs.
|
// This function will be invoked each time Payload goes to pick up and run jobs.
|
||||||
// If this function ever returns false, the cron schedule will be stopped.
|
// If this function ever returns false, the cron schedule will be stopped.
|
||||||
return true
|
return true
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">autoRun is intended for use with a dedicated server that is always running, and should not be used on serverless platforms like Vercel.</Banner>
|
<Banner type="warning">
|
||||||
|
autoRun is intended for use with a dedicated server that is always running,
|
||||||
|
and should not be used on serverless platforms like Vercel.
|
||||||
|
</Banner>
|
||||||
|
|
||||||
#### Endpoint
|
#### Endpoint
|
||||||
|
|
||||||
@@ -69,9 +73,9 @@ You can execute jobs by making a fetch request to the `/api/payload-jobs/run` en
|
|||||||
await fetch('/api/payload-jobs/run?limit=100&queue=nightly', {
|
await fetch('/api/payload-jobs/run?limit=100&queue=nightly', {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': `Bearer ${token}`,
|
Authorization: `Bearer ${token}`,
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
This endpoint is automatically mounted for you and is helpful in conjunction with serverless platforms like Vercel, where you might want to use Vercel Cron to invoke a serverless function that executes your jobs.
|
This endpoint is automatically mounted for you and is helpful in conjunction with serverless platforms like Vercel, where you might want to use Vercel Cron to invoke a serverless function that executes your jobs.
|
||||||
@@ -113,12 +117,12 @@ export default buildConfig({
|
|||||||
// If there is no logged in user, then check
|
// If there is no logged in user, then check
|
||||||
// for the Vercel Cron secret to be present as an
|
// for the Vercel Cron secret to be present as an
|
||||||
// Authorization header:
|
// Authorization header:
|
||||||
const authHeader = req.headers.get('authorization');
|
const authHeader = req.headers.get('authorization')
|
||||||
return authHeader === `Bearer ${process.env.CRON_SECRET}`;
|
return authHeader === `Bearer ${process.env.CRON_SECRET}`
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// Other job configurations...
|
// Other job configurations...
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -139,14 +143,16 @@ const results = await payload.jobs.run()
|
|||||||
await payload.jobs.run({ queue: 'nightly', limit: 100 })
|
await payload.jobs.run({ queue: 'nightly', limit: 100 })
|
||||||
|
|
||||||
// You can provide a where clause to filter the jobs that should be run:
|
// You can provide a where clause to filter the jobs that should be run:
|
||||||
await payload.jobs.run({ where: { 'input.message': { equals: 'secret' } } })
|
await payload.jobs.run({
|
||||||
|
where: { 'input.message': { equals: 'secret' } },
|
||||||
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
**Run a single job:**
|
**Run a single job:**
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const results = await payload.jobs.runByID({
|
const results = await payload.jobs.runByID({
|
||||||
id: myJobID
|
id: myJobID,
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ keywords: jobs queue, application framework, typescript, node, react, nextjs
|
|||||||
---
|
---
|
||||||
|
|
||||||
<Banner type="default">
|
<Banner type="default">
|
||||||
A **"Task"** is a function definition that performs business logic and whose input and output are both strongly typed.
|
A **"Task"** is a function definition that performs business logic and whose
|
||||||
|
input and output are both strongly typed.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
You can register Tasks on the Payload config, and then create [Jobs](/docs/jobs-queue/jobs) or [Workflows](/docs/jobs-queue/workflows) that use them. Think of Tasks like tidy, isolated "functions that do one specific thing".
|
You can register Tasks on the Payload config, and then create [Jobs](/docs/jobs-queue/jobs) or [Workflows](/docs/jobs-queue/workflows) that use them. Think of Tasks like tidy, isolated "functions that do one specific thing".
|
||||||
@@ -21,8 +22,8 @@ Tasks can either be defined within the `jobs.tasks` array in your payload config
|
|||||||
Simply add a task to the `jobs.tasks` array in your Payload config. A task consists of the following fields:
|
Simply add a task to the `jobs.tasks` array in your Payload config. A task consists of the following fields:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| --------------------------- | -------------------------------------------------------------------------------- |
|
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| `slug` | Define a slug-based name for this job. This slug needs to be unique among both tasks and workflows.|
|
| `slug` | Define a slug-based name for this job. This slug needs to be unique among both tasks and workflows. |
|
||||||
| `handler` | The function that should be responsible for running the job. You can either pass a string-based path to the job function file, or the job function itself. If you are using large dependencies within your job, you might prefer to pass the string path because that will avoid bundling large dependencies in your Next.js app. Passing a string path is an advanced feature that may require a sophisticated build pipeline in order to work. |
|
| `handler` | The function that should be responsible for running the job. You can either pass a string-based path to the job function file, or the job function itself. If you are using large dependencies within your job, you might prefer to pass the string path because that will avoid bundling large dependencies in your Next.js app. Passing a string path is an advanced feature that may require a sophisticated build pipeline in order to work. |
|
||||||
| `inputSchema` | Define the input field schema - payload will generate a type for this schema. |
|
| `inputSchema` | Define the input field schema - payload will generate a type for this schema. |
|
||||||
| `interfaceName` | You can use interfaceName to change the name of the interface that is generated for this task. By default, this is "Task" + the capitalized task slug. |
|
| `interfaceName` | You can use interfaceName to change the name of the interface that is generated for this task. By default, this is "Task" + the capitalized task slug. |
|
||||||
@@ -86,8 +87,8 @@ export default buildConfig({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
} as TaskConfig<'createPost'>,
|
} as TaskConfig<'createPost'>,
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -112,10 +113,12 @@ export default buildConfig({
|
|||||||
{
|
{
|
||||||
// ...
|
// ...
|
||||||
// The #createPostHandler is a named export within the `createPost.ts` file
|
// The #createPostHandler is a named export within the `createPost.ts` file
|
||||||
handler: path.resolve(dirname, 'src/tasks/createPost.ts') + '#createPostHandler',
|
handler:
|
||||||
}
|
path.resolve(dirname, 'src/tasks/createPost.ts') +
|
||||||
]
|
'#createPostHandler',
|
||||||
}
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -126,7 +129,11 @@ Then, the `createPost` file itself:
|
|||||||
```ts
|
```ts
|
||||||
import type { TaskHandler } from 'payload'
|
import type { TaskHandler } from 'payload'
|
||||||
|
|
||||||
export const createPostHandler: TaskHandler<'createPost'> = async ({ input, job, req }) => {
|
export const createPostHandler: TaskHandler<'createPost'> = async ({
|
||||||
|
input,
|
||||||
|
job,
|
||||||
|
req,
|
||||||
|
}) => {
|
||||||
const newPost = await req.payload.create({
|
const newPost = await req.payload.create({
|
||||||
collection: 'post',
|
collection: 'post',
|
||||||
req,
|
req,
|
||||||
@@ -165,11 +172,11 @@ export default buildConfig({
|
|||||||
slug: 'myTask',
|
slug: 'myTask',
|
||||||
retries: {
|
retries: {
|
||||||
shouldRestore: false,
|
shouldRestore: false,
|
||||||
}
|
},
|
||||||
// ...
|
// ...
|
||||||
} as TaskConfig<'myTask'>,
|
} as TaskConfig<'myTask'>,
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -191,16 +198,16 @@ export default buildConfig({
|
|||||||
],
|
],
|
||||||
retries: {
|
retries: {
|
||||||
shouldRestore: ({ input }) => {
|
shouldRestore: ({ input }) => {
|
||||||
if(new Date(input.someDate) > new Date()) {
|
if (new Date(input.someDate) > new Date()) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
// ...
|
// ...
|
||||||
} as TaskConfig<'myTask'>,
|
} as TaskConfig<'myTask'>,
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -208,7 +215,6 @@ export default buildConfig({
|
|||||||
|
|
||||||
You can run sub-tasks within an existing task, by using the `tasks` or `ìnlineTask` arguments passed to the task `handler` function:
|
You can run sub-tasks within an existing task, by using the `tasks` or `ìnlineTask` arguments passed to the task `handler` function:
|
||||||
|
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
export default buildConfig({
|
export default buildConfig({
|
||||||
// ...
|
// ...
|
||||||
@@ -222,11 +228,10 @@ export default buildConfig({
|
|||||||
inputSchema: [
|
inputSchema: [
|
||||||
{
|
{
|
||||||
name: 'text',
|
name: 'text',
|
||||||
type: 'text'
|
type: 'text',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
handler: async ({ input, req, tasks, inlineTask }) => {
|
handler: async ({ input, req, tasks, inlineTask }) => {
|
||||||
|
|
||||||
await inlineTask('Sub Task 1', {
|
await inlineTask('Sub Task 1', {
|
||||||
task: () => {
|
task: () => {
|
||||||
// Do something
|
// Do something
|
||||||
@@ -243,9 +248,9 @@ export default buildConfig({
|
|||||||
return {
|
return {
|
||||||
output: {},
|
output: {},
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
} as TaskConfig<'parentTask'>,
|
} as TaskConfig<'parentTask'>,
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ keywords: jobs queue, application framework, typescript, node, react, nextjs
|
|||||||
---
|
---
|
||||||
|
|
||||||
<Banner type="default">
|
<Banner type="default">
|
||||||
A **"Workflow"** is an optional way to *combine multiple tasks together* in a way that can be gracefully retried from the point of failure.
|
A **"Workflow"** is an optional way to *combine multiple tasks together* in a
|
||||||
|
way that can be gracefully retried from the point of failure.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
They're most helpful when you have multiple tasks in a row, and you want to configure each task to be able to be retried if they fail.
|
They're most helpful when you have multiple tasks in a row, and you want to configure each task to be able to be retried if they fail.
|
||||||
@@ -23,8 +24,8 @@ However, importantly, tasks that have successfully been completed will simply re
|
|||||||
To define a JS-based workflow, simply add a workflow to the `jobs.workflows` array in your Payload config. A workflow consists of the following fields:
|
To define a JS-based workflow, simply add a workflow to the `jobs.workflows` array in your Payload config. A workflow consists of the following fields:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| --------------------------- | -------------------------------------------------------------------------------- |
|
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| `slug` | Define a slug-based name for this workflow. This slug needs to be unique among both tasks and workflows.|
|
| `slug` | Define a slug-based name for this workflow. This slug needs to be unique among both tasks and workflows. |
|
||||||
| `handler` | The function that should be responsible for running the workflow. You can either pass a string-based path to the workflow function file, or workflow job function itself. If you are using large dependencies within your workflow, you might prefer to pass the string path because that will avoid bundling large dependencies in your Next.js app. Passing a string path is an advanced feature that may require a sophisticated build pipeline in order to work. |
|
| `handler` | The function that should be responsible for running the workflow. You can either pass a string-based path to the workflow function file, or workflow job function itself. If you are using large dependencies within your workflow, you might prefer to pass the string path because that will avoid bundling large dependencies in your Next.js app. Passing a string path is an advanced feature that may require a sophisticated build pipeline in order to work. |
|
||||||
| `inputSchema` | Define the input field schema - payload will generate a type for this schema. |
|
| `inputSchema` | Define the input field schema - payload will generate a type for this schema. |
|
||||||
| `interfaceName` | You can use interfaceName to change the name of the interface that is generated for this workflow. By default, this is "Workflow" + the capitalized workflow slug. |
|
| `interfaceName` | You can use interfaceName to change the name of the interface that is generated for this workflow. By default, this is "Workflow" + the capitalized workflow slug. |
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ keywords: live preview, frontend, react, next.js, vue, nuxt.js, svelte, hook, us
|
|||||||
---
|
---
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
If your front-end application supports Server Components like the [Next.js App Router](https://nextjs.org/docs/app), etc., we suggest setting up [server-side Live Preview](./server) instead.
|
If your front-end application supports Server Components like the [Next.js App
|
||||||
|
Router](https://nextjs.org/docs/app), etc., we suggest setting up [server-side
|
||||||
|
Live Preview](./server) instead.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
While using Live Preview, the [Admin Panel](../admin/overview) emits a new `window.postMessage` event every time your document has changed. Your front-end application can listen for these events and re-render accordingly.
|
While using Live Preview, the [Admin Panel](../admin/overview) emits a new `window.postMessage` event every time your document has changed. Your front-end application can listen for these events and re-render accordingly.
|
||||||
@@ -18,12 +20,12 @@ By default, all hooks accept the following args:
|
|||||||
|
|
||||||
| Path | Description |
|
| Path | Description |
|
||||||
| ------------------ | -------------------------------------------------------------------------------------- |
|
| ------------------ | -------------------------------------------------------------------------------------- |
|
||||||
| **`serverURL`** * | The URL of your Payload server. |
|
| **`serverURL`** \* | The URL of your Payload server. |
|
||||||
| **`initialData`** | The initial data of the document. The live data will be merged in as changes are made. |
|
| **`initialData`** | The initial data of the document. The live data will be merged in as changes are made. |
|
||||||
| **`depth`** | The depth of the relationships to fetch. Defaults to `0`. |
|
| **`depth`** | The depth of the relationships to fetch. Defaults to `0`. |
|
||||||
| **`apiRoute`** | The path of your API route as defined in `routes.api`. Defaults to `/api`. |
|
| **`apiRoute`** | The path of your API route as defined in `routes.api`. Defaults to `/api`. |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
And return the following values:
|
And return the following values:
|
||||||
|
|
||||||
@@ -33,15 +35,19 @@ And return the following values:
|
|||||||
| **`isLoading`** | A boolean that indicates whether or not the document is loading. |
|
| **`isLoading`** | A boolean that indicates whether or not the document is loading. |
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
If your front-end is tightly coupled to required fields, you should ensure that your UI does not
|
If your front-end is tightly coupled to required fields, you should ensure
|
||||||
break when these fields are removed. For example, if you are rendering something like
|
that your UI does not break when these fields are removed. For example, if you
|
||||||
`data.relatedPosts[0].title`, your page will break once you remove the first related post. To get
|
are rendering something like `data.relatedPosts[0].title`, your page will
|
||||||
around this, use conditional logic, optional chaining, or default values in your UI where needed.
|
break once you remove the first related post. To get around this, use
|
||||||
For example, `data?.relatedPosts?.[0]?.title`.
|
conditional logic, optional chaining, or default values in your UI where
|
||||||
|
needed. For example, `data?.relatedPosts?.[0]?.title`.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
It is important that the `depth` argument matches exactly with the depth of your initial page request. The depth property is used to populated relationships and uploads beyond their IDs. See [Depth](../queries/depth) for more information.
|
It is important that the `depth` argument matches exactly with the depth of
|
||||||
|
your initial page request. The depth property is used to populated
|
||||||
|
relationships and uploads beyond their IDs. See [Depth](../queries/depth) for
|
||||||
|
more information.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Frameworks
|
## Frameworks
|
||||||
@@ -89,8 +95,9 @@ export const PageClient: React.FC<{
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Reminder:**
|
**Reminder:** If you are using [React Server
|
||||||
If you are using [React Server Components](https://react.dev/reference/rsc/server-components), we strongly suggest setting up [server-side Live Preview](./server) instead.
|
Components](https://react.dev/reference/rsc/server-components), we strongly
|
||||||
|
suggest setting up [server-side Live Preview](./server) instead.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### Vue
|
### Vue
|
||||||
@@ -141,7 +148,7 @@ npm install @payloadcms/live-preview
|
|||||||
This package provides the following functions:
|
This package provides the following functions:
|
||||||
|
|
||||||
| Path | Description |
|
| Path | Description |
|
||||||
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
|
| ------------------------ | ------------------------------------------------------------------------------------------------------------------ |
|
||||||
| **`subscribe`** | Subscribes to the Admin Panel's `window.postMessage` events and calls the provided callback function. |
|
| **`subscribe`** | Subscribes to the Admin Panel's `window.postMessage` events and calls the provided callback function. |
|
||||||
| **`unsubscribe`** | Unsubscribes from the Admin Panel's `window.postMessage` events. |
|
| **`unsubscribe`** | Unsubscribes from the Admin Panel's `window.postMessage` events. |
|
||||||
| **`ready`** | Sends a `window.postMessage` event to the Admin Panel to indicate that the front-end is ready to receive messages. |
|
| **`ready`** | Sends a `window.postMessage` event to the Admin Panel to indicate that the front-end is ready to receive messages. |
|
||||||
@@ -151,8 +158,8 @@ The `subscribe` function takes the following args:
|
|||||||
|
|
||||||
| Path | Description |
|
| Path | Description |
|
||||||
| ------------------ | ------------------------------------------------------------------------------------------- |
|
| ------------------ | ------------------------------------------------------------------------------------------- |
|
||||||
| **`callback`** * | A callback function that is called with `data` every time a change is made to the document. |
|
| **`callback`** \* | A callback function that is called with `data` every time a change is made to the document. |
|
||||||
| **`serverURL`** * | The URL of your Payload server. |
|
| **`serverURL`** \* | The URL of your Payload server. |
|
||||||
| **`initialData`** | The initial data of the document. The live data will be merged in as changes are made. |
|
| **`initialData`** | The initial data of the document. The live data will be merged in as changes are made. |
|
||||||
| **`depth`** | The depth of the relationships to fetch. Defaults to `0`. |
|
| **`depth`** | The depth of the relationships to fetch. Defaults to `0`. |
|
||||||
|
|
||||||
@@ -233,8 +240,9 @@ export const useLivePreview = <T extends any>(props: {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
When building your own hook, ensure that the args and return values are consistent with the ones
|
When building your own hook, ensure that the args and return values are
|
||||||
listed at the top of this document. This will ensure that all hooks follow the same API.
|
consistent with the ones listed at the top of this document. This will ensure
|
||||||
|
that all hooks follow the same API.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|||||||
@@ -12,5 +12,7 @@ There are two ways to use Live Preview in your own application depending on whet
|
|||||||
- [Client-side Live Preview](./client)
|
- [Client-side Live Preview](./client)
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
We suggest using server-side Live Preview if your framework supports Server Components, it is both simpler to setup and more performant to run than the client-side alternative.
|
We suggest using server-side Live Preview if your framework supports Server
|
||||||
|
Components, it is both simpler to setup and more performant to run than the
|
||||||
|
client-side alternative.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|||||||
@@ -22,16 +22,19 @@ const config = buildConfig({
|
|||||||
// highlight-start
|
// highlight-start
|
||||||
livePreview: {
|
livePreview: {
|
||||||
url: 'http://localhost:3000',
|
url: 'http://localhost:3000',
|
||||||
collections: ['pages']
|
collections: ['pages'],
|
||||||
},
|
},
|
||||||
// highlight-end
|
// highlight-end
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Reminder:**
|
**Reminder:** Alternatively, you can define the `admin.livePreview` property
|
||||||
Alternatively, you can define the `admin.livePreview` property on individual [Collection Admin Configs](../configuration/collections#admin-options) and [Global Admin Configs](../configuration/globals#admin-options). Settings defined here will be merged into the top-level as overrides.
|
on individual [Collection Admin
|
||||||
|
Configs](../configuration/collections#admin-options) and [Global Admin
|
||||||
|
Configs](../configuration/globals#admin-options). Settings defined here will
|
||||||
|
be merged into the top-level as overrides.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Options
|
## Options
|
||||||
@@ -42,12 +45,12 @@ The following options are available:
|
|||||||
|
|
||||||
| Path | Description |
|
| Path | Description |
|
||||||
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`url`** * | String, or function that returns a string, pointing to your front-end application. This value is used as the iframe `src`. [More details](#url). |
|
| **`url`** \* | String, or function that returns a string, pointing to your front-end application. This value is used as the iframe `src`. [More details](#url). |
|
||||||
| **`breakpoints`** | Array of breakpoints to be used as “device sizes” in the preview window. Each item appears as an option in the toolbar. [More details](#breakpoints). |
|
| **`breakpoints`** | Array of breakpoints to be used as “device sizes” in the preview window. Each item appears as an option in the toolbar. [More details](#breakpoints). |
|
||||||
| **`collections`** | Array of collection slugs to enable Live Preview on. |
|
| **`collections`** | Array of collection slugs to enable Live Preview on. |
|
||||||
| **`globals`** | Array of global slugs to enable Live Preview on. |
|
| **`globals`** | Array of global slugs to enable Live Preview on. |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
### URL
|
### URL
|
||||||
|
|
||||||
@@ -66,7 +69,7 @@ const config = buildConfig({
|
|||||||
url: 'http://localhost:3000', // highlight-line
|
url: 'http://localhost:3000', // highlight-line
|
||||||
collections: ['pages'],
|
collections: ['pages'],
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -102,7 +105,7 @@ const config = buildConfig({
|
|||||||
The following arguments are provided to the `url` function:
|
The following arguments are provided to the `url` function:
|
||||||
|
|
||||||
| Path | Description |
|
| Path | Description |
|
||||||
| ------------------ | ----------------------------------------------------------------------------------------------------------------- |
|
| ---------------------- | --------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`data`** | The data of the Document being edited. This includes changes that have not yet been saved. |
|
| **`data`** | The data of the Document being edited. This includes changes that have not yet been saved. |
|
||||||
| **`locale`** | The locale currently being edited (if applicable). [More details](../configuration/localization). |
|
| **`locale`** | The locale currently being edited (if applicable). [More details](../configuration/localization). |
|
||||||
| **`collectionConfig`** | The Collection Admin Config of the Document being edited. [More details](../configuration/collections#admin-options). |
|
| **`collectionConfig`** | The Collection Admin Config of the Document being edited. [More details](../configuration/collections#admin-options). |
|
||||||
@@ -143,7 +146,7 @@ const config = buildConfig({
|
|||||||
],
|
],
|
||||||
// highlight-end
|
// highlight-end
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -151,12 +154,12 @@ The following options are available for each breakpoint:
|
|||||||
|
|
||||||
| Path | Description |
|
| Path | Description |
|
||||||
| --------------- | --------------------------------------------------------------------------- |
|
| --------------- | --------------------------------------------------------------------------- |
|
||||||
| **`label`** * | The label to display in the drop-down. This is what the user will see. |
|
| **`label`** \* | The label to display in the drop-down. This is what the user will see. |
|
||||||
| **`name`** * | The name of the breakpoint. |
|
| **`name`** \* | The name of the breakpoint. |
|
||||||
| **`width`** * | The width of the breakpoint. This is used to set the width of the iframe. |
|
| **`width`** \* | The width of the breakpoint. This is used to set the width of the iframe. |
|
||||||
| **`height`** * | The height of the breakpoint. This is used to set the height of the iframe. |
|
| **`height`** \* | The height of the breakpoint. This is used to set the height of the iframe. |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
The "Responsive" option is always available in the drop-down and requires no additional configuration. This is the default breakpoint that will be used on initial load. This option styles the iframe with a width and height of `100%` so that it fills the screen at its maximum size and automatically resizes as the window changes size.
|
The "Responsive" option is always available in the drop-down and requires no additional configuration. This is the default breakpoint that will be used on initial load. This option styles the iframe with a width and height of `100%` so that it fills the screen at its maximum size and automatically resizes as the window changes size.
|
||||||
|
|
||||||
|
|||||||
@@ -7,13 +7,20 @@ keywords: live preview, frontend, react, next.js, vue, nuxt.js, svelte, hook, us
|
|||||||
---
|
---
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
Server-side Live Preview is only for front-end frameworks that support the concept of Server Components, i.e. [React Server Components](https://react.dev/reference/rsc/server-components). If your front-end application is built with a client-side framework like the [Next.js Pages Router](https://nextjs.org/docs/pages), [React Router](https://reactrouter.com), [Vue 3](https://vuejs.org), etc., see [client-side Live Preview](./client).
|
Server-side Live Preview is only for front-end frameworks that support the
|
||||||
|
concept of Server Components, i.e. [React Server
|
||||||
|
Components](https://react.dev/reference/rsc/server-components). If your
|
||||||
|
front-end application is built with a client-side framework like the [Next.js
|
||||||
|
Pages Router](https://nextjs.org/docs/pages), [React
|
||||||
|
Router](https://reactrouter.com), [Vue 3](https://vuejs.org), etc., see
|
||||||
|
[client-side Live Preview](./client).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
Server-side Live Preview works by making a roundtrip to the server every time your document is saved, i.e. draft save, autosave, or publish. While using Live Preview, the Admin Panel emits a new `window.postMessage` event which your front-end application can use to invoke this process. In Next.js, this means simply calling `router.refresh()` which will hydrate the HTML using new data straight from the [Local API](../local-api/overview).
|
Server-side Live Preview works by making a roundtrip to the server every time your document is saved, i.e. draft save, autosave, or publish. While using Live Preview, the Admin Panel emits a new `window.postMessage` event which your front-end application can use to invoke this process. In Next.js, this means simply calling `router.refresh()` which will hydrate the HTML using new data straight from the [Local API](../local-api/overview).
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
It is recommended that you enable [Autosave](../versions/autosave) alongside Live Preview to make the experience feel more responsive.
|
It is recommended that you enable [Autosave](../versions/autosave) alongside
|
||||||
|
Live Preview to make the experience feel more responsive.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
If your front-end application is built with [React](#react), you can use the `RefreshRouteOnChange` function that Payload provides. In the future, all other major frameworks like Vue and Svelte will be officially supported. If you are using any of these frameworks today, you can still integrate with Live Preview yourself using the underlying tooling that Payload provides. See [building your own router refresh component](#building-your-own-router-refresh-component) for more information.
|
If your front-end application is built with [React](#react), you can use the `RefreshRouteOnChange` function that Payload provides. In the future, all other major frameworks like Vue and Svelte will be officially supported. If you are using any of these frameworks today, you can still integrate with Live Preview yourself using the underlying tooling that Payload provides. See [building your own router refresh component](#building-your-own-router-refresh-component) for more information.
|
||||||
@@ -43,7 +50,7 @@ export default async function Page() {
|
|||||||
const page = await payload.findByID({
|
const page = await payload.findByID({
|
||||||
collection: 'pages',
|
collection: 'pages',
|
||||||
id: '123',
|
id: '123',
|
||||||
draft: true
|
draft: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -88,7 +95,7 @@ npm install @payloadcms/live-preview
|
|||||||
This package provides the following functions:
|
This package provides the following functions:
|
||||||
|
|
||||||
| Path | Description |
|
| Path | Description |
|
||||||
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`ready`** | Sends a `window.postMessage` event to the Admin Panel to indicate that the front-end is ready to receive messages. |
|
| **`ready`** | Sends a `window.postMessage` event to the Admin Panel to indicate that the front-end is ready to receive messages. |
|
||||||
| **`isDocumentEvent`** | Checks if a `MessageEvent` originates from the Admin Panel and is a document-level event, i.e. draft save, autosave, publish, etc. |
|
| **`isDocumentEvent`** | Checks if a `MessageEvent` originates from the Admin Panel and is a document-level event, i.e. draft save, autosave, publish, etc. |
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ keywords: local api, config, configuration, documentation, Content Management Sy
|
|||||||
Payload can be used completely outside of Next.js which is helpful in cases like running scripts, using Payload in a separate backend service, or using Payload's Local API to fetch your data directly from your database in other frontend frameworks like SvelteKit, Remix, Nuxt, and similar.
|
Payload can be used completely outside of Next.js which is helpful in cases like running scripts, using Payload in a separate backend service, or using Payload's Local API to fetch your data directly from your database in other frontend frameworks like SvelteKit, Remix, Nuxt, and similar.
|
||||||
|
|
||||||
<Banner>
|
<Banner>
|
||||||
**Note:**
|
**Note:** Payload and all of its official packages are fully ESM. If you want
|
||||||
|
to use Payload within your own projects, make sure you are writing your
|
||||||
Payload and all of its official packages are fully ESM. If you want to use Payload within your own projects, make sure you are writing your scripts in ESM format or dynamically importing the Payload Config.
|
scripts in ESM format or dynamically importing the Payload Config.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Importing the Payload Config outside of Next.js
|
## Importing the Payload Config outside of Next.js
|
||||||
@@ -32,8 +32,8 @@ const seed = async () => {
|
|||||||
collection: 'users',
|
collection: 'users',
|
||||||
data: {
|
data: {
|
||||||
email: 'dev@payloadcms.com',
|
email: 'dev@payloadcms.com',
|
||||||
password: 'some-password'
|
password: 'some-password',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const page = await payload.create({
|
const page = await payload.create({
|
||||||
@@ -41,7 +41,7 @@ const seed = async () => {
|
|||||||
data: {
|
data: {
|
||||||
title: 'My Homepage',
|
title: 'My Homepage',
|
||||||
// other data to seed here
|
// other data to seed here
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,6 +67,7 @@ If you encounter import-related errors, you have 2 options:
|
|||||||
#### Option 1: enable swc mode by appending `--use-swc` to the `payload` command:
|
#### Option 1: enable swc mode by appending `--use-swc` to the `payload` command:
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
payload run src/seed.ts --use-swc
|
payload run src/seed.ts --use-swc
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ The Payload Local API gives you the ability to execute the same operations that
|
|||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Tip:**
|
**Tip:**
|
||||||
|
|
||||||
The Local API is incredibly powerful when used in React Server Components and other similar server-side contexts. With other headless CMS, you need to request your data from third-party servers via an HTTP layer, which can add significant loading time to your server-rendered pages. With Payload, you don't have to leave your server to gather the data you need. It can be incredibly fast and is definitely a game changer.
|
The Local API is incredibly powerful when used in React Server Components and other similar server-side contexts. With other headless CMS, you need to request your data from third-party servers via an HTTP layer, which can add significant loading time to your server-rendered pages. With Payload, you don't have to leave your server to gather the data you need. It can be incredibly fast and is definitely a game changer.
|
||||||
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
Here are some common examples of how you can use the Local API:
|
Here are some common examples of how you can use the Local API:
|
||||||
@@ -32,7 +33,9 @@ In most places within Payload itself, you can access `payload` directly from the
|
|||||||
Example:
|
Example:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const afterChangeHook: CollectionAfterChangeHook = async ({ req: { payload } }) => {
|
const afterChangeHook: CollectionAfterChangeHook = async ({
|
||||||
|
req: { payload },
|
||||||
|
}) => {
|
||||||
const posts = await payload.find({
|
const posts = await payload.find({
|
||||||
collection: 'posts',
|
collection: 'posts',
|
||||||
})
|
})
|
||||||
@@ -94,8 +97,9 @@ const post = await payload.find({
|
|||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Note:**
|
**Note:**
|
||||||
|
|
||||||
By default, all access control checks are disabled in the Local API, but you can re-enable them if
|
By default, all access control checks are disabled in the Local API, but you can re-enable them if
|
||||||
you'd like, as well as pass a specific user to run the operation with.
|
you'd like, as well as pass a specific user to run the operation with.
|
||||||
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Collections
|
## Collections
|
||||||
@@ -325,7 +329,7 @@ available:
|
|||||||
// responseHeaders: { ... } // returned headers from the response
|
// responseHeaders: { ... } // returned headers from the response
|
||||||
// }
|
// }
|
||||||
|
|
||||||
const result = await payload.auth({headers})
|
const result = await payload.auth({ headers })
|
||||||
```
|
```
|
||||||
|
|
||||||
### Login
|
### Login
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ For more details, see the [Documentation](https://payloadcms.com/docs/getting-st
|
|||||||
```
|
```
|
||||||
|
|
||||||
Also install the other @payloadcms packages specific to the plugins and adapters you are using. Depending on your project, these may include:
|
Also install the other @payloadcms packages specific to the plugins and adapters you are using. Depending on your project, these may include:
|
||||||
|
|
||||||
- @payloadcms/db-mongodb
|
- @payloadcms/db-mongodb
|
||||||
- @payloadcms/db-postgres
|
- @payloadcms/db-postgres
|
||||||
- @payloadcms/richtext-slate
|
- @payloadcms/richtext-slate
|
||||||
@@ -76,7 +77,7 @@ For more details, see the [Documentation](https://payloadcms.com/docs/getting-st
|
|||||||
- [postgres](https://github.com/payloadcms/payload/releases/tag/v3.0.0-beta.39)
|
- [postgres](https://github.com/payloadcms/payload/releases/tag/v3.0.0-beta.39)
|
||||||
- [mongodb](https://github.com/payloadcms/payload/releases/tag/v3.0.0-beta.131)
|
- [mongodb](https://github.com/payloadcms/payload/releases/tag/v3.0.0-beta.131)
|
||||||
|
|
||||||
2. For Payload Cloud users, the plugin has changed.
|
1. For Payload Cloud users, the plugin has changed.
|
||||||
|
|
||||||
Uninstall the old package:
|
Uninstall the old package:
|
||||||
|
|
||||||
@@ -104,7 +105,7 @@ For more details, see the [Documentation](https://payloadcms.com/docs/getting-st
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
3. **Optional** sharp dependency
|
1. **Optional** sharp dependency
|
||||||
|
|
||||||
If you have upload enabled collections that use `formatOptions`, `imageSizes`, or `resizeOptions`—payload expects to have `sharp` installed. In 2.0 this was a dependency was installed for you. Now it is only installed if needed. If you have any of these options set, you will need to install `sharp` and add it to your payload.config.ts:
|
If you have upload enabled collections that use `formatOptions`, `imageSizes`, or `resizeOptions`—payload expects to have `sharp` installed. In 2.0 this was a dependency was installed for you. Now it is only installed if needed. If you have any of these options set, you will need to install `sharp` and add it to your payload.config.ts:
|
||||||
|
|
||||||
@@ -412,17 +413,17 @@ For more details, see the [Documentation](https://payloadcms.com/docs/getting-st
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
1. The `./src/public` directory is now located directly at root level `./public` [see Next.js docs for details](https://nextjs.org/docs/pages/building-your-application/optimizing/static-assets)
|
1. The `./src/public` directory is now located directly at root level `./public` [see Next.js docs for details](https://nextjs.org/docs/pages/building-your-application/optimizing/static-assets)
|
||||||
|
|
||||||
1. Payload now automatically removes `localized: true` property from sub-fields if a parent is localized, as it's redunant and unnecessary. If you have some existing data in this structure and you want to disable that behavior, you need to enable `allowLocalizedWithinLocalized` flag in your payload.config [read more in documentation](https://payloadcms.com/docs/configuration/overview#compatibility-flags), or create a migration script that aligns your data.
|
1. Payload now automatically removes `localized: true` property from sub-fields if a parent is localized, as it's redunant and unnecessary. If you have some existing data in this structure and you want to disable that behavior, you need to enable `allowLocalizedWithinLocalized` flag in your payload.config [read more in documentation](https://payloadcms.com/docs/configuration/overview#compatibility-flags), or create a migration script that aligns your data.
|
||||||
Mongodb example for a link in a page layout.
|
Mongodb example for a link in a page layout.
|
||||||
|
|
||||||
```diff
|
```diff
|
||||||
- layout.columns.en.link.en.type.en
|
- layout.columns.en.link.en.type.en
|
||||||
+ layout.columns.en.link.type
|
+ layout.columns.en.link.type
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Custom Components
|
## Custom Components
|
||||||
|
|
||||||
1. All Payload React components have been moved from the `payload` package to `@payloadcms/ui`. If you were previously importing components into your app from the `payload` package, for example to create Custom Components, you will need to change your import paths:
|
1. All Payload React components have been moved from the `payload` package to `@payloadcms/ui`. If you were previously importing components into your app from the `payload` package, for example to create Custom Components, you will need to change your import paths:
|
||||||
@@ -431,7 +432,8 @@ Mongodb example for a link in a page layout.
|
|||||||
- import { TextField, useField, etc. } from 'payload'
|
- import { TextField, useField, etc. } from 'payload'
|
||||||
+ import { TextField, useField, etc. } from '@payloadcms/ui'
|
+ import { TextField, useField, etc. } from '@payloadcms/ui'
|
||||||
```
|
```
|
||||||
*Note: for brevity, not _all_ modules are listed here*
|
|
||||||
|
_Note: for brevity, not *all* modules are listed here_
|
||||||
|
|
||||||
1. All Custom Components are now defined as _file paths_ instead of direct imports. If you are using Custom Components in your Payload Config, remove the imported module and point to the file's path instead:
|
1. All Custom Components are now defined as _file paths_ instead of direct imports. If you are using Custom Components in your Payload Config, remove the imported module and point to the file's path instead:
|
||||||
|
|
||||||
@@ -975,7 +977,7 @@ export default buildConfig({
|
|||||||
|
|
||||||
## Plugins
|
## Plugins
|
||||||
|
|
||||||
1. *All* plugins have been standardized to use _named exports_ (as opposed to default exports). Most also have a suffix of `Plugin` to make it clear what is being imported.
|
1. _All_ plugins have been standardized to use _named exports_ (as opposed to default exports). Most also have a suffix of `Plugin` to make it clear what is being imported.
|
||||||
|
|
||||||
```diff
|
```diff
|
||||||
- import seo from '@payloadcms/plugin-seo'
|
- import seo from '@payloadcms/plugin-seo'
|
||||||
@@ -990,7 +992,7 @@ export default buildConfig({
|
|||||||
## `@payloadcms/plugin-cloud-storage`
|
## `@payloadcms/plugin-cloud-storage`
|
||||||
|
|
||||||
- The adapters that are exported from `@payloadcms/plugin-cloud-storage` (ie. `@payloadcms/plugin-cloud-storage/s3`) package have been removed.
|
- The adapters that are exported from `@payloadcms/plugin-cloud-storage` (ie. `@payloadcms/plugin-cloud-storage/s3`) package have been removed.
|
||||||
- New *standalone* packages have been created for each of the existing adapters. Please see the documentation for the one that you use.
|
- New _standalone_ packages have been created for each of the existing adapters. Please see the documentation for the one that you use.
|
||||||
- `@payloadcms/plugin-cloud-storage` is still fully supported but should only to be used if you are providing a custom adapter that does not have a dedicated package.
|
- `@payloadcms/plugin-cloud-storage` is still fully supported but should only to be used if you are providing a custom adapter that does not have a dedicated package.
|
||||||
- If you have created a custom adapter, the type must now provide a `name` property.
|
- If you have created a custom adapter, the type must now provide a `name` property.
|
||||||
|
|
||||||
@@ -1134,6 +1136,7 @@ Payload reserves certain field names for internal use. Using any of the followin
|
|||||||
### Auth-Related Reserved Names
|
### Auth-Related Reserved Names
|
||||||
|
|
||||||
These are restricted if your collection uses `auth: true` and does not have `disableAuthStrategy: true`:
|
These are restricted if your collection uses `auth: true` and does not have `disableAuthStrategy: true`:
|
||||||
|
|
||||||
- `salt`
|
- `salt`
|
||||||
- `hash`
|
- `hash`
|
||||||
- `apiKey` (when `auth.useAPIKey: true` is enabled)
|
- `apiKey` (when `auth.useAPIKey: true` is enabled)
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ keywords: plugins, template, config, configuration, extensions, custom, document
|
|||||||
Building your own [Payload Plugin](./overview) is easy, and if you're already familiar with Payload then you'll have everything you need to get started. You can either start from scratch or use the [Plugin Template](#plugin-template) to get up and running quickly.
|
Building your own [Payload Plugin](./overview) is easy, and if you're already familiar with Payload then you'll have everything you need to get started. You can either start from scratch or use the [Plugin Template](#plugin-template) to get up and running quickly.
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
To use the template, run `npx create-payload-app@latest --template plugin` directly in
|
To use the template, run `npx create-payload-app@latest --template plugin`
|
||||||
your terminal.
|
directly in your terminal.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
Our plugin template includes everything you need to build a full life-cycle plugin:
|
Our plugin template includes everything you need to build a full life-cycle plugin:
|
||||||
@@ -162,7 +162,6 @@ export const seed = async (payload: Payload): Promise<void> => {
|
|||||||
|
|
||||||
Now that we have our environment setup and dev project ready to go - it's time to build the plugin!
|
Now that we have our environment setup and dev project ready to go - it's time to build the plugin!
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
import type { Config } from 'payload'
|
import type { Config } from 'payload'
|
||||||
|
|
||||||
@@ -210,7 +209,6 @@ export const samplePlugin =
|
|||||||
|
|
||||||
To reiterate, the essence of a [Payload Plugin](./overview) is simply to extend the [Payload Config](../configuration/overview) - and that is exactly what we are doing in this file.
|
To reiterate, the essence of a [Payload Plugin](./overview) is simply to extend the [Payload Config](../configuration/overview) - and that is exactly what we are doing in this file.
|
||||||
|
|
||||||
|
|
||||||
### Spread syntax
|
### Spread syntax
|
||||||
|
|
||||||
[Spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) (or the spread operator) is a feature in JavaScript that uses the dot notation **(...)** to spread elements from arrays, strings, or objects into various contexts.
|
[Spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) (or the spread operator) is a feature in JavaScript that uses the dot notation **(...)** to spread elements from arrays, strings, or objects into various contexts.
|
||||||
@@ -244,6 +242,7 @@ config.hooks = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Extending functions
|
### Extending functions
|
||||||
|
|
||||||
Function properties cannot use spread syntax. The way to extend them is to execute the existing function if it exists and then run your additional functionality.
|
Function properties cannot use spread syntax. The way to extend them is to execute the existing function if it exists and then run your additional functionality.
|
||||||
|
|
||||||
Here is an example extending the `onInit` property:
|
Here is an example extending the `onInit` property:
|
||||||
|
|||||||
@@ -16,9 +16,10 @@ Forms can be as simple or complex as you need, from a basic contact form, to a m
|
|||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
This plugin is completely open-source and the [source code can be found
|
This plugin is completely open-source and the [source code can be found
|
||||||
here](https://github.com/payloadcms/payload/tree/main/packages/plugin-form-builder). If you need
|
here](https://github.com/payloadcms/payload/tree/main/packages/plugin-form-builder).
|
||||||
help, check out our [Community Help](https://payloadcms.com/community-help). If you think you've
|
If you need help, check out our [Community
|
||||||
found a bug, please [open a new
|
Help](https://payloadcms.com/community-help). If you think you've found a bug,
|
||||||
|
please [open a new
|
||||||
issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20form-builder&template=bug_report.md&title=plugin-form-builder%3A)
|
issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20form-builder&template=bug_report.md&title=plugin-form-builder%3A)
|
||||||
with as much detail as possible.
|
with as much detail as possible.
|
||||||
</Banner>
|
</Banner>
|
||||||
@@ -124,10 +125,13 @@ For full types with `beforeChangeParams`, you can import the types from the plug
|
|||||||
```ts
|
```ts
|
||||||
import type { BeforeEmail } from '@payloadcms/plugin-form-builder'
|
import type { BeforeEmail } from '@payloadcms/plugin-form-builder'
|
||||||
// Your generated FormSubmission type
|
// Your generated FormSubmission type
|
||||||
import type {FormSubmission} from '@payload-types'
|
import type { FormSubmission } from '@payload-types'
|
||||||
|
|
||||||
// Pass it through and 'data' or 'originalDoc' will now be typed
|
// Pass it through and 'data' or 'originalDoc' will now be typed
|
||||||
const beforeEmail: BeforeEmail<FormSubmission> = (emailsToSend, beforeChangeParams) => {
|
const beforeEmail: BeforeEmail<FormSubmission> = (
|
||||||
|
emailsToSend,
|
||||||
|
beforeChangeParams,
|
||||||
|
) => {
|
||||||
// modify the emails in any way before they are sent
|
// modify the emails in any way before they are sent
|
||||||
return emails.map((email) => ({
|
return emails.map((email) => ({
|
||||||
...email,
|
...email,
|
||||||
@@ -155,7 +159,11 @@ Override anything on the `forms` collection by sending a [Payload Collection Con
|
|||||||
Note that the `fields` property is a function that receives the default fields and returns an array of fields. This is because the `fields` property is a special case that is merged with the default fields, rather than replacing them. This allows you to map over default fields and modify them as needed.
|
Note that the `fields` property is a function that receives the default fields and returns an array of fields. This is because the `fields` property is a special case that is merged with the default fields, rather than replacing them. This allows you to map over default fields and modify them as needed.
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
Good to know: The form collection is publicly available to read by default. The emails field is locked for authenticated users only. If you have any frontend users you should override the access permissions for both the collection and the emails field to make sure you don't leak out any private emails.
|
Good to know: The form collection is publicly available to read by default.
|
||||||
|
The emails field is locked for authenticated users only. If you have any
|
||||||
|
frontend users you should override the access permissions for both the
|
||||||
|
collection and the emails field to make sure you don't leak out any private
|
||||||
|
emails.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
@@ -187,10 +195,11 @@ Override anything on the `form-submissions` collection by sending a [Payload Col
|
|||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
By default, this plugin relies on [Payload access
|
By default, this plugin relies on [Payload access
|
||||||
control](https://payloadcms.com/docs/access-control/collections) to restrict the `update` and
|
control](https://payloadcms.com/docs/access-control/collections) to restrict
|
||||||
`read` operations on the `form-submissions` collection. This is because _anyone_ should be able to
|
the `update` and `read` operations on the `form-submissions` collection. This
|
||||||
create a form submission, even from a public-facing website, but _no one_ should be able to update
|
is because _anyone_ should be able to create a form submission, even from a
|
||||||
a submission once it has been created, or read a submission unless they have permission. You can
|
public-facing website, but _no one_ should be able to update a submission once
|
||||||
|
it has been created, or read a submission unless they have permission. You can
|
||||||
override this behavior or any other property as needed.
|
override this behavior or any other property as needed.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
@@ -232,7 +241,9 @@ formBuilderPlugin({
|
|||||||
// ...
|
// ...
|
||||||
handlePayment: async ({ form, submissionData }) => {
|
handlePayment: async ({ form, submissionData }) => {
|
||||||
// first calculate the price
|
// first calculate the price
|
||||||
const paymentField = form.fields?.find((field) => field.blockType === 'payment')
|
const paymentField = form.fields?.find(
|
||||||
|
(field) => field.blockType === 'payment',
|
||||||
|
)
|
||||||
const price = getPaymentTotal({
|
const price = getPaymentTotal({
|
||||||
basePrice: paymentField.basePrice,
|
basePrice: paymentField.basePrice,
|
||||||
priceConditions: paymentField.priceConditions,
|
priceConditions: paymentField.priceConditions,
|
||||||
@@ -248,9 +259,9 @@ formBuilderPlugin({
|
|||||||
Each field represents a form input. To override default settings pass either a boolean value or a partial [Payload Block](https://payloadcms.com/docs/fields/blocks) _keyed to the block's slug_. See [Field Overrides](#field-overrides) for more details on how to do this.
|
Each field represents a form input. To override default settings pass either a boolean value or a partial [Payload Block](https://payloadcms.com/docs/fields/blocks) _keyed to the block's slug_. See [Field Overrides](#field-overrides) for more details on how to do this.
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
**Note:**
|
**Note:** "Fields" here is in reference to the _fields to build forms with_,
|
||||||
"Fields" here is in reference to the _fields to build forms with_, not to be confused with the _fields
|
not to be confused with the _fields of a collection_ which are set via
|
||||||
of a collection_ which are set via `formOverrides.fields`.
|
`formOverrides.fields`.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### Text
|
### Text
|
||||||
@@ -458,7 +469,6 @@ Below are some common troubleshooting tips. To help other developers, please con
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@@ -10,12 +10,12 @@ keywords: plugins, multi-tenant, multi-tenancy, plugin, payload, cms, seo, index
|
|||||||
|
|
||||||
This plugin sets up multi-tenancy for your application from within your [Admin Panel](../admin/overview). It does so by adding a `tenant` field to all specified collections. Your front-end application can then query data by tenant. You must add the Tenants collection so you control what fields are available for each tenant.
|
This plugin sets up multi-tenancy for your application from within your [Admin Panel](../admin/overview). It does so by adding a `tenant` field to all specified collections. Your front-end application can then query data by tenant. You must add the Tenants collection so you control what fields are available for each tenant.
|
||||||
|
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
This plugin is completely open-source and the [source code can be found
|
This plugin is completely open-source and the [source code can be found
|
||||||
here](https://github.com/payloadcms/payload/tree/main/packages/plugin-multi-tenant). If you need
|
here](https://github.com/payloadcms/payload/tree/main/packages/plugin-multi-tenant).
|
||||||
help, check out our [Community Help](https://payloadcms.com/community-help). If you think you've
|
If you need help, check out our [Community
|
||||||
found a bug, please [open a new
|
Help](https://payloadcms.com/community-help). If you think you've found a bug,
|
||||||
|
please [open a new
|
||||||
issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%multi-tenant&template=bug_report.md&title=plugin-multi-tenant%3A)
|
issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%multi-tenant&template=bug_report.md&title=plugin-multi-tenant%3A)
|
||||||
with as much detail as possible.
|
with as much detail as possible.
|
||||||
</Banner>
|
</Banner>
|
||||||
@@ -32,10 +32,11 @@ This plugin sets up multi-tenancy for your application from within your [Admin P
|
|||||||
<Banner type="error">
|
<Banner type="error">
|
||||||
**Warning**
|
**Warning**
|
||||||
|
|
||||||
By default this plugin cleans up documents when a tenant is deleted. You should ensure you have
|
By default this plugin cleans up documents when a tenant is deleted. You should ensure you have
|
||||||
strong access control on your tenants collection to prevent deletions by unauthorized users.
|
strong access control on your tenants collection to prevent deletions by unauthorized users.
|
||||||
|
|
||||||
|
You can disabled this behavior by setting `cleanupAfterTenantDelete` to `false` in the plugin options.
|
||||||
|
|
||||||
You can disabled this behavior by setting `cleanupAfterTenantDelete` to `false` in the plugin options.
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
@@ -253,7 +254,6 @@ export default config
|
|||||||
|
|
||||||
The plugin scaffolds out everything you will need to separate data by tenant. You can use the `tenant` field to filter data from enabled collections in your front-end application.
|
The plugin scaffolds out everything you will need to separate data by tenant. You can use the `tenant` field to filter data from enabled collections in your front-end application.
|
||||||
|
|
||||||
|
|
||||||
In your frontend you can query and constrain data by tenant with the following:
|
In your frontend you can query and constrain data by tenant with the following:
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
@@ -336,11 +336,13 @@ type ContextType = {
|
|||||||
* @param args.id - The ID of the tenant to select
|
* @param args.id - The ID of the tenant to select
|
||||||
* @param args.refresh - Whether to refresh the page after changing the tenant
|
* @param args.refresh - Whether to refresh the page after changing the tenant
|
||||||
*/
|
*/
|
||||||
setTenant: (args: { id: number | string | undefined; refresh?: boolean }) => void
|
setTenant: (args: {
|
||||||
|
id: number | string | undefined
|
||||||
|
refresh?: boolean
|
||||||
|
}) => void
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
The [Examples Directory](https://github.com/payloadcms/payload/tree/main/examples) also contains an official [Multi-Tenant](https://github.com/payloadcms/payload/tree/main/examples/multi-tenant) example.
|
The [Examples Directory](https://github.com/payloadcms/payload/tree/main/examples) also contains an official [Multi-Tenant](https://github.com/payloadcms/payload/tree/main/examples/multi-tenant) example.
|
||||||
|
|||||||
@@ -26,9 +26,10 @@ but different parents.
|
|||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
This plugin is completely open-source and the [source code can be found
|
This plugin is completely open-source and the [source code can be found
|
||||||
here](https://github.com/payloadcms/payload/tree/main/packages/plugin-nested-docs). If you need
|
here](https://github.com/payloadcms/payload/tree/main/packages/plugin-nested-docs).
|
||||||
help, check out our [Community Help](https://payloadcms.com/community-help). If you think you've
|
If you need help, check out our [Community
|
||||||
found a bug, please [open a new
|
Help](https://payloadcms.com/community-help). If you think you've found a bug,
|
||||||
|
please [open a new
|
||||||
issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20nested-docs&template=bug_report.md&title=plugin-nested-docs%3A)
|
issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20nested-docs&template=bug_report.md&title=plugin-nested-docs%3A)
|
||||||
with as much detail as possible.
|
with as much detail as possible.
|
||||||
</Banner>
|
</Banner>
|
||||||
@@ -79,7 +80,8 @@ const config = buildConfig({
|
|||||||
nestedDocsPlugin({
|
nestedDocsPlugin({
|
||||||
collections: ['pages'],
|
collections: ['pages'],
|
||||||
generateLabel: (_, doc) => doc.title,
|
generateLabel: (_, doc) => doc.title,
|
||||||
generateURL: (docs) => docs.reduce((url, doc) => `${url}/${doc.slug}`, ''),
|
generateURL: (docs) =>
|
||||||
|
docs.reduce((url, doc) => `${url}/${doc.slug}`, ''),
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
@@ -165,9 +167,10 @@ own `breadcrumbs` field to each collection manually. Set this property to the `n
|
|||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
**Note:**
|
**Note:**
|
||||||
|
|
||||||
If you opt out of automatically being provided a `parent` or `breadcrumbs` field, you need to make
|
If you opt out of automatically being provided a `parent` or `breadcrumbs` field, you need to make
|
||||||
sure that both fields are placed at the top-level of your document. They cannot exist within any
|
sure that both fields are placed at the top-level of your document. They cannot exist within any
|
||||||
nested data structures like a `group`, `array`, or `blocks`.
|
nested data structures like a `group`, `array`, or `blocks`.
|
||||||
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Overrides
|
## Overrides
|
||||||
@@ -217,8 +220,9 @@ const examplePageConfig: CollectionConfig = {
|
|||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Note:**
|
**Note:**
|
||||||
|
|
||||||
If overriding the `name` of either `breadcrumbs` or `parent` fields, you must specify the
|
If overriding the `name` of either `breadcrumbs` or `parent` fields, you must specify the
|
||||||
`breadcrumbsFieldSlug` or `parentFieldSlug` respectively.
|
`breadcrumbsFieldSlug` or `parentFieldSlug` respectively.
|
||||||
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Localization
|
## Localization
|
||||||
@@ -232,7 +236,11 @@ the [Localization](https://payloadcms.com/docs/configuration/localization) docs.
|
|||||||
All types can be directly imported:
|
All types can be directly imported:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { PluginConfig, GenerateURL, GenerateLabel } from '@payloadcms/plugin-nested-docs/types'
|
import {
|
||||||
|
PluginConfig,
|
||||||
|
GenerateURL,
|
||||||
|
GenerateLabel,
|
||||||
|
} from '@payloadcms/plugin-nested-docs/types'
|
||||||
```
|
```
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|||||||
@@ -28,9 +28,9 @@ const config = buildConfig({
|
|||||||
Writing Plugins is no more complex than writing regular JavaScript. If you know the basic concept of [callback functions](https://developer.mozilla.org/en-US/docs/Glossary/Callback_function) or how [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) works, and are up to speed with Payload concepts, then writing a plugin will be a breeze.
|
Writing Plugins is no more complex than writing regular JavaScript. If you know the basic concept of [callback functions](https://developer.mozilla.org/en-US/docs/Glossary/Callback_function) or how [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) works, and are up to speed with Payload concepts, then writing a plugin will be a breeze.
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
Because we rely on a simple config-based structure, Payload Plugins simply take in an
|
Because we rely on a simple config-based structure, Payload Plugins simply
|
||||||
existing config and returns a _modified_ config with new fields, hooks, collections, admin views, or
|
take in an existing config and returns a _modified_ config with new fields,
|
||||||
anything else you can think of.
|
hooks, collections, admin views, or anything else you can think of.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
**Example use cases:**
|
**Example use cases:**
|
||||||
@@ -61,7 +61,9 @@ You can also [build your own plugin](./build-your-own) to easily extend Payload'
|
|||||||
Plugins are changing every day, so be sure to check back often to see what new plugins may have been added. If you have a specific plugin you would like to see, please feel free to start a new [Discussion](https://github.com/payloadcms/payload/discussions).
|
Plugins are changing every day, so be sure to check back often to see what new plugins may have been added. If you have a specific plugin you would like to see, please feel free to start a new [Discussion](https://github.com/payloadcms/payload/discussions).
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
For a complete list of Official Plugins, visit the [Packages Directory](https://github.com/payloadcms/payload/tree/main/packages) of the [Payload Monorepo](https://github.com/payloadcms/payload).
|
For a complete list of Official Plugins, visit the [Packages
|
||||||
|
Directory](https://github.com/payloadcms/payload/tree/main/packages) of the
|
||||||
|
[Payload Monorepo](https://github.com/payloadcms/payload).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Community Plugins
|
## Community Plugins
|
||||||
@@ -71,7 +73,9 @@ Community Plugins are those that are maintained entirely by outside contributors
|
|||||||
Some plugins have become so widely used that they are adopted as an [Official Plugin](#official-plugins), such as the [Lexical Plugin](https://github.com/AlessioGr/payload-plugin-lexical). If you have a plugin that you think should be an Official Plugin, please feel free to start a new [Discussion](https://github.com/payloadcms/payload/discussions).
|
Some plugins have become so widely used that they are adopted as an [Official Plugin](#official-plugins), such as the [Lexical Plugin](https://github.com/AlessioGr/payload-plugin-lexical). If you have a plugin that you think should be an Official Plugin, please feel free to start a new [Discussion](https://github.com/payloadcms/payload/discussions).
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
For maintainers building plugins for others to use, please add the `payload-plugin` topic on [GitHub](https://github.com/topics/payload-plugin) to help others find it.
|
For maintainers building plugins for others to use, please add the
|
||||||
|
`payload-plugin` topic on [GitHub](https://github.com/topics/payload-plugin)
|
||||||
|
to help others find it.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
@@ -85,15 +89,15 @@ import { addLastModified } from './addLastModified.ts'
|
|||||||
const config = buildConfig({
|
const config = buildConfig({
|
||||||
// ...
|
// ...
|
||||||
// highlight-start
|
// highlight-start
|
||||||
plugins: [
|
plugins: [addLastModified],
|
||||||
addLastModified,
|
|
||||||
],
|
|
||||||
// highlight-end
|
// highlight-end
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
Payload Plugins are executed _after_ the incoming config is validated, but before it is sanitized and has had default options merged in. After all plugins are executed, the full config with all plugins will be sanitized.
|
Payload Plugins are executed _after_ the incoming config is validated, but
|
||||||
|
before it is sanitized and has had default options merged in. After all
|
||||||
|
plugins are executed, the full config with all plugins will be sanitized.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
Here is an example what the `addLastModified` plugin from above might look like. It adds a `lastModifiedBy` field to all Payload collections. For full details, see [how to build your own plugin](./build-your-own).
|
Here is an example what the `addLastModified` plugin from above might look like. It adds a `lastModifiedBy` field to all Payload collections. For full details, see [how to build your own plugin](./build-your-own).
|
||||||
@@ -105,8 +109,8 @@ export const addLastModified: Plugin = (incomingConfig: Config): Config => {
|
|||||||
// Find all incoming auth-enabled collections
|
// Find all incoming auth-enabled collections
|
||||||
// so we can create a lastModifiedBy relationship field
|
// so we can create a lastModifiedBy relationship field
|
||||||
// to all auth collections
|
// to all auth collections
|
||||||
const authEnabledCollections = incomingConfig.collections.filter((collection) =>
|
const authEnabledCollections = incomingConfig.collections.filter(
|
||||||
Boolean(collection.auth),
|
(collection) => Boolean(collection.auth),
|
||||||
)
|
)
|
||||||
|
|
||||||
// Spread the existing config
|
// Spread the existing config
|
||||||
@@ -147,6 +151,6 @@ export const addLastModified: Plugin = (incomingConfig: Config): Config => {
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
**Reminder:**
|
**Reminder:** See [how to build your own plugin](./build-your-own) for a more
|
||||||
See [how to build your own plugin](./build-your-own) for a more in-depth explication on how create your own Payload Plugin.
|
in-depth explication on how create your own Payload Plugin.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|||||||
@@ -14,9 +14,10 @@ For example, if you have a page at `/about` and you want to change it to `/about
|
|||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
This plugin is completely open-source and the [source code can be found
|
This plugin is completely open-source and the [source code can be found
|
||||||
here](https://github.com/payloadcms/payload/tree/main/packages/plugin-redirects). If you need
|
here](https://github.com/payloadcms/payload/tree/main/packages/plugin-redirects).
|
||||||
help, check out our [Community Help](https://payloadcms.com/community-help). If you think you've
|
If you need help, check out our [Community
|
||||||
found a bug, please [open a new
|
Help](https://payloadcms.com/community-help). If you think you've found a bug,
|
||||||
|
please [open a new
|
||||||
issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%redirects&template=bug_report.md&title=plugin-redirects%3A)
|
issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%redirects&template=bug_report.md&title=plugin-redirects%3A)
|
||||||
with as much detail as possible.
|
with as much detail as possible.
|
||||||
</Banner>
|
</Banner>
|
||||||
@@ -63,7 +64,7 @@ export default config
|
|||||||
### Options
|
### Options
|
||||||
|
|
||||||
| Option | Type | Description |
|
| Option | Type | Description |
|
||||||
| ------------- | ---------- | ----------------------------------------------------------------------------------------------- |
|
| --------------------------- | ---------- | ------------------------------------------------------------------------------------------------------- |
|
||||||
| `collections` | `string[]` | An array of collection slugs to populate in the `to` field of each redirect. |
|
| `collections` | `string[]` | An array of collection slugs to populate in the `to` field of each redirect. |
|
||||||
| `overrides` | `object` | A partial collection config that allows you to override anything on the `redirects` collection. |
|
| `overrides` | `object` | A partial collection config that allows you to override anything on the `redirects` collection. |
|
||||||
| `redirectTypes` | `string[]` | Provide an array of redirects if you want to provide options for the type of redirects to be supported. |
|
| `redirectTypes` | `string[]` | Provide an array of redirects if you want to provide options for the type of redirects to be supported. |
|
||||||
|
|||||||
@@ -18,9 +18,10 @@ This plugin is a great way to implement a fast, immersive search experience such
|
|||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
This plugin is completely open-source and the [source code can be found
|
This plugin is completely open-source and the [source code can be found
|
||||||
here](https://github.com/payloadcms/payload/tree/main/packages/plugin-search). If you need help,
|
here](https://github.com/payloadcms/payload/tree/main/packages/plugin-search).
|
||||||
check out our [Community Help](https://payloadcms.com/community-help). If you think you've found a
|
If you need help, check out our [Community
|
||||||
bug, please [open a new
|
Help](https://payloadcms.com/community-help). If you think you've found a bug,
|
||||||
|
please [open a new
|
||||||
issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20search&template=bug_report.md&title=plugin-search%3A)
|
issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20search&template=bug_report.md&title=plugin-search%3A)
|
||||||
with as much detail as possible.
|
with as much detail as possible.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ This plugin allows you to integrate [Sentry](https://sentry.io/) seamlessly with
|
|||||||
Sentry is a powerful error tracking and performance monitoring tool that helps developers identify, diagnose, and resolve issues in their applications.
|
Sentry is a powerful error tracking and performance monitoring tool that helps developers identify, diagnose, and resolve issues in their applications.
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
Sentry does smart stuff with error data to make bugs easier to find and fix. - [sentry.io](https://sentry.io/)
|
Sentry does smart stuff with error data to make bugs easier to find and fix. -
|
||||||
|
[sentry.io](https://sentry.io/)
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
This multi-faceted software offers a range of features that will help you manage errors with greater ease and ultimately ensure your application is running smoothly:
|
This multi-faceted software offers a range of features that will help you manage errors with greater ease and ultimately ensure your application is running smoothly:
|
||||||
@@ -31,7 +32,13 @@ This multi-faceted software offers a range of features that will help you manage
|
|||||||
- **Integrations**: Connects with various tools and services for enhanced workflow and issue management
|
- **Integrations**: Connects with various tools and services for enhanced workflow and issue management
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
This plugin is completely open-source and the [source code can be found here](https://github.com/payloadcms/payload/tree/main/packages/plugin-sentry). If you need help, check out our [Community Help](https://payloadcms.com/community-help). If you think you've found a bug, please [open a new issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20seo&template=bug_report.md&title=plugin-sentry%3A) with as much detail as possible.
|
This plugin is completely open-source and the [source code can be found
|
||||||
|
here](https://github.com/payloadcms/payload/tree/main/packages/plugin-sentry).
|
||||||
|
If you need help, check out our [Community
|
||||||
|
Help](https://payloadcms.com/community-help). If you think you've found a bug,
|
||||||
|
please [open a new
|
||||||
|
issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20seo&template=bug_report.md&title=plugin-sentry%3A)
|
||||||
|
with as much detail as possible.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
@@ -43,12 +50,15 @@ Install the plugin using any JavaScript package manager like [pnpm](https://pnpm
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Sentry for Next.js setup
|
## Sentry for Next.js setup
|
||||||
|
|
||||||
This plugin requires to complete the [Sentry + Next.js setup](https://docs.sentry.io/platforms/javascript/guides/nextjs/) before.
|
This plugin requires to complete the [Sentry + Next.js setup](https://docs.sentry.io/platforms/javascript/guides/nextjs/) before.
|
||||||
|
|
||||||
You can use either the [automatic setup](https://docs.sentry.io/platforms/javascript/guides/nextjs/#install) with the installation wizard:
|
You can use either the [automatic setup](https://docs.sentry.io/platforms/javascript/guides/nextjs/#install) with the installation wizard:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npx @sentry/wizard@latest -i nextjs
|
npx @sentry/wizard@latest -i nextjs
|
||||||
```
|
```
|
||||||
|
|
||||||
Or the [Manual Setup](https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/)
|
Or the [Manual Setup](https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/)
|
||||||
|
|
||||||
## Basic Usage
|
## Basic Usage
|
||||||
@@ -81,7 +91,8 @@ export default config
|
|||||||
The `Sentry` instance
|
The `Sentry` instance
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
Make sure to complete the [Sentry for Next.js Setup](#sentry-for-nextjs-setup) before.
|
Make sure to complete the [Sentry for Next.js Setup](#sentry-for-nextjs-setup)
|
||||||
|
before.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
- `enabled`: boolean | optional
|
- `enabled`: boolean | optional
|
||||||
|
|||||||
@@ -15,7 +15,13 @@ As users are editing documents within the Admin Panel, they have the option to "
|
|||||||
To help you visualize what your page might look like in a search engine, a preview is rendered on the page just beneath the meta fields. This preview is updated in real-time as you edit your metadata. There are also visual indicators to help you write effective meta, such as a character counter for the title and description fields. You can even inject your own custom fields into the `meta` field group as your application requires, like `og:title` or `json-ld`. If you've ever used something like Yoast SEO, this plugin might feel very familiar.
|
To help you visualize what your page might look like in a search engine, a preview is rendered on the page just beneath the meta fields. This preview is updated in real-time as you edit your metadata. There are also visual indicators to help you write effective meta, such as a character counter for the title and description fields. You can even inject your own custom fields into the `meta` field group as your application requires, like `og:title` or `json-ld`. If you've ever used something like Yoast SEO, this plugin might feel very familiar.
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
This plugin is completely open-source and the [source code can be found here](https://github.com/payloadcms/payload/tree/main/packages/plugin-seo). If you need help, check out our [Community Help](https://payloadcms.com/community-help). If you think you've found a bug, please [open a new issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20seo&template=bug_report.md&title=plugin-seo%3A) with as much detail as possible.
|
This plugin is completely open-source and the [source code can be found
|
||||||
|
here](https://github.com/payloadcms/payload/tree/main/packages/plugin-seo). If
|
||||||
|
you need help, check out our [Community
|
||||||
|
Help](https://payloadcms.com/community-help). If you think you've found a bug,
|
||||||
|
please [open a new
|
||||||
|
issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20seo&template=bug_report.md&title=plugin-seo%3A)
|
||||||
|
with as much detail as possible.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Core features
|
## Core features
|
||||||
@@ -96,8 +102,8 @@ A function that takes in the default fields via an object and expects an array o
|
|||||||
{
|
{
|
||||||
name: 'customField',
|
name: 'customField',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -111,7 +117,10 @@ Set the `uploadsCollection` to your application's upload-enabled collection slug
|
|||||||
When the `tabbedUI` property is `true`, it appends an `SEO` tab onto your config using Payload's [Tabs Field](../fields/tabs). If your collection is not already tab-enabled, meaning the first field in your config is not of type `tabs`, then one will be created for you called `Content`. Defaults to `false`.
|
When the `tabbedUI` property is `true`, it appends an `SEO` tab onto your config using Payload's [Tabs Field](../fields/tabs). If your collection is not already tab-enabled, meaning the first field in your config is not of type `tabs`, then one will be created for you called `Content`. Defaults to `false`.
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
If you wish to continue to use top-level or sidebar fields with `tabbedUI`, you must not let the default `Content` tab get created for you (see the note above). Instead, you must define the first field of your config with type `tabs` and place all other fields adjacent to this one.
|
If you wish to continue to use top-level or sidebar fields with `tabbedUI`,
|
||||||
|
you must not let the default `Content` tab get created for you (see the note
|
||||||
|
above). Instead, you must define the first field of your config with type
|
||||||
|
`tabs` and place all other fields adjacent to this one.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
##### `generateTitle`
|
##### `generateTitle`
|
||||||
@@ -131,7 +140,7 @@ A function that allows you to return any meta title, including from the document
|
|||||||
All "generate" functions receive the following arguments:
|
All "generate" functions receive the following arguments:
|
||||||
|
|
||||||
| Argument | Description |
|
| Argument | Description |
|
||||||
| --- | --- |
|
| -------------------------- | --------------------------------------------------------------------- |
|
||||||
| **`collectionConfig`** | The configuration of the collection. |
|
| **`collectionConfig`** | The configuration of the collection. |
|
||||||
| **`collectionSlug`** | The slug of the collection. |
|
| **`collectionSlug`** | The slug of the collection. |
|
||||||
| **`doc`** | The data of the current document. |
|
| **`doc`** | The data of the current document. |
|
||||||
@@ -218,11 +227,20 @@ Rename the meta group interface name that is generated for TypeScript and GraphQ
|
|||||||
There is the option to directly import any of the fields from the plugin so that you can include them anywhere as needed.
|
There is the option to directly import any of the fields from the plugin so that you can include them anywhere as needed.
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
You will still need to configure the plugin in the Payload Config in order to configure the generation functions. Since these fields are imported and used directly, they don't have access to the plugin config so they may need additional arguments to work the same way.
|
You will still need to configure the plugin in the Payload Config in order to
|
||||||
|
configure the generation functions. Since these fields are imported and used
|
||||||
|
directly, they don't have access to the plugin config so they may need
|
||||||
|
additional arguments to work the same way.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { MetaDescriptionField, MetaImageField, MetaTitleField, OverviewField, PreviewField } from '@payloadcms/plugin-seo/fields'
|
import {
|
||||||
|
MetaDescriptionField,
|
||||||
|
MetaImageField,
|
||||||
|
MetaTitleField,
|
||||||
|
OverviewField,
|
||||||
|
PreviewField,
|
||||||
|
} from '@payloadcms/plugin-seo/fields'
|
||||||
|
|
||||||
// Used as fields
|
// Used as fields
|
||||||
MetaImageField({
|
MetaImageField({
|
||||||
@@ -261,7 +279,9 @@ OverviewField({
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
Tip: You can override the length rules by changing the minLength and maxLength props on the fields. In the case of the OverviewField you can use `titleOverrides` and `descriptionOverrides` to override the length rules.
|
Tip: You can override the length rules by changing the minLength and maxLength
|
||||||
|
props on the fields. In the case of the OverviewField you can use
|
||||||
|
`titleOverrides` and `descriptionOverrides` to override the length rules.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## TypeScript
|
## TypeScript
|
||||||
@@ -280,9 +300,9 @@ import type {
|
|||||||
You can then pass the collections from your generated Payload types into the generation types, for example:
|
You can then pass the collections from your generated Payload types into the generation types, for example:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import type { Page } from './payload-types.ts';
|
import type { Page } from './payload-types.ts'
|
||||||
|
|
||||||
import type { GenerateTitle } from '@payloadcms/plugin-seo/types';
|
import type { GenerateTitle } from '@payloadcms/plugin-seo/types'
|
||||||
|
|
||||||
const generateTitle: GenerateTitle<Page> = async ({ doc, locale }) => {
|
const generateTitle: GenerateTitle<Page> = async ({ doc, locale }) => {
|
||||||
return `Website.com — ${doc?.title}`
|
return `Website.com — ${doc?.title}`
|
||||||
|
|||||||
@@ -18,9 +18,10 @@ The beauty of this plugin is the entirety of your application's content and busi
|
|||||||
|
|
||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
This plugin is completely open-source and the [source code can be found
|
This plugin is completely open-source and the [source code can be found
|
||||||
here](https://github.com/payloadcms/payload/tree/main/packages/plugin-stripe). If you need help,
|
here](https://github.com/payloadcms/payload/tree/main/packages/plugin-stripe).
|
||||||
check out our [Community Help](https://payloadcms.com/community-help). If you think you've found a
|
If you need help, check out our [Community
|
||||||
bug, please [open a new
|
Help](https://payloadcms.com/community-help). If you think you've found a bug,
|
||||||
|
please [open a new
|
||||||
issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20stripe&template=bug_report.md&title=plugin-stripe%3A)
|
issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20stripe&template=bug_report.md&title=plugin-stripe%3A)
|
||||||
with as much detail as possible.
|
with as much detail as possible.
|
||||||
</Banner>
|
</Banner>
|
||||||
@@ -65,14 +66,14 @@ export default config
|
|||||||
|
|
||||||
| Option | Type | Default | Description |
|
| Option | Type | Default | Description |
|
||||||
| ------------------------------ | ------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------ |
|
| ------------------------------ | ------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| `stripeSecretKey` * | string | `undefined` | Your Stripe secret key |
|
| `stripeSecretKey` \* | string | `undefined` | Your Stripe secret key |
|
||||||
| `stripeWebhooksEndpointSecret` | string | `undefined` | Your Stripe webhook endpoint secret |
|
| `stripeWebhooksEndpointSecret` | string | `undefined` | Your Stripe webhook endpoint secret |
|
||||||
| `rest` | boolean | `false` | When `true`, opens the `/api/stripe/rest` endpoint |
|
| `rest` | boolean | `false` | When `true`, opens the `/api/stripe/rest` endpoint |
|
||||||
| `webhooks` | object or function | `undefined` | Either a function to handle all webhooks events, or an object of Stripe webhook handlers, keyed to the name of the event |
|
| `webhooks` | object or function | `undefined` | Either a function to handle all webhooks events, or an object of Stripe webhook handlers, keyed to the name of the event |
|
||||||
| `sync` | array | `undefined` | An array of sync configs |
|
| `sync` | array | `undefined` | An array of sync configs |
|
||||||
| `logs` | boolean | `false` | When `true`, logs sync events to the console as they happen |
|
| `logs` | boolean | `false` | When `true`, logs sync events to the console as they happen |
|
||||||
|
|
||||||
_* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
## Endpoints
|
## Endpoints
|
||||||
|
|
||||||
@@ -111,14 +112,16 @@ If you need to proxy the API server-side, use the [stripeProxy](#node) function.
|
|||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
**Note:**
|
**Note:**
|
||||||
|
|
||||||
The `/api` part of these routes may be different based on the settings defined in your Payload
|
The `/api` part of these routes may be different based on the settings defined in your Payload
|
||||||
config.
|
config.
|
||||||
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Warning:**
|
**Warning:**
|
||||||
|
|
||||||
Opening the REST proxy endpoint in production is a potential security risk. Authenticated users will have open access to the Stripe REST API. In production, open your own endpoint and use the [stripeProxy](#node) function to proxy the Stripe API server-side.
|
Opening the REST proxy endpoint in production is a potential security risk. Authenticated users will have open access to the Stripe REST API. In production, open your own endpoint and use the [stripeProxy](#node) function to proxy the Stripe API server-side.
|
||||||
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Webhooks
|
## Webhooks
|
||||||
@@ -182,7 +185,9 @@ On the server you should interface with Stripe directly using the [stripe](https
|
|||||||
import Stripe from 'stripe'
|
import Stripe from 'stripe'
|
||||||
|
|
||||||
const stripeSecretKey = process.env.STRIPE_SECRET_KEY
|
const stripeSecretKey = process.env.STRIPE_SECRET_KEY
|
||||||
const stripe = new Stripe(stripeSecretKey, { apiVersion: '2022-08-01' })
|
const stripe = new Stripe(stripeSecretKey, {
|
||||||
|
apiVersion: '2022-08-01',
|
||||||
|
})
|
||||||
|
|
||||||
export const MyFunction = async () => {
|
export const MyFunction = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -234,8 +239,9 @@ This option will setup a basic sync between Payload collections and Stripe resou
|
|||||||
<Banner type="info">
|
<Banner type="info">
|
||||||
**Note:**
|
**Note:**
|
||||||
|
|
||||||
If you wish to enable a _two-way_ sync, be sure to setup [`webhooks`](#webhooks) and pass the
|
If you wish to enable a _two-way_ sync, be sure to setup [`webhooks`](#webhooks) and pass the
|
||||||
`stripeWebhooksEndpointSecret` through your config.
|
`stripeWebhooksEndpointSecret` through your config.
|
||||||
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
@@ -270,10 +276,11 @@ export default config
|
|||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
**Note:**
|
**Note:**
|
||||||
|
|
||||||
Due to limitations in the Stripe API, this currently only works with top-level fields. This is
|
Due to limitations in the Stripe API, this currently only works with top-level fields. This is
|
||||||
because every Stripe object is a separate entity, making it difficult to abstract into a simple
|
because every Stripe object is a separate entity, making it difficult to abstract into a simple
|
||||||
reusable library. In the future, we may find a pattern around this. But for now, cases like that
|
reusable library. In the future, we may find a pattern around this. But for now, cases like that
|
||||||
will need to be hard-coded.
|
will need to be hard-coded.
|
||||||
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
Using `sync` will do the following:
|
Using `sync` will do the following:
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user