You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(plugin-form-builder): add support for multi part uploads (#15268)
Adds support for multi part uploads directly in the plugin, this makes
it so you don't need to upload documents separately and instead the form
submissions themselves can handle this part.
Before
```ts
// Step 1: upload the file
const uploadForm = new FormData()
uploadForm.append('file', imageFile)
const { doc: media } = await fetch('/api/media', {
method: 'POST',
body: uploadForm,
}).then(r => r.json())
// Step 2: submit the form with the pre-uploaded ID
await fetch('/api/form-submissions', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
form: formId,
submissionData: [
{ field: 'fullName', value: 'Alice' },
{ field: 'avatar', value: media.id }, // string ID only
],
}),
})
```
After
```ts
const formData = new FormData()
formData.append('_payload', JSON.stringify({
form: formId,
submissionData: [{ field: 'fullName', value: 'Alice' }],
}))
formData.append('avatar', imageFile) // keyed by field name
await fetch('/api/form-submissions', {
method: 'POST',
body: formData,
})
```
Copy file name to clipboardExpand all lines: docs/plugins/form-builder.mdx
+179Lines changed: 179 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -88,6 +88,9 @@ formBuilderPlugin({
88
88
message: true,
89
89
date: false,
90
90
payment: false,
91
+
upload: {
92
+
uploadCollections: ['media', 'documents'], // Required when using upload
93
+
},
91
94
},
92
95
})
93
96
```
@@ -441,6 +444,180 @@ Each of the `priceConditions` are executed by the `getPaymentTotal` utility that
441
444
|`valueType`| string | The type of value to use to determine the price. |
442
445
|`value`| string | The value to use to determine the price. |
443
446
447
+
### Upload
448
+
449
+
Add this field to your form to collect file uploads. Files are stored in a specified upload-enabled collection, and the file ID is stored as the submission value. This field is disabled by default and must be explicitly enabled.
|`uploadCollection`| string \*| The slug of the upload-enabled collection to store files in. |
456
+
|`mimeTypes`| array | An array of allowed MIME types (e.g., `image/*`, `application/pdf`). Empty allows all types. |
457
+
|`maxFileSize`| number | Maximum file size in bytes. Leave empty for no limit. |
458
+
|`width`| number | The width of the field as a percentage (e.g., `50` for 50%). |
459
+
|`required`| checkbox | Whether or not the field is required when submitted. |
460
+
|`multiple`| checkbox | Whether to allow multiple file uploads. |
461
+
462
+
#### Enabling Upload Fields
463
+
464
+
To use upload fields, enable the `upload` field and provide `uploadCollections` at the top level of the plugin config:
465
+
466
+
```ts
467
+
// payload.config.ts
468
+
formBuilderPlugin({
469
+
fields: {
470
+
upload: true,
471
+
},
472
+
uploadCollections: ['media', 'documents'], // Required — available upload collections
473
+
})
474
+
```
475
+
476
+
#### Frontend Implementation
477
+
478
+
The simplest way to handle upload fields is to submit files directly with the form as `multipart/form-data`. The form builder will automatically upload files to the appropriate collection and store the file IDs in the submission.
479
+
480
+
```ts
481
+
asyncfunction submitFormWithFiles(
482
+
formId:string,
483
+
fields:FormField[],
484
+
values:Record<string, any>,
485
+
) {
486
+
const formData =newFormData()
487
+
488
+
// Build submission data for non-file fields
489
+
const submissionData = []
490
+
491
+
for (const field offields) {
492
+
if (field.blockType==='upload') {
493
+
// Files are appended to FormData separately using the field name
1. Validate MIME types and file sizes against the field configuration
523
+
2. Upload files to the specified upload collection
524
+
3. Store the created file IDs in the submission data
525
+
526
+
#### Alternative: Pre-upload Files
527
+
528
+
If you prefer more control over the upload process (e.g., for progress tracking or resumable uploads), you can upload files separately and submit their IDs:
If your upload collection uses a storage adapter with `clientUploads` enabled (e.g., S3, Azure, GCS), you can upload files directly to cloud storage using presigned URLs for better performance with large files:
You can provide your own custom fields by passing a new [Payload Block](https://payloadcms.com/docs/fields/blocks#block-configs) object into `fields`. You can override or extend any existing fields by first importing the `fields` from the plugin:
0 commit comments