Installation
composer require mati365/ckeditor5-livewire
npm install --save-dev @ckeditor/ckeditor5-build-classic
Publish assets (if needed):
php artisan vendor:publish --provider="Mati365\Ckeditor5Livewire\Ckeditor5LivewireServiceProvider" --tag=public
Basic Livewire Component Usage
use Mati365\Ckeditor5Livewire\Ckeditor5Livewire;
public $content = '<p>Hello World!</p>';
public function mount()
{
$this->content = '<p>Default content</p>';
}
public function render()
{
return view('livewire.example', [
'editor' => Ckeditor5Livewire::make('content')
->config([
'language' => 'en',
'toolbar' => ['heading', '|', 'bold', 'italic', 'bulletedList']
])
]);
}
Blade Form Integration
<form wire:submit.prevent="save">
{!! $editor !!}
<button type="submit">Save</button>
</form>
Replace a <textarea> with a rich editor in a Livewire form for blog posts or CMS content. The package handles real-time updates via Livewire’s reactivity.
Dynamic Editor Configuration
Use config() to customize editor behavior per component:
Ckeditor5Livewire::make('content')
->config([
'language' => $this->user->locale,
'plugins' => ['Image', 'Table'],
'image' => [
'upload' => [
'types' => ['jpeg', 'png'],
'url' => route('upload.image')
]
]
]);
Reusable Editor Components Create a base component for shared configurations:
// BaseEditor.php
class BaseEditor extends Component
{
public function getEditor()
{
return Ckeditor5Livewire::make('content')
->config(config('ckeditor.default_config'))
->allowedFileExtensions(['jpg', 'png', 'pdf']);
}
}
Handling File Uploads Pair with a Livewire upload handler:
// UploadHandler.php
public function uploadImage()
{
$this->validate(['upload' => 'required|image']);
$path = $this->upload->store('uploads');
return ['url' => asset($path)];
}
Localization Load translations dynamically:
Ckeditor5Livewire::make('content')
->config([
'language' => app()->getLocale(),
'languageForContent' => app()->getLocale()
]);
wire:ignore for non-Livewire JS:
<div wire:ignore>
<script>
document.addEventListener('livewire:init', () => {
Livewire.hook('editor.ready', (editor) => {
editor.ui.getEditableElement().parentElement.style.border = '1px solid #ccc';
});
});
</script>
</div>
Illuminate\Support\Str::of($this->content)->markdown() or a package like spatie/laravel-html-sanitizer.Asset Loading Conflicts
@ckeditor/ckeditor5-build-classic is installed only once (check node_modules and vendor).npm cache clean --force) and rebuild assets.Livewire Reactivity Delays
wire:model.live or trigger a manual update:
Livewire.hook('editor.contentUpdated', (editor) => {
editor.model.document.getRoot().getChild(0).setHtml(editor.data);
});
CSRF Token Mismatch
419 errors.@livewireScripts
@stack('scripts')
Custom Builds Not Loading
@ckeditor/ckeditor5-build-balloon) fail silently.'build_path' => public_path('vendor/ckeditor5-custom-build/build.js'),
Console tab) and verify CKEditor logs no errors. Look for:
console.log('CKEditor initialized:', window.CKEDITOR);
Livewire::configureLogging(function () {
return [
'driver' => 'single',
'path' => storage_path('logs/livewire.log'),
'level' => 'debug',
];
});
Custom Plugins
Add plugins via config():
->config([
'plugins' => ['MyCustomPlugin'],
'extraPlugins' => ['myplugin']
]);
Register the plugin in your JS:
import MyCustomPlugin from './MyCustomPlugin';
ClassicEditor.create(document.querySelector('#editor'), {
extraPlugins: [MyCustomPlugin]
});
Event Listeners Hook into editor events via Livewire’s JS hooks:
Livewire.hook('editor.ready', (editor) => {
editor.model.document.on('change:data', () => {
editor.data = editor.model.document.getData();
});
});
Server-Side Processing
Use Livewire’s updated* methods to process HTML:
public function updatedContent($value)
{
$this->content = Str::of($value)->replaceMatches('/<img[^>]+src="([^"]+)"/', function ($match) {
return '<img src="' . asset('storage/' . ltrim($match[1], '/')) . '">';
});
}
config/ckeditor.php:
'default_config' => [
'removePlugins' => ['ImageUpload'], // Disable by default
'toolbar' => ['heading', '|', 'bold', 'italic']
],
$config = array_merge(
config('ckeditor.default_config'),
['language' => $this->user->locale]
);
Ckeditor5Livewire::make('content')->config($config);
How can I help you explore Laravel packages today?