XamarinDevil
XamarinDevil

Reputation: 891

How to integrate CKEditor in angular 2

I am trying to integrate CKEditor into my angular project. I have followed other similar solutions but only the textarea appears. Here is what I have done so far.

HTML

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>A Simple Page with CKEditor</title>
    <!-- Make sure the path to CKEditor is correct. -->
    <script src="../Email/ckeditor/ckeditor.js"></script>
</head>
<body>
<form>
            <textarea name="editor1" id="editor1" rows="10" cols="80">
                This is my textarea to be replaced with CKEditor.
            </textarea>
    <script>
        // Replace the <textarea id="editor1"> with a CKEditor
        // instance, using default configuration.
        CKEDITOR.replace( 'editor1' );
    </script>
</form>
</body>
</html>

JS

import {Component} from '@angular/core';

@Component({
    selector: 'test',
    templateUrl:'test.html'
})

export class TestComponent {

}

Upvotes: 5

Views: 26915

Answers (4)

Maciej Bukowski
Maciej Bukowski

Reputation: 3348

If you want to integrate the CKEditor 5 editor with the Angular 2+ framework, there's a ready-to-use official integration, which provides simple and conscious API:

editor.component.html

<ckeditor
    [editor]="Editor"
    [data]="editorData"
    [config]="config"
    [disabled]="isDisabled"

    (ready)="onReady($event)"
    (change)="onChange($event)"
    (focus)="onFocus($event)"
    (blur)="onBlur($event)">
</ckeditor>

editor.component.ts

import '@ckeditor/ckeditor5-build-classic/build/translations/de';
import * as ClassicEditorBuild from '@ckeditor/ckeditor5-build-classic';

@Component( {
    selector: 'editor',
    templateUrl: './editor.component.html',
    styleUrls: [ './editor.component.css' ]
} )
export class SimpleUsageComponent {
    public Editor = ClassicEditorBuild;
    public editorData = '<p>Ckeditor5 & Angular</p>';
    public config = {
        language: 'de'
    };
    public isDisabled = false;

    onReady( editor ): void {}
    onChange( event ): void {}
    onFocus( event ): void {}
    onBlur( event ): void {}
}

app.module.ts

import { CKEditorModule } from '@ckeditor/ckeditor5-angular';

@NgModule({
  declarations: [
      // ...
  ],
  imports: [
      CKEditorModule,
      // ...
  ],
  // ...
})
export class AppModule { }

Upvotes: 2

dirbacke
dirbacke

Reputation: 3019

I am not allowed to use cdn in my project and I also need to add plugins to my project. To be able to do that using npm. This is my solution to this problem

Install ng2-ckeditor with ckeditor using npm.

npm install --save ckeditor

and

npm install --save ng2-ckeditor

Update the angular-cli.json to be able to add plugins to the instance of CKEditor. In the assets section of angular-cli.json add:

"assets": [
    "assets",
    "favicon.ico",
    {
       "glob": "**/*", 
       "input": "../node_modules/ckeditor/", 
       "output": "assets/js/ckeditor/", 
       "allowOutsideOutDir": true
    }
 ]

add also ckeditor.js from the downloaded npm to the script-tag in angular-cli.json:

"scripts": [
   "../node_modules/ckeditor/ckeditor.js"
]

Download the plugins that you need to use to the folder /assets/js/ckeditor/plugins/ of your project. Be sure that the plugin.js file exists in each subfolder of your plugins folder.

Create your own config file assets/js/ckeditor/ckeditor-config.js for ckeditor with the following content:

(function(){
    CKEDITOR.basePath = '/assets/js/ckeditor/'
    CKEDITOR.plugins.addExternal('wordcount', 'plugins/wordcount/');
    CKEDITOR.plugins.addExternal('notification', 'plugins/notification/');
    CKEDITOR.editorConfig = function( config ) {
        config.extraPlugins = 'wordcount,notification';
    }
})();

Create an internal service to be able to configure your ckeditor with your own input. Here I'm using the service to adjust the height and set the maximum limit of my characters from my ckeditor component. I'm also telling the plugin to display only character counter.

import { Injectable } from '@angular/core';

@Injectable()
export class CkeditorConfigService {

  constructor() { }
  public getConfig(height: number, maxCharCount: number){
    return {
      customConfig: '/assets/js/ckeditor/ckeditor-config.js',
      height: height,
      wordcount: {
        showParagraphs: false,
        showWordCount: false,
        showCharCount: true,
        maxCharCount: maxCharCount
      }
    };
  }
}

As ckeditor is a form section, you need to add FormsModule to your app.module.ts, as well as the ng2-ckeditor module.

imports: [
   ...
   FormsModule,
   CKEditorModule,
   ...
]

From your component add the internal service.

@Component({
  selector: 'test-ckeditor-app',
  templateUrl: './editor.component.html',
  providers: [
    CkeditorConfigService
  ]
})
export class EditorComponent implements OnInit {
  ckeditorContent: string = '<p>Some html</p>';
  private myCkeditorConfig: any;
  constructor(private ckService: CkeditorConfigService) {}

  ngOnInit() {
    this.myCkeditorConfig = this.ckService.getConfig(150, 400);
  }

}

And finally in your html file add the following:

<ckeditor
   [(ngModel)]="ckeditorContent"
   [config]="myCkeditorConfig">
</ckeditor>

Please find my project sample on github:

https://github.com/dirbacke/ckeditor4

Note! When you compile and run, you will get the MIME-type console warning. That is because the css files specified in the warning have comments.

Upvotes: 2

Sumama Waheed
Sumama Waheed

Reputation: 3609

You can use component that wraps the CKEditor library:

https://github.com/chymz/ng2-ckeditor

This makes it very easy and provides two-way binding:

<ckeditor [(ngModel)]="content" [config]="config"></ckeditor>

Edit:

Another option is to use this module which I've refactored from ng2-ckeditor and simplified. This way you don't have to install and manage another dependency.

1. Create file ckeditor.module.ts

2. Paste Content

import { Component, Input, OnInit, OnDestroy, ViewChild, ElementRef, forwardRef, NgZone, NgModule } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';

declare const CKEDITOR;

@Component({
    selector: 'app-ckeditor',
    template: `
        <textarea #editor>
            {{value}}
        </textarea>
    `,
    providers: [{
        provide: NG_VALUE_ACCESSOR,
        useExisting: forwardRef(() => CkEditorComponent),
        multi: true
    }]
})
export class CkEditorComponent implements OnInit, OnDestroy, ControlValueAccessor {


    @ViewChild('editor') editor: ElementRef;

    wait = false;

    instance: any;

    config = {
        uiColor: '#F0F3F4',
        height: '100%'
    };

    private _value = '';

    get value(): any { return this._value; }
    @Input() set value(v) {
        if (v !== this._value) {
            this._value = v;
            this.onChange(v);
        }
    }

    constructor(private zone: NgZone) { }

    ngOnInit() {
        this.instance = CKEDITOR.replace(this.editor.nativeElement, this.config);

        this.instance.setData(this._value);

        // CKEditor change event
        this.instance.on('change', () => {
            let value = this.instance.getData();
            this.updateValue(value);
        });
    }

    /**
   * Value update process
   */
    updateValue(value: any) {
        this.zone.run(() => {
            this.value = value;
            this.onChange(value);
            this.onTouched();
        });
    }

    /**
   * Implements ControlValueAccessor
   */
    writeValue(value: any) {
        console.log('writeValue');
        this._value = value;
        if (this.instance) {
            this.instance.setData(value);
        }
    }
    onChange(_: any) { }
    onTouched() { }
    registerOnChange(fn: any) { this.onChange = fn; }
    registerOnTouched(fn: any) { this.onTouched = fn; }



    ngOnDestroy() {
        if (this.instance) {
            setTimeout(() => {
                this.instance.removeAllListeners();
                CKEDITOR.instances[this.instance.name].destroy();
                this.instance.destroy();
                this.instance = null;
            });
        }
    }
}

@NgModule({
    imports: [],
    declarations: [CkEditorComponent],
    providers: [],
    exports: [CkEditorComponent]
})
export class CkEditorModule { }

3. Use like this

import { CkEditorModule } from '../../';

<app-ckeditor formControlName="postContent"></app-ckeditor>

4. I dynamically load the script when I need it using this function

    public addCkEditor(permissions) {
        if (this.usesCKEditor(permissions) && !window['CKEDITOR']) {
            const url = '//cdn.ckeditor.com/4.7.3/full/ckeditor.js';
            const script = document.createElement('script');
            script.onload = () => {
                this.ckeditorLoaded.next(true);
            };
            script.type = 'text/javascript';
            script.src = url;
            document.body.appendChild(script);
        }
    }

Upvotes: 7

Dudi Boy
Dudi Boy

Reputation: 4900

As of Angular 4 angular-cli is the standard tool to build and manage Angular projects.

These are the steps to start and test CKEditor in an Angular 4 application.

Assuming angular-cli is installed.

1. Create a new Angular application

$ ng new ckeditorSample --skip-test
$ cd ckeditorSample

2. Install ng2-ckeditor

ng2-ckeditor is the CKEditor intergration package to Angular 2 and beyond.

$ npm install --save ng2-ckeditor
$ npm update

3. Add SampleEditor component

Modify src/app/app.component.ts to include the SampleEditor component.

import { Component } from '@angular/core';

  @Component({
  selector: 'sampleEditor',
  template: `
  <ckeditor
    [(ngModel)]="ckeditorContent"
    [config]="{uiColor: '#a4a4a4'}"
    (change)="onChange($event)"
    (ready)="onReady($event)"
    (focus)="onFocus($event)"
    (blur)="onBlur($event)"
    debounce="500">
  </ckeditor>
  `,
})
export class SampleEditor {
  private ckeditorContent: string;
  constructor() {
    this.ckeditorContent = `<p>Greetings from CKEditor...</p>`;
  }
}

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

4. Add SampleEditor viewer template

Modify src/app/app.component.html to invoke SampleEditor component.

<div>
  <sampleEditor></sampleEditor>
</div>

5. Add CKEditor module to Angular application

Modify src/app/app.module.ts to include the CKEditorModule and SampleEditor component.

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

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

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

6. Add latest CKEditor script from CDN to Angular framework

Modify src/index.html to include the latest script.

As of the time writing this: https://cdn.ckeditor.com/4.7.0/standard-all/ckeditor.js

Check for the latest here: http://cdn.ckeditor.com/

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>CkeditorSample</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">

  <script src="https://cdn.ckeditor.com/4.7.0/standard-all/ckeditor.js"></script>

</head>

<body>
  <app-root></app-root>
</body>
</html>

7. Run the application

npm start &
firefox http://localhost:4200

Open the browser on http://localhost:4200 CKEditor should be there.

Upvotes: 22

Related Questions