WARNINGYou're reading the legacy documentation.
Sign up (with export icon)

(Legacy) Angular rich text editor component

Contribute to this guide Show the table of contents

CKEditor 5 consists of the ready-to-use editor builds and the CKEditor 5 Framework upon which the builds are based.

Currently, the CKEditor 5 component for Angular supports integrating CKEditor 5 only via builds. Integrating CKEditor 5 built from source is not possible yet due to the lack of ability to adjust webpack configuration in angular-cli.

Supported Angular versions

Copy link

Because of the breaking changes in the Angular library output format, the @ckeditor/ckeditor5-angular package is released in the following versions to support various Angular ecosystems:

CKEditor 5 version Angular version Details
Actively supported versions
^6 13+ Requires CKEditor 5 in version 37 or higher.
Past releases (no longer maintained)
^5 13+ Requires Angular in version 13+ or higher. Lower versions are no longer maintained.
^5 13+ Requires Angular in version 13+ or higher. Lower versions are no longer maintained.
^4 9.1+ Requires CKEditor 5 in version 34 or higher.
^3 9.1+ Requires Node.js in version 14 or higher.
^2 9.1+ Migration to TypeScript 4. Declaration files are not backward compatible.
^1 5.x - 8.x Angular versions are no longer maintained.

All available Angular versions are listed on npm, where they can be pulled from.

Quick start

Copy link

In your existing Angular project, install the CKEditor 5 WYSIWYG editor component for Angular:

npm install --save @ckeditor/ckeditor5-angular
Copy code
Note

If you do not have an existing project, you can use the Angular CLI to create a new one.

Install one of the CKEditor 5 predefined builds or create a custom one.

This tutorial assumes that you picked @ckeditor/ckeditor5-build-classic:

npm install --save @ckeditor/ckeditor5-build-classic
Copy code

The @ckeditor/ckeditor5-angular package requires the following peer dependencies, with a version of at least 37.0.0:

Keep in mind that they must have the same version as the editor build.

Install all the required peer dependencies:

npm install --save @ckeditor/ckeditor5-core @ckeditor/ckeditor5-engine @ckeditor/ckeditor5-utils @ckeditor/ckeditor5-watchdog
Copy code

Now, add CKEditorModule to modules whose components will be using the <ckeditor> component in their templates.

// app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { CKEditorModule } from '@ckeditor/ckeditor5-angular';

import { AppComponent } from './app.component';

@NgModule( {
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    CKEditorModule
  ],
  providers: [],
  bootstrap: [ AppComponent ]
} )
export class AppModule { }

Copy code

Import the editor build in your Angular component and assign it to a public property to make it accessible from the template:

// app.component.ts

import { Component } from '@angular/core';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';

@Component( {
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
} )
export class AppComponent {
  title = 'angular';
  public Editor = ClassicEditor;
}
Copy code

Finally, use the <ckeditor> tag in the template to run the rich text editor:

<!-- app.component.html -->

<ckeditor [editor]="Editor" data="<p>Hello, world!</p>"></ckeditor>
Copy code

Rebuild your application and CKEditor 5 should greet you with a “Hello, world!”

Using the Document editor build

Copy link

If you want to use the document editor build, you need to add the toolbar to the DOM manually.

// app.component.ts

import { Component } from '@angular/core';
import DecoupledEditor from '@ckeditor/ckeditor5-build-decoupled-document';

@Component( {
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
} )
export class AppComponent {
  title = 'angular';
  public Editor = DecoupledEditor;

  public onReady( editor: DecoupledEditor ): void {
    const element = editor.ui.getEditableElement()!;
    const parent = element.parentElement!;

    parent.insertBefore(
      editor.ui.view.toolbar.element!,
      element
    );
  }
}
Copy code

And then, in the template:

<!-- app.component.html -->

<ckeditor [editor]="Editor" data="<p>Hello, world!</p>" (ready)="onReady($event)"></ckeditor>
Copy code

Using a custom CKEditor 5 build

Copy link

If you want to add more plugins to an existing build or customize something that cannot be controlled with the editor configuration you need to create a custom build first, as described in the Building the editor from source guide.

By completing the above tutorial you should get a generated ckeditor.js file (and corresponding translation files). In the next step you should copy it to the src directory and import it to the component file.

// app.component.ts

import * as Editor from 'path/to/the/ckeditor';

@Component( {
    // ...
} )
export class MyComponent {
    public Editor = Editor;
    // ...
}
Copy code

Note that to allow importing JavaScript files without providing their corresponding types you need to set allowJs to true in the tsconfig.json file. Also, make sure that you target ES6 or higher, otherwise you are likely to end up with a weird transpilation error in the production build.

// tsconfig.json

"compilerOptions": {
    "allowJs": true,
    "target": "es2015"
    // other options
}
Copy code
Note

If you cannot set the target higher than es5, try to set "buildOptimizer": false which will produce a bigger, but correct production build.

Integrating a build from the online builder

Copy link

This guide assumes that you have created a zip archive with the editor built using the CKEditor 5 online builder.

Unpack it into you application’s main directory. The directory with the editor build cannot be placed inside the src/ directory as Node will return an error. Because of that, we recommend placing the directory next to the src/ and node_modules/ folders:

├── ckeditor5
│   ├── build
│   ├── sample
│   ├── src
│   ├── ...
│   ├── package.json
│   └── webpack.config.js
├── node_modules
├── src
├── ...
└── package.json
Copy code

Then, add the package located in the ckeditor5 directory as a dependency of your project:

npm install ./ckeditor5
Copy code

Now, import the build in your application:

// app.component.ts

import { Component } from '@angular/core';
import Editor from 'ckeditor5-custom-build/build/ckeditor';

@Component( {
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
} )
export class AppComponent {
  title = 'customEditor';
  public Editor = Editor;
}
Copy code

Using the editor with collaboration plugins

Copy link

The easiest way to integrate collaboration plugins in an Angular application is to create a custom build first and then import it from the Angular application. See Using a custom CKEditor 5 build.

Integration with ngModel

Copy link

The component implements the ControlValueAccessor interface and works with the ngModel. Here is how to use it:

Create some model in your component to share with the editor:

@Component( {
    // ...
} )
export class MyComponent {
    public model = {
        editorData: '<p>Hello, world!</p>'
    };
    // ...
}
Copy code

Use the model in the template to enable a two–way data binding:

<ckeditor [(ngModel)]="model.editorData" [editor]="Editor"></ckeditor>
Copy code

Supported @Input properties

Copy link

The following @Input properties are supported by the CKEditor 5 rich text editor component for Angular:

editor (required)

Copy link

The Editor which provides the static create() method to create an instance of the editor:

<ckeditor [editor]="Editor"></ckeditor>
Copy code

config

Copy link

The configuration of the editor:

<ckeditor [config]="{ toolbar: [ 'heading', '|', 'bold', 'italic' ] }" ...></ckeditor>
Copy code

data

Copy link

The initial data of the editor. It can be a static value:

<ckeditor data="<p>Hello, world!</p>" ...></ckeditor>
Copy code

or a shared parent component’s property

@Component( {
    // ...
} )
export class MyComponent {
    public editorData = '<p>Hello, world!</p>';
    // ...
}
Copy code
<ckeditor [data]="editorData" ...></ckeditor>
Copy code

tagName

Copy link

The tag name of the HTML element on which the rich text editor will be created.

The default tag is <div>.

<ckeditor tagName="textarea" ...></ckeditor>
Copy code

disabled

Copy link

Controls the editor’s read–only state:

@Component( {
    // ...
} )
export class MyComponent {
    public isDisabled = false;
    // ...
    toggleDisabled() {
        this.isDisabled = !this.isDisabled
    }
}
Copy code
<ckeditor [disabled]="isDisabled" ...></ckeditor>

<button (click)="toggleDisabled()">
    {{ isDisabled ? 'Enable editor' : 'Disable editor' }}
</button>
Copy code

watchdog

Copy link

An instance of the ContextWatchdog class that is responsible for providing the same context to multiple editor instances and restarting the whole structure in case of crashes.

import CKSource from 'path/to/custom/build';

const Context = CKSource.Context;
const Editor = CKSource.Editor;
const ContextWatchdog = CKSource.ContextWatchdog;

@Component( {
    // ...
} )
export class MyComponent {
    public editor = Editor;
    public watchdog: any;
    public ready = false;

    ngOnInit() {
        const contextConfig = {};

        this.watchdog = new ContextWatchdog( Context );

        this.watchdog.create( contextConfig )
            .then( () => {
                this.ready = true;
            } );
    }
}
Copy code
<div *ngIf="ready">
    <ckeditor [watchdog]="watchdog" ...></ckeditor>
    <ckeditor [watchdog]="watchdog" ...></ckeditor>
    <ckeditor [watchdog]="watchdog" ...></ckeditor>
</div>
Copy code

editorWatchdogConfig

Copy link

If the watchdog property is not used, EditorWatchdog will be used by default. editorWatchdogConfig property allows for passing a config to that watchdog.

@Component( {
    // ...
} )
export class MyComponent {
    public myWatchdogConfig = {
        crashNumberLimit: 5,
        // ...
    };
    // ...
}
Copy code
<ckeditor [editorWatchdogConfig]="myWatchdogConfig" ...></ckeditor>
Copy code

disableTwoWayDataBinding

Copy link

Allows disabling the two-way data binding mechanism. The default value is false.

The reason for the introduction of this option are performance issues in large documents. By default, while using the ngModel directive, whenever the editor’s data is changed, the component must synchronize the data between the editor instance and the connected property. This results in calling the editor.getData() function, which causes a massive slowdown while typing in large documents.

This option allows the integrator to disable the default behavior and only call the editor.getData() method on demand, which prevents the slowdowns. You can read more in the relevant issue.

Supported @Output properties

Copy link

The following @Output properties are supported by the CKEditor 5 rich text editor component for Angular:

ready

Copy link

Fired when the editor is ready. It corresponds with the editor#ready event.
It is fired with the editor instance.

Note that this method might be called multiple times. Apart from initialization, it is also called whenever the editor is restarted after a crash. Do not keep the reference to the editor instance internally, because it will change in case of restart. Instead, you should use watchdog.editor property.

change

Copy link

Fired when the content of the editor has changed. It corresponds with the editor.model.document#change:data event.
It is fired with an object containing the editor and the CKEditor 5 change:data event object.

<ckeditor [editor]="Editor" (change)="onChange($event)"></ckeditor>
Copy code
import * as ClassicEditor from '@ckeditor/ckeditor5-build-classic';
import { ChangeEvent } from '@ckeditor/ckeditor5-angular/ckeditor.component';

@Component( {
    // ...
} )
export class MyComponent {
    public Editor = ClassicEditor;

    public onChange( { editor }: ChangeEvent ) {
        const data = editor.getData();

        console.log( data );
    }
    ...
}
Copy code

blur

Copy link

Fired when the editing view of the editor is blurred. It corresponds with the editor.editing.view.document#blur event.
It is fired with an object containing the editor and the CKEditor 5 blur event data.

focus

Copy link

Fired when the editing view of the editor is focused. It corresponds with the editor.editing.view.document#focus event.
It is fired with an object containing the editor and the CKEditor 5 focus event data.

error

Copy link

Fired when the editor crashes. Once the editor is crashed, the internal watchdog mechanism restarts the editor and fires the ready event.

Note

Prior to ckeditor5-angular v7.0.1, this event was not fired for crashes during the editor initialization.

Styling

Copy link

The CKEditor 5 rich text editor component for Angular can be styled using the component style sheet or using a global style sheet. See how to set the CKEditor 5 component’s height using these two approaches.

Setting the height via the component style sheet

Copy link

First, create a (S)CSS file in the parent component’s directory and style the given editor’s part preceded by the :host and ::ng-deep pseudo selectors:

/* src/app/app.component.css */

:host ::ng-deep .ck-editor__editable_inline {
    min-height: 500px;
}
Copy code

Then in the parent component add the relative path to the above style sheet:

/* src/app/app.component.ts */

@Component( {
    // ...
    styleUrls: [ './app.component.css' ]
} )
Copy code

Setting the height via a global style sheet

Copy link

To style the component using a global style sheet, first, create it:

/* src/styles.css */

.ck-editor__editable_inline {
    min-height: 500px;
}
Copy code

Then, add it in the angular.json configuration file:

"architect": {
    "build": {
        "options": {
            "styles": [
                { "input": "src/styles.css" }
            ]
        }
    }
}
Copy code

Setting the placeholder

Copy link

To display the placeholder in the main editable element, set the placeholder field in the CKEditor 5 rich text editor component configuration:

@Component( {
    // ...
} )
export class MyComponent {
    public config = {
        placeholder: 'Type the content here!'
    }
}
Copy code

Accessing the editor instance

Copy link

The CKEditor 5 rich text editor component provides all the functionality needed for most use cases. When access to the full CKEditor 5 API is needed you can get the editor instance with an additional step.

To do this, create a template reference variable #editor pointing to the <ckeditor> component:

<ckeditor #editor [editor]="Editor" ...></ckeditor>
Copy code

Then get the <ckeditor> component using a property decorated by @ViewChild( 'editor' ) and access the editor instance when needed:

@Component()
export class MyComponent {
    @ViewChild( 'editor' ) editorComponent: CKEditorComponent;

    public getEditor() {
        // Warning: This may return "undefined" if the editor is hidden behind the `*ngIf` directive or
        // if the editor is not fully initialised yet.
        return this.editorComponent.editorInstance;
    }
}
Copy code
Note

The editor creation is asynchronous so the editorInstance will not be available until the editor is created. If you want to make changes to an editor that has just been created, a better option would be getting the CKEditor 5 instance on the ready event.

Localization

Copy link

The CKEditor 5 rich text editor component can be localized in two steps.

Loading translation files

Copy link

First, you need to add translation files to the bundle. This step can be achieved in two ways:

By importing translations for given languages directly in your component file:

import '@ckeditor/ckeditor5-build-classic/build/translations/de';
import * as ClassicEditor from '@ckeditor/ckeditor5-build-classic';
// More imports.
// ...
Copy code

By adding paths to translation files to the "scripts" array in angular.json:

"architect": {
    "build": {
        "options": {
            "scripts": [ "node_modules/@ckeditor/ckeditor5-build-classic/build/translations/de.js" ]
        }
    }
}
Copy code

Configuring the language

Copy link

Then, you need to configure the editor to use the given language:

@Component( {
    // ...
} )
export class MyComponent {
    public Editor = ClassicEditor;
    public config = {
        language: 'de'
    };
}
Copy code

For advanced usage see the Setting the UI language guide.

Common issues

Copy link

zone.js

Copy link

There is a repeatable issue with zone.js library when upgrading to new Angular versions. The ngOnDestroy handler crashes throwing:

ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'data-ck-expando' of undefined
TypeError: Cannot read property 'data-ck-expando' of undefined
Copy code

Workaround: in polyfills.js import zone.js using import zone.js/dist/zone.js instead of import 'zone.js'.
More details:

Contributing and reporting issues

Copy link

The source code of the CKEditor 5 rich text editor component for Angular is available on GitHub in https://github.com/ckeditor/ckeditor5-angular.