Editor
Editor component.
Editor, Customization Blocks
Insert link
Insert image
<x-editor />
Before continuing, it is important to know:
- The component can be used inside or outside Livewire.
- Inside Livewire, use wire:model to bind the content.
- In a normal form, use name . The HTML is mirrored into a hidden input.
- Without a wire:model or name , the component will throw an exception.
- The default output is raw HTML content, but you can stamp a class on every element. Learn more about it below.
The default output of the editor is raw HTML content. Tailwind's Preflight strips the list markers and the heading sizes, so the same markup reads as plain lines once it is rendered anywhere else. output-classes stamps a class on every element the editor writes, so the content can be styled wherever it lands.
Insert link
Insert image
<x-editor output-classes />
After enable output-classes , every element will carries a class of its own:
<ol class="tsui-editor-numeric-list"> <li class="tsui-editor-list-item">…</li></ol>
So you will be able to customize the output of the editor with your own CSS, for example:
.tsui-editor-numeric-list { @apply my-2 list-decimal pl-6; }.tsui-editor-heading-1 { @apply text-3xl font-bold; }.tsui-editor-paragraph { @apply my-2; }
An array changes only the tags it lists and leaves the rest alone. A name has to keep the prefix, which is what the sanitizer recognizes on the way back in, and anything else throws.
<x-editor :output-classes="['ol' => 'tsui-editor-steps']" />
A string is the prefix itself:
<x-editor output-classes="blog-" />
<ol class="blog-numeric-list"> <li class="blog-list-item">…</li></ol>
Without a string, the prefix comes from output_classes_prefix in the configuration file when output_classes is enable , defaulting to tsui-editor- . The option is off by default, under output_classes , and ignored while markdown is on, since Markdown carries no classes.
// ... 'editor' => [ Components\Editor\Component::class, // ... [ 'markdown' => false, 'output_classes' => true, 'output_classes_prefix' => null, 'toolbar' => [/* ... */], // ...// ...
The default tags and classes are:
The stamp is authoritative rather than incremental. On the way in and after every command the classes are wiped and written again from the tag, so a renamed class, a duplicate, and a class the browser carried onto the wrong element all settle on the next pass. Turning it off stops the stamping, it does not rewrite what is stored.
An option to display a label and a hint below the editor.
Insert link
Insert image
<x-editor label="Article" hint="Keep it under a thousand words" />
Twenty buttons across eight groups. Dividers sit between groups. An unknown slug throws.
Insert link
Insert image
<x-editor :toolbar="['style', 'bold', 'italic', 'link', 'image']" />
An option to set min-height and max-height. Any CSS unit. Defaults to 12rem and 40rem.
Insert link
Insert image
<x-editor min-height="20rem" max-height="60vh" />
An option to lock the editor. They cannot be used together.
<x-editor readonly /> <x-editor disabled />
An option to display word and line counters in the footer. On by default.
Insert link
Insert image
<x-editor :counters="false" />
The editor stays a WYSIWYG. The bound property stores Markdown instead of HTML.
Insert link
Insert image
<x-editor markdown />
Tables, task lists and footnotes are not covered, in either direction.
Applied as you type. Ctrl+Z undoes the formatting and keeps the characters. Nothing changes inside a code block.
An option to allow upload of image using normal Livewire way
<x-editor upload-property="picture" upload-method="storeImage" />
use Livewire\WithFileUploads; class PostForm extends Component{ use WithFileUploads; public string $content = ''; public $picture = null; public function storeImage(): string { $this->validate(['picture' => ['image', 'max:5120']]); return asset('storage/'.$this->picture->store('posts', 'public')); }}
<x-editor x-on:editor:change="words = $event.detail.words" x-on:editor:link-inserted="console.log($event.detail.href)" x-on:editor:image-inserted="console.log($event.detail.src)" x-on:editor:fullscreen-toggled="console.log($event.detail.on)" />
The sanitizer is defense in depth, not the defense.
The sanitizer strips tags, attributes and style properties outside the configured whitelist, over pasted markup and over the value the editor boots with. The stamped output classes are the one exception: they pass whether the option is on or off, bounded by the prefix. href and src are additionally checked by scheme. allowed_styles is applied after allowed_attributes , so widening the tags that may carry a style cannot widen what that style does. SVG is deliberately absent from the default upload mimes.
There are a lot things that can be configured using the configuration file. For example, you can turn markdown or output-classes on for every editor, or set the default toolbar , output_classes_prefix and heights. The default min-height is 12rem and the default max-height is 40rem in the configuration file.
The editor component reuse other components internally, such as modal and dropdown . You can customize the internal components by using the scopes following the guide of the soft customization .
// The two dialogs are <x-modal> instances under a fixed scopeTallStackUi::customize('modal', scope: 'editor.modal.link') ->block('wrapper.fourth', 'rounded-2xl'); TallStackUi::customize('modal', scope: 'editor.modal.image') ->block('wrapper.fourth', 'rounded-2xl'); // The toolbar dropdowns are <x-dropdown> instancesTallStackUi::customize('dropdown', scope: 'editor.toolbar') ->block('slot.wrapper', 'p-1');