TinyMCE als Livewire Component
Laravel Livewire ist eine massive Arbeitserleichterung für dynamische Webapps. Aber bei der Kombination mit externen JavaScript-Bibliotheken wie TinyMCE gibt es eine Falle: Livewire und der Editor kämpfen um die Kontrolle über das DOM.
Das Problem: Livewire zerstört den Editor
Livewire ersetzt bei jedem Server-Roundtrip die DOM-Elemente seiner Komponente. Wenn TinyMCE an ein <textarea> innerhalb einer Livewire-Komponente gebunden ist, wird die TinyMCE-Instanz bei jedem Update zerstört und müsste neu initialisiert werden. Der Editor verliert den Fokus, der Cursor springt, Undo-History geht verloren – in der Praxis unbenutzbar.
Das gleiche Problem betrifft übrigens alle JavaScript-Bibliotheken, die eigene DOM-Elemente erzeugen: Quill, CKEditor, CodeMirror, Select2, Flatpickr. Die Lösung ist identisch.
Die Lösung: wire:ignore + Events
Zwei Mechanismen lösen das Problem:
wire:ignore– Verhindert, dass Livewire den umschlossenen DOM-Bereich bei Updates anfasst. TinyMCE behält die Kontrolle über sein<textarea>.@this.set()– Über denchange-Event von TinyMCE synchronisieren wir den Editor-Inhalt manuell zurück in die Livewire-Property.
Implementation
<!-- Blade-Template -->
<div>
<div wire:ignore>
<textarea id="editor" wire:model="document">{{ $document }}</textarea>
</div>
<button type="submit" wire:click="save">Speichern</button>
@script
<script>
tinymce.init({
selector: '#editor',
license_key: 'gpl',
setup: function (editor) {
editor.on('change input', function () {
$wire.set('document', editor.getContent());
});
}
});
</script>
@endscript
</div>Language:html
Was hier passiert
wire:ignoreauf dem Container-Div schützt die Textarea vor Livewire-Morphing.@scriptist Livewire 3 Syntax – das Script wird automatisch evaluiert, auch wenn die Komponente via Turbolinks/navigate geladen wird. In Livewire 2 müsste man stattdessenwindow.addEventListener('livewire:load', ...)verwenden.$wire.set()(Livewire 3) ersetzt@this.set()(Livewire 2). Beide setzen eine PHP-Property direkt vom JavaScript aus.license_key: 'gpl'– Seit TinyMCE 7 (2024) ist die Community-Edition unter GPL lizenziert. Ohne diesen Key zeigt TinyMCE eine Warnmeldung. Für kommerzielle Projekte, die nicht GPL-kompatibel sind, brauchen Sie einen kostenpflichtigen API-Key.
Häufige Stolperfallen
Mehrere Editoren auf einer Seite: Der Selector '#editor' funktioniert nur für ein Element. Bei mehreren TinyMCE-Instanzen (z.B. in einer Livewire-Schleife) brauchen Sie einen dynamischen Selector wie '.tinymce-editor' und müssen jede Instanz einzeln mit tinymce.get() ansprechen.
Initiales Laden: Wenn $document serverseitig befüllt ist, muss der Inhalt als Value der Textarea gerendert werden ({{ $document }}), nicht per wire:model allein – denn Livewire hydratisiert erst nach dem initialen Render.
Filament-Alternative: Wer Filament nutzt, braucht TinyMCE in vielen Fällen nicht. Filaments eingebauter Rich-Text-Editor (basierend auf Tiptap) ist Livewire-nativ und hat das DOM-Problem nicht. TinyMCE lohnt sich, wenn Sie spezifische Features brauchen (Templates, Mail-Merge, erweiterte Tabellen), die Tiptap nicht bietet.
Das allgemeine Pattern
Die Kombination wire:ignore + manueller Event-Sync funktioniert für jede JavaScript-Bibliothek, die eigene DOM-Elemente erzeugt. Das Pattern ist immer gleich:
Container mit
wire:ignoreumschließenJS-Bibliothek im
@script-Block initialisierenÄnderungen per
$wire.set()zurück an Livewire synchronisierenFalls nötig:
$wire.on()für serverseitige Updates, die den Editor-Inhalt ändern sollen
Dokumentation: Livewire wire:ignore | TinyMCE Laravel Integration
Keine Treffer Ein Treffer
Zu viele Suchanfragen in kurzer Zeit. Die Suche ist gerade nicht erreichbar.
Bitte warten Sie einen Moment, dann geht es weiter. Bitte versuchen Sie es in einem Moment noch einmal.
Keine Treffer für „“
Versuchen Sie einen anderen Begriff oder schreiben Sie uns direkt.
Kontaktformular