Implementing Image Upload with CKEditor in Vue 2
Setting Up CKEditor 5 with Image Upload in Vue 2
This guide covers integrating CKEditor 5 into a Vue 2 project and implementing custom image upload functionality.
Installation
First, install the Vue 2 wrapper for CKEditor 5:
npm i @ckeditor/ckeditor5-vue2
Building Custom CKEditor SDK
Download the CKEditor 5 online builder from the official website and customize your build with required plugins. After configuration, build the package:
npm install
npm run build
The built ckeditor.js file will be located in the build directory. Place this file in your project's public folder and include it via script tag in your index.html.
Creating Custom Upload Adapter
CKEditor 5 requires a custom adapter to handle image uploads. Create a new file MyUploadAdapter.js:
import axios from 'axios';
export default class MyUploadAdapter {
constructor(loader, uploadUrl, authToken) {
this.loader = loader;
this.uploadUrl = uploadUrl;
this.authToken = authToken;
}
async upload() {
return this.uploadFile(this.loader.file);
}
async uploadFile(file) {
const formData = new FormData();
formData.append('file', file);
const response = await axios({
url: this.uploadUrl,
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
},
data: {
fileBinaryData: formData,
uploadToken: this.authToken,
fileName: file.name,
},
});
return {
default: response.data.url,
};
}
abort() {
// Implement abort logic if needed
}
}
Vue 2 Component Integration
Create the editor compoennt with the custom adapter:
<template>
<div>
<ckeditor
:editor="editorInstance"
v-model="content"
:disabled="isReadOnly"
:config="editorConfig"
@ready="handleEditorReady"
@focus="handleEditorFocus"
@blur="handleEditorBlur"
@input="handleEditorInput"
@destroy="handleEditorDestroy"
></ckeditor>
</div>
</template>
<script>
import MyUploadAdapter from './MyUploadAdapter.js';
export default {
name: 'CKEditorWrapper',
props: {
initialContent: {
type: String,
default: '',
},
isReadOnly: {
type: Boolean,
default: false,
},
},
data() {
return {
editorInstance: ClassicEditor,
content: this.initialContent,
uploadUrl: '',
authToken: '',
editorConfig: {
toolbar: [
'heading',
'|',
'fontFamily',
'fontSize',
'fontColor',
'fontBackgroundColor',
'|',
'bold',
'italic',
'underline',
'strikethrough',
'|',
'alignment:left',
'alignment:right',
'alignment:center',
'alignment:justify',
'|',
'numberedList',
'bulletedList',
'|',
'outdent',
'indent',
'|',
'link',
'blockquote',
'insertTable',
'imageUpload',
'mediaEmbed',
'htmlEmbed',
'|',
'undo',
'redo',
],
image: {
toolbar: [
'imageTextAlternative',
'imageStyle:inline',
'imageStyle:block',
'imageStyle:side',
],
},
language: 'en',
},
};
},
methods: {
handleEditorReady(editor) {
editor.plugins.get('FileRepository').createUploadAdapter = (loader) => {
return new MyUploadAdapter(loader, this.uploadUrl, this.authToken);
};
},
handleEditorFocus(event) {
this.$emit('focus', event);
},
handleEditorBlur(event) {
this.$emit('blur', event);
},
handleEditorInput(data) {
this.$emit('input', data);
},
handleEditorDestroy() {
this.$emit('destroy');
},
},
};
</script>
Key Configuration Points
The imageUpload plugin must be included in the toolbar configuration. In the ready event handler, override the default upload adapter by assigning your custom adapter to the FileRepository plugin.
The adapter receives the file loader instance, your upload endpoint URL, and authentication token. It returns the uploaded image URL in the response format expected by CKEditor.
This implementation provides full control over the upload process while maintaining CKEditor 5's standard integration pattern.