CKEditor 4 Angular Integration Documentation
The Angular 5+ integration allows you to implement CKEditor 4 as an Angular component, using the <ckeditor>
tag.
The following examples showcase the most important features of the CKEditor 4 WYSIWYG editor Angular integration.
Click the tab below to change an example.
Classic Editor
To use the CKEditor 4 WYSIWYG editor component, create a new <ckeditor>
tag. The initial data of the editor can be set with the data
property.
Three available editor types are classic editor (default one), divarea editor (an inline editor with a fixed UI) and inline editor with a floating UI.
Use the select below to change the editor type.
Rich Text Editor, editor1
Editor toolbars
Press ALT 0 for help
◢Elements path Get Sample Source Code
- Editor types
import { Component } from '@angular/core'; @Component( { selector: 'app-editor-types', template: ` <h2>{{ type }} Editor</h2> <p> To use the CKEditor 4 WYSIWYG editor component, create a new <code><ckeditor></code> tag. The initial data of the editor can be set with the <code>data</code> property. </p> <p> Three available editor types are <strong>classic editor</strong> (default one), <strong>divarea editor</strong> (an inline editor with a <a href="./fixedui.html">fixed UI</a>) and <strong>inline editor</strong> with a <a href="./floatingui.html">floating UI</a>. </p> <p>Use the select below to change the editor type.</p> <ckeditor *ngIf="!inline && !divarea" [(data)]="editorData"> </ckeditor> <ckeditor *ngIf="divarea" type="divarea" [(data)]="editorData"> </ckeditor> <ckeditor *ngIf="inline" type="inline" [(data)]="editorData"> </ckeditor> <div class="select-editor-type"> <label for="editor-type">Choose editor type:</label> <select id="editor-type" class="editor-type" (change)="onChange($event.target.value)"> <option value="classic">Classic Editor</option> <option value="divarea">Divarea Editor</option> <option value="inline">Inline Editor</option> </select> </div> ` } ) export class EditorTypesComponent { public isReadOnly = false; public editorData = `<p>This is a CKEditor 4 instance created with Angular.</p>`; public type = 'Classic'; public inline = false; public divarea = false; public componentEvents: string[] = []; onChange( newValue ) { this.inline = newValue === 'inline'; this.divarea = newValue === 'divarea'; this.type = newValue.charAt( 0 ).toUpperCase() + newValue.substring( 1 ); } }
- Component events and Angular directives
import { Component } from '@angular/core'; interface ComponentEvent { name: string; counter: number; message: string; } @Component( { selector: 'app-events', template: ` <h2>Events and Directives</h2> <p> The CKEditor 4 WYSIWYG editor component allows you to bind event handlers with <a href="https://ckeditor.com/docs/ckeditor4/latest/guide/dev_angular.html#supported-output-properties"><code>@Output</code></a> attributes in the HTML code. </p> <p> The following example shows how to bind several CKEditor events. Additionally, it presents how the component could be used with <a href="https://angular.io/guide/attribute-directives">Angular directives</a>. </p> <ckeditor *ngIf="!isRemoved" data="<p>This is a CKEditor 4 instance created with Angular.</p>" [readOnly]="isReadOnly" [hidden]="isHidden" (ready)="onReady()" (change)="onChange()" (focus)="onFocus()" (blur)="onBlur()"> </ckeditor> <h3>Events log</h3> <ul class="events-log"> <li *ngFor="let event of componentEvents">{{ event.message }}> <span *ngIf="event.counter > 1"> ({{ event.counter }})</span> </li> </ul> <button (click)="clearEventsLog()">Clear events log</button> <h3>Angular directives</h3> <p><label><input type="checkbox" [(ngModel)]="isHidden">Hide the editor with the <code>[hidden]</code> directive.</label></p> <p><label><input type="checkbox" [(ngModel)]="isRemoved">Remove the editor from DOM with the <code>*ngIf</code> directive.</label></p> <p><label><input type="checkbox" [(ngModel)]="isReadOnly">Make the editor read-only.</label></p> ` } ) export class EventsComponent { public isReadOnly = false; public isHidden = false; public isRemoved = false; public componentEvents: ComponentEvent[] = []; clearEventsLog(): void { this.componentEvents.length = 0; } onReady(): void { this.saveEvent( 'ready' ); } onChange(): void { this.saveEvent( 'changed' ); } onFocus(): void { this.saveEvent( 'focused' ); } onBlur(): void { this.saveEvent( 'blurred' ); } private saveEvent( eventName: string ): void { const events = this.componentEvents; let message = `Editor ${ eventName === 'changed' ? 'has' : 'is' } ${ eventName }`; if ( events.length && events[ 0 ].name === eventName ) { events[ 0 ].counter++; } else { events.unshift( { name: eventName, counter: 1, message: message } ); } } }
- Form example
import { Component, ViewChild, AfterViewInit, ElementRef } from '@angular/core'; import { NgForm } from '@angular/forms'; @Component( { selector: 'app-demo-form', template: ` <h2>Integration with forms (<code>ngModel</code>)</h2> <p> The CKEditor 4 WYSIWYG editor component implements the <a href="https://angular.io/api/forms/ControlValueAccessor"><code>ControlValueAccessor</code> interface</a> and works with <code>ngModel</code>. For example, it can be used to integrate with a simple form like the one below. </p> <form (ngSubmit)="onSubmit()" #demoForm="ngForm"> <h3>User profile form</h3> <div> <label for="name">Name</label> <input [(ngModel)]="model.name" type="text" name="name" id="name"> </div> <div> <label for="surname">Surname</label> <input [(ngModel)]="model.surname" type="text" name="surname" id="surname"> </div> <label for="description">Description</label> <ckeditor #editor [(ngModel)]="model.description" id="description" name="description" type="divarea"> </ckeditor> <p><button type="reset" (click)="reset()">Reset form</button></p> <p><button type="submit">Submit this form</button></p> </form> <h3>Editor data preview</h3> <p> Note that this is only a proof of concept of using <code>ngModel</code>. It allows for editing the form, but the editor strips out unknown tags. It also autoparagraphs text outside of block elements. The editor updates when the textarea element is blurred. </p> <textarea #preview (focus)="isPreviewActive = true; previewModel = model.description" (change)="isPreviewActive = false; model.description = previewModel" [(ngModel)]="previewModel"></textarea> `, styleUrls: [ './demo-form.component.css' ] } ) export class DemoFormComponent implements AfterViewInit { @ViewChild( 'demoForm' ) demoForm?: NgForm; @ViewChild( 'preview' ) preview: ElementRef; @ViewChild( 'editor' ) editor; public model = { name: 'John', surname: 'Doe', description: '<p>This is a sample form using CKEditor 4 and created in Angular.</p>' }; public isPreviewActive: boolean; public previewModel: string; onSubmit() { alert( `Form submit, model: ${ JSON.stringify( this.model ) }` ); } reset() { this.demoForm!.reset(); } get description() { return this.demoForm!.controls.description; } ngAfterViewInit() { this.editor.dataChange.subscribe( ( value ) => { if ( !this.isPreviewActive ) { this.previewModel = value; } } ); } }