---
menu-title: Vue.js 3+ component
category: builds-integration-frameworks
order: 50
---

# Rich text editor component for Vue.js 3+

[![npm version](https://badge.fury.io/js/%40ckeditor%2Fckeditor5-vue.svg)](https://www.npmjs.com/package/@ckeditor/ckeditor5-vue)

<info-box>
	**Important**: This guide is about the CKEditor 5 integration with Vue.js 3+. To learn more about the integration with Vue.js 2.x, check out the {@link builds/guides/frameworks/vuejs-v2 "Rich text editor component for Vue.js 2.x"} guide.
</info-box>

CKEditor 5 consists of the {@link builds/guides/overview ready-to-use editor builds} and the {@link framework/guides/overview CKEditor 5 Framework} upon which the builds are based.

The easiest way to use CKEditor 5 in your Vue.js application is by choosing one of the {@link builds/guides/overview#available-builds rich text editor builds} and simply passing it to the configuration of the Vue.js component. Read more about this solution in the [Quick start](#quick-start) section of this guide.

Additionally, you can [integrate CKEditor 5 from source](#using-ckeditor-from-source) which is a much more flexible and powerful solution, but requires some additional configuration.

## Quick start

Install the [CKEditor 5 WYSIWYG editor component for Vue.js](https://www.npmjs.com/package/@ckeditor/ckeditor5-vue) and the {@link builds/guides/overview#available-builds editor build of your choice}.

Assuming that you picked [`@ckeditor/ckeditor5-build-classic`](https://www.npmjs.com/package/@ckeditor/ckeditor5-build-classic):

```bash
npm install --save @ckeditor/ckeditor5-vue @ckeditor/ckeditor5-build-classic
```

You now need to enable the CKEditor component in your application. There are 2 ways to do so:

* [via a direct script include](#direct-script-include),
* [by using ES6 module imports](#using-es6-modules).

Optionally, you can [use the component locally](#using-the-component-locally).

### Direct script include

This is the quickest way to start using CKEditor in your project. Assuming [Vue is installed](https://v3.vuejs.org/guide/installation.html), include the `<script>` tags for the WYSIWYG editor component and the build:

```html
<script src="../node_modules/@ckeditor/ckeditor5-build-classic/build/ckeditor.js"></script>
<script src="../node_modules/@ckeditor/ckeditor5-vue/dist/ckeditor.js"></script>
```

Enable the component globally in your application using the [application instance](https://v3.vuejs.org/guide/instance.html#creating-an-application-instance):

```js
Vue.createApp( { /* options */ } ).use( CKEditor ).mount( /* DOM element */ );
```

<info-box>
	Instead of calling the `use()` method to install CKEditor component globally, you can always [use the component locally](#using-the-component-locally).
</info-box>

Use the `<ckeditor>` component in your template:

* The [`editor`](#editor) directive specifies the editor build.
* The [`v-model`](#v-model) directive enables an out–of–the–box two–way data binding.
* The [`config`](#config) directive helps you pass the configuration to the editor instance.

```html
<div id="app">
	<ckeditor :editor="editor" v-model="editorData" :config="editorConfig"></ckeditor>
</div>
```

```js
Vue.createApp( {
	data() {
		editor: ClassicEditor,
		editorData: '<p>Content of the editor.</p>',
		editorConfig: {
			// The configuration of the editor.
		}
	}
} ).use( CKEditor ).mount( '#app' );
```

Voilà! You should see CKEditor 5 running in your Vue.js app.

<info-box>
	See the list of supported [directives](#component-directives) and [events](#component-events) that will help you configure the component.
</info-box>

### Using ES6 modules

The editor component comes as a [UMD module](https://github.com/umdjs/umd), which makes it possible to use in various environments, for instance, applications generated by [Vue CLI](https://cli.vuejs.org/), built using [webpack](https://webpack.js.org), etc.

To create an editor instance, you must first import the editor build and the component modules into the root file of your application (e.g. `main.js` when generated by Vue CLI). Then, enable the component using the [application instance](https://v3.vuejs.org/guide/instance.html#creating-an-application-instance):

```js
import { createApp } from 'vue';
import CKEditor from '@ckeditor/ckeditor5-vue';

createApp( { /* options */ } ).use( CKEditor ).mount( /* DOM element */ );
```

<info-box>
	Instead of calling the `use()` method to install CKEditor component globally, you can always [use the component locally](#using-the-component-locally).
</info-box>

The following example showcases a single–file component of the application. Use the `<ckeditor>` component in your template:

* The [`editor`](#editor) directive specifies the editor build (the editor constructor).
* The [`v-model`](#v-model) directive enables an out–of–the–box two–way data binding.
* The [`config`](#config) directive helps you pass the configuration to the editor instance.

```html
<template>
	<div id="app">
		<ckeditor :editor="editor" v-model="editorData" :config="editorConfig"></ckeditor>
	</div>
</template>

<script>
	import ClassicEditor from '@ckeditor/ckeditor5-build-classic';

	export default {
		name: 'app',
		data() {
			return {
				editor: ClassicEditor,
				editorData: '<p>Content of the editor.</p>',
				editorConfig: {
					// The configuration of the editor.
				}
			};
		}
	}
</script>
```

<info-box>
	See the list of the supported [directives](#component-directives) and [events](#component-events) that will help you configure the component.
</info-box>

## Using the component locally

If you do not want the CKEditor component to be enabled globally, you can skip the `use()` part entirely. Instead, configure it in the `components` property of your view.

<info-box>
	Make sure `CKEditor` and `ClassicEditor` are accessible depending on the integration scenario: as [direct script includes](#direct-script-include) or [ES6 module imports](#using-es6-modules).
</info-box>

```html
<template>
	<div id="app">
		<ckeditor :editor="editor" ... ></ckeditor>
	</div>
</template>

<script>
	export default {
		name: 'app',
		components: {
			// Use the <ckeditor> component in this view.
			ckeditor: CKEditor.component
		},
		data() {
			return {
				editor: ClassicEditor,

				// ...
			};
		}
	}
</script>
```

## Using CKEditor from source

Integrating the rich text editor from source allows you to use the full power of the {@link framework/guides/overview CKEditor 5 Framework}.

This guide assumes that you are using [Vue CLI 4.5.0+](https://cli.vuejs.org) as your boilerplate and your application has been created using the [`vue create`](https://cli.vuejs.org/guide/creating-a-project.html#vue-create) command.

<info-box>
	Learn more about building CKEditor from source in the {@link builds/guides/integration/advanced-setup Advanced setup} guide.
</info-box>

### Configuring `vue.config.js`

To build CKEditor with your application, certain changes must be made to the default project configuration.

First, install the necessary dependencies:

```bash
npm install --save \
    @ckeditor/ckeditor5-vue \
    @ckeditor/ckeditor5-dev-webpack-plugin \
    @ckeditor/ckeditor5-dev-utils \
    postcss-loader@3 \
    raw-loader@0.5.1
```

Edit the `vue.config.js` file and use the following configuration. If the file is not present, create it in the root of the application (i.e. next to `package.json`):

```js
const path = require( 'path' );
const CKEditorWebpackPlugin = require( '@ckeditor/ckeditor5-dev-webpack-plugin' );
const { styles } = require( '@ckeditor/ckeditor5-dev-utils' );

module.exports = {
	// The source of CKEditor is encapsulated in ES6 modules. By default, the code
	// from the node_modules directory is not transpiled, so you must explicitly tell
	// the CLI tools to transpile JavaScript files in all ckeditor5-* modules.
	transpileDependencies: [
		/ckeditor5-[^/\\]+[/\\]src[/\\].+\.js$/,
	],

	configureWebpack: {
		plugins: [
			// CKEditor needs its own plugin to be built using webpack.
			new CKEditorWebpackPlugin( {
				// See https://ckeditor.com/docs/ckeditor5/latest/features/ui-language.html
				language: 'en',

				// Append translations to the file matching the `app` name.
				translationsOutputFile: /app/
			} )
		]
	},

	// Vue CLI would normally use its own loader to load .svg and .css files, however:
	//	1. The icons used by CKEditor must be loaded using raw-loader,
	//	2. The CSS used by CKEditor must be transpiled using PostCSS to load properly.
	chainWebpack: config => {
		// (1.) To handle the editor icons, get the default rule for *.svg files first:
		const svgRule = config.module.rule( 'svg' );

		// Then you can either:
		//
		// * clear all loaders for existing 'svg' rule:
		//
		//		svgRule.uses.clear();
		//
		// * or exclude ckeditor directory from node_modules:
		svgRule.exclude.add( path.join( __dirname, 'node_modules', '@ckeditor' ) );

		// Add an entry for *.svg files belonging to CKEditor. You can either:
		//
		// * modify the existing 'svg' rule:
		//
		//		svgRule.use( 'raw-loader' ).loader( 'raw-loader' );
		//
		// * or add a new one:
		config.module
			.rule( 'cke-svg' )
			.test( /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/ )
			.use( 'raw-loader' )
			.loader( 'raw-loader' );

		// (2.) Transpile the .css files imported by the editor using PostCSS.
		// Make sure only the CSS belonging to ckeditor5-* packages is processed this way.
		config.module
			.rule( 'cke-css' )
			.test( /ckeditor5-[^/\\]+[/\\].+\.css$/ )
			.use( 'postcss-loader' )
			.loader( 'postcss-loader' )
			.tap( () => {
				return styles.getPostCssConfig( {
					themeImporter: {
						themePath: require.resolve( '@ckeditor/ckeditor5-theme-lark' ),
					},
					minify: true
				} );
			} );
	}
};
```

<info-box>
    By default, the Vue CLI uses [`file-loader`](https://webpack.js.org/loaders/file-loader/) for all SVG files. The `file-loader` copies the file to the output directory and resolves imports into URLs. The CKEditor's UI components use SVG {@link module:ui/icon/iconview~IconView#content source directly} so the theme icons must be loaded using [`raw-loader`](https://webpack.js.org/loaders/raw-loader). If your project uses different approach than CKEditor's UI library you must create different webpack loader rules for your project's SVG files and the CKEditor's ones.
</info-box>

### Using the editor from source

Having configured `vue.config.js`, you can choose the building blocks of your editor. Install the packages necessary for your integration:

```bash
npm install --save \
	@ckeditor/ckeditor5-editor-classic \
	@ckeditor/ckeditor5-essentials \
	@ckeditor/ckeditor5-basic-styles \
	@ckeditor/ckeditor5-link \
	@ckeditor/ckeditor5-paragraph \
	@ckeditor/ckeditor5-theme-lark
```

You can use more packages, depending on which features are needed in your application.

```js
import { createApp } from 'vue';
import CKEditor from '@ckeditor/ckeditor5-vue';

createApp( { /* options */ } ).use( CKEditor ).mount( /* DOM element */ );
```

<info-box>
	Instead of calling the `use()` method to install CKEditor component globally, you can always [use the component locally](#using-the-component-locally).
</info-box>

Now all you need to do is specify the list of rich text editor options (**including plugins**) in the `editorConfig` data property:

```html
<template>
	<div id="app">
		<ckeditor :editor="editor" v-model="editorData" :config="editorConfig"></ckeditor>
	</div>
</template>

<script>
	// ⚠️ NOTE: We don't use @ckeditor/ckeditor5-build-classic any more!
	// Since we're building CKEditor from source, we use the source version of ClassicEditor.
	import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';

	import EssentialsPlugin from '@ckeditor/ckeditor5-essentials/src/essentials';
	import BoldPlugin from '@ckeditor/ckeditor5-basic-styles/src/bold';
	import ItalicPlugin from '@ckeditor/ckeditor5-basic-styles/src/italic';
	import LinkPlugin from '@ckeditor/ckeditor5-link/src/link';
	import ParagraphPlugin from '@ckeditor/ckeditor5-paragraph/src/paragraph';

	export default {
		name: 'app',
		data() {
			return {
				editor: ClassicEditor,
				editorData: '<p>Content of the editor.</p>',
				editorConfig: {
					plugins: [
						EssentialsPlugin,
						BoldPlugin,
						ItalicPlugin,
						LinkPlugin,
						ParagraphPlugin
					],

					toolbar: {
						items: [
							'bold',
							'italic',
							'link',
							'undo',
							'redo'
						]
					}
				}
			};
		}
	};
</script>
```

## Using the Document editor build

If you use the {@link framework/guides/document-editor Document editor} in your application, you need to {@link module:editor-decoupled/decouplededitor~DecoupledEditor.create manually add the editor toolbar to the DOM}.

Since accessing the editor toolbar is not possible until after the editor instance is {@link module:core/editor/editor~Editor#event:ready ready}, put your toolbar insertion code in a method executed upon the [`ready`](#ready) event of the component, like in the following example:

```html
<template>
		<div id="app">
			<ckeditor :editor="editor" @ready="onReady" ... ></ckeditor>
		</div>
</template>

<script>
	import DecoupledEditor from '@ckeditor/ckeditor5-build-decoupled-document';

	export default {
		name: 'app',
		data() {
			return {
				editor: DecoupledEditor,

				// ...
			};
		},
		methods: {
			onReady( editor )  {
				// Insert the toolbar before the editable area.
				editor.ui.getEditableElement().parentElement.insertBefore(
					editor.ui.view.toolbar.element,
					editor.ui.getEditableElement()
				);
			}
		}
	}
</script>
```

## Localization

CKEditor 5 supports {@link features/ui-language multiple UI languages}, and so does the official Vue.js component. Follow the instructions below to translate CKEditor 5 in your Vue.js application.

### Ready-to-use builds

When using one of the {@link builds/guides/overview#available-builds official editor builds}, you need to import the translations first.

* When using a [direct script include](#direct-script-include):
	```html
	<!-- Import translations for the German language. -->
	<script src="../node_modules/@ckeditor/ckeditor5-build-classic/build/translations/de.js"></script>
	<script src="../node_modules/@ckeditor/ckeditor5-build-classic/build/ckeditor.js"></script>
	<script src="../node_modules/@ckeditor/ckeditor5-vue/dist/ckeditor.js"></script>
	```
* When using [ES6 modules](#using-es6-modules):
	```js
	import ClassicEditor from '@ckeditor/ckeditor5-build-classic';

	// Import translations for the German language.
	import '@ckeditor/ckeditor5-build-classic/build/translations/de';
	```

Then, {@link builds/guides/integration/configuration configure} the language of the editor in the component:

```html
<ckeditor :editor="editor" v-model="editorData" :config="editorConfig"></ckeditor>
```

```js
export default {
	name: 'app',
	data() {
		return {
			editor: ClassicEditor,
			editorData: '<p>Content of the editor.</p>',
			editorConfig: {
				// Run the editor with the German UI.
				language: 'de'
			}
		};
	}
}
```

For more information, please refer to the {@link features/ui-language Setting the UI language} guide.

### CKEditor 5 built from source

Using the editor [built from source](#using-ckeditor-from-source) requires you to modify the webpack configuration. Pass the `language` (also `additionalLanguages`) to the constructor of  [`CKEditorWebpackPlugin`](https://www.npmjs.com/package/@ckeditor/ckeditor5-dev-webpack-plugin) to localize your editor:

```js
// vue.config.js
// ...

const CKEditorWebpackPlugin = require( '@ckeditor/ckeditor5-dev-webpack-plugin' );

// ...

module.exports = {
	// ...

	configureWebpack: {
		plugins: [
			// CKEditor needs its own plugin to be built using webpack.
			new CKEditorWebpackPlugin( {
				// The UI language. Language codes follow the https://en.wikipedia.org/wiki/ISO_639-1 format.
				language: 'de',

				// Append translations to the file matching the `app` name.
				translationsOutputFile: /app/
			} )
		]
	},

	// ...
}
```

After building the application, CKEditor 5 will run with the UI translated to the specified language.

For more information, please refer to the {@link features/ui-language "Setting UI language"} guide.

## Component directives

### `editor`

This directive specifies the editor to be used by the component. It must directly reference the editor constructor to be used in the template.

```html
<template>
		<div id="app">
			<ckeditor :editor="editor" ... ></ckeditor>
		</div>
</template>

<script>
	import ClassicEditor from '@ckeditor/ckeditor5-build-classic';

	export default {
		name: 'app',
		data() {
			return {
				editor: ClassicEditor,

				// ...
			};
		}
	}
</script>
```

<info-box>
	To use more than one rich text editor build in your application, you will need to configure it [from source](#using-ckeditor-from-source) or use a {@link builds/guides/integration/advanced-setup#scenario-3-using-two-different-editors "super build"}.
</info-box>

### `tag-name`

By default, the editor component creates a `<div>` container which is used as an element passed to the editor (e.g. {@link module:editor-classic/classiceditorui~ClassicEditorUI#element `ClassicEditor#element`}). The element can be configured, so for example to create a `<textarea>`, use the following directive:

```html
<ckeditor :editor="editor" tag-name="textarea"></ckeditor>
```

### `v-model`

A [standard directive](https://v3.vuejs.org/guide/component-basics.html#using-v-model-on-components) for form inputs in Vue. Unlike [`model-value`](#model-value), it creates a two–way data binding, which:

* sets the initial editor content,
* automatically updates the state of the application as the editor content changes (e.g. as the user types),
* can be used to set the editor content when necessary.

```html
<template>
	<div id="app">
		<ckeditor :editor="editor" v-model="editorData"></ckeditor>
		<button @click="emptyEditor">Empty the editor</button>

		<h2>Editor data</h2>
		<code>{{ editorData }}</code>
	</div>
</template>

<script>
	import ClassicEditor from '@ckeditor/ckeditor5-build-classic';

	export default {
		name: 'app',
		data() {
			return {
				editor: ClassicEditor,
				editorData: '<p>Content of the editor.</p>'
			};
		},
		methods: {
			emptyEditor() {
				this.editorData = '';
			}
		}
	}
</script>
```

In the above example, the `editorData` property will be updated automatically as the user types and the content changes. It can also be used to change (as in `emptyEditor()`) or set the initial content of the editor.

If you only want to execute an action when the editor data changes, use the [`input`](#input) event.

### `model-value`

Allows a one–way data binding that sets the content of the editor. Unlike [`v-model`](#v-model), the value will not be updated when the content of the editor changes.

```html
<template>
	<div id="app">
		<ckeditor :editor="editor" :model-value="editorData"></ckeditor>
	</div>
</template>

<script>
	import ClassicEditor from '@ckeditor/ckeditor5-build-classic';

	export default {
		name: 'app',
		data() {
			return {
				editor: ClassicEditor,
				editorData: '<p>Content of the editor.</p>'
			};
		}
	}
</script>
```

To execute an action when the editor data changes, use the [`input`](#input) event.

### `config`

Specifies the {@link module:core/editor/editorconfig~EditorConfig configuration} of the editor.

```html
<template>
	<div id="app">
		<ckeditor :editor="editor" :config="editorConfig"></ckeditor>
	</div>
</template>

<script>
	import ClassicEditor from '@ckeditor/ckeditor5-build-classic';

	export default {
		name: 'app',
		data() {
			return {
				editor: ClassicEditor,
				editorConfig: {
					toolbar: [ 'bold', 'italic', '|', 'link' ]
				}
			};
		}
	}
</script>
```

### `disabled`

This directive controls the {@link module:core/editor/editor~Editor#isReadOnly `isReadOnly`} property of the editor.

It sets the initial read–only state of the editor and changes it during its lifecycle.

```html
<template>
	<div id="app">
		<ckeditor :editor="editor" :disabled="editorDisabled"></ckeditor>
	</div>
</template>

<script>
	import ClassicEditor from '@ckeditor/ckeditor5-build-classic';

	export default {
		name: 'app',
		data() {
			return {
				editor: ClassicEditor,
				// This editor will be read–only when created.
				editorDisabled: true
			};
		}
	}
</script>
```

## Component events

### `ready`

Corresponds to the {@link module:core/editor/editor~Editor#event:ready `ready`} editor event.

```html
<ckeditor :editor="editor" @ready="onEditorReady"></ckeditor>
```

### `focus`

Corresponds to the {@link module:engine/view/document~Document#event:focus `focus`} editor event.

```html
<ckeditor :editor="editor" @focus="onEditorFocus"></ckeditor>
```

### `blur`

Corresponds to the {@link module:engine/view/document~Document#event:blur `blur`} editor event.

```html
<ckeditor :editor="editor" @blur="onEditorBlur"></ckeditor>
```

### `input`

Corresponds to the {@link module:engine/model/document~Document#event:change:data `change:data`} editor event.

```html
<ckeditor :editor="editor" @input="onEditorInput"></ckeditor>
```

### `destroy`

Corresponds to the {@link module:core/editor/editor~Editor#event:destroy `destroy`} editor event.

**Note:** Because the destruction of the editor is promise–driven, this event can be fired before the actual promise resolves.

```html
<ckeditor :editor="editor" @destroy="onEditorDestroy"></ckeditor>
```

## Contributing and reporting issues

The source code of this component is available on GitHub in https://github.com/ckeditor/ckeditor5-vue.
