Composer and rich text
Neither Composer nor RichText ships an editor. They define value and upload behavior; your application connects its preferred text area, message composer, or rich-text editor through the matching controller.
| Field | Submitted value |
|---|---|
Composer without attachments | string or null |
Composer with attachments | { text: string, attachments: array } |
RichText | HTML string; optional images use a separate token array |
Route::inertiaFormUploads() as shown in the uploads guide.Composer attachments
Enable attachments and configure them with the same upload options as a File field.
use Inertify\Form\Fields\Composer;
Composer::make('message')
->maxLength(5_000)
->allowAttachments()
->acceptedFileTypes(['image/png', 'application/pdf'])
->maxFileSize(5 * 1024)
->reorderable();
useComposer(name, form) exposes text, attachments, attachmentUploadState, setText(), setAttachments(), uploadAttachments(), removeAttachment(), and reorderAttachment().
<script setup lang="ts">
import { useComposer, type FormFieldSlotProps } from '@inertify/form-vue'
const props = defineProps<FormFieldSlotProps>()
const composer = useComposer(props.name, props.form)
function attach(event: Event) {
const input = event.currentTarget as HTMLInputElement
if (input.files) {
void composer.uploadAttachments(input.files)
}
}
</script>
<template>
<textarea v-model="composer.text.value" @blur="blur" />
<input v-if="composer.allowAttachments.value" type="file" multiple @change="attach">
</template>
After server validation, validated(files: false) retains message.text and removes message.attachments for every upload strategy. Resolve token-based attachments using their qualified message.attachments upload path. For native attachments configured with storeWithForm(), use validated() with its default files: true value or read Laravel's request file bag.
Rich-text image uploads
RichText always submits an HTML string. imageUploads() adds a companion array named <field>_images; for body, the path is body_images.
use Inertify\Form\Fields\RichText;
use Inertify\Form\Fields\UploadConfig;
RichText::make('body')
->maxLength(50_000)
->imageUploads(
fn (UploadConfig $images): UploadConfig => $images
->maxSize(2 * 1024)
->directToStorage('private'),
);
Use useRichText(name, form) to access html, images, imageUploadState, setHtml(), clearContent(), uploadImages(), removeImage(), and reorderImage().
When the controller returns an uploaded file, insert an image into the editor with its token in data-inertia-forms-upload. Keep the companion token list synchronized; the controller does this when uploading and removing images.
<img
src="blob:https://example.test/local-preview"
alt="Diagram"
data-inertia-forms-upload="encrypted-upload-token"
>
The server compares unique token sets: every HTML marker token must appear in the companion array and vice versa. Ordering and duplicate entries are ignored.
Store and rewrite images
After form validation, store each submitted image and replace its temporary marker. Passing deleteTemporary: false lets RichTextUploads delete every token only after the complete rewrite succeeds.
use Inertify\Form\RichText\RichTextImage;
use Inertify\Form\RichText\RichTextUploads;
use Inertify\Form\Uploads\SubmittedUpload;
$data = $form->validated(files: false);
$data['body'] = RichTextUploads::from(request(), 'body')
->storeImagesUsing(function (
SubmittedUpload $upload,
RichTextImage $image,
): RichTextImage {
$path = $upload->store(
'post-images',
'private',
deleteTemporary: false,
);
return $image->identifier($path, ['disk' => 'private']);
})
->keepTokenized()
->toHtml();
keepTokenized() removes the temporary src and stores a versioned data-inertia-forms-image marker containing your identifier and metadata. If public URLs are stable, return $image->src($url) and omit keepTokenized() instead. storeImagesInMediaLibrary() is the optional Media Library shortcut.
Resolve stored images
For tokenized HTML, replace stored markers with fresh URLs before sending content to the browser:
use Illuminate\Support\Facades\Storage;
use Inertify\Form\RichText\RichTextContent;
use Inertify\Form\RichText\RichTextImage;
use Inertify\Form\RichText\RichTextStoredImage;
$body = RichTextContent::from($post->body)
->replaceImagesUsing(function (
RichTextStoredImage $stored,
RichTextImage $image,
): RichTextImage {
$disk = (string) $stored->meta('disk', 'private');
$url = Storage::disk($disk)->temporaryUrl(
$stored->identifier(),
now()->addMinutes(5),
);
return $image->src($url);
})
->toHtml();