System Environment Variables On Windows
September 18, 2019How To Deploy A Backend API To Azure
October 7, 2019What is CKEditor and why would you be interested in using it?
So if you have ever added a comment to an online forum or written a blog on Wordpress, you may have noticed that the text-area in which you enter your very emotionally invested few lines of opinions has a bar at the top which lets you italicise , bold, or even put your text in "quotes" to highlight the important bits of whatever message your getting across.
This amazing piece of software is called a WYSIWYG (What you see is what you get ) editor and I am using one variant of it right now as I type out this blog post.
For everyone else this great tool offered on most websites to structure text from users is convenience at the "click of a widget". For software developers, this becomes an implementation problem. How best to get this to work with your web development framework of choice, mine and yours if your are reading this being faced with the same problem I was, Angular.
Enter CKEditor
CKEditor one variant of WYSIWYG editors out there that has great documentation and customisation support as well as community plugins to add extra functionality to it.
The Integration with Angular problem
If you have built an angular production site recently, you may have run into the nifty angular server side rendering support that was added with angular universal . There is a great article explaining how server side rendering works here. Another article explaining how to build your angular app with SSR here. Also here's how to deploy after you have build your app here.
Now while angular is built to work with third party npm packages like the one that brings CKEditor support to your angular app, not all of them are compatible with angular universal.
After some deep internet diving, "I came up" with with following solution that only uses plain old including the CKEditor library via CDN into your angular application without requiring the npm package built for angular to support CKEditor.
The HACK (How to use CKEditor 5 in Angular with server side rendering support)
Now that we have the origin story out of the way. . . Don't worry you will not be judged for not reading it. everyone goes straight for the code.
Using Angular's renderer2 . we can load CDN JS libraries at a component level and even run init scripts on them and here is how.
Step 1: create a new angular project, cd into it and serve it
ng new ckeditorDemo cd ckeditorDemo ng serve
now if you open a browser and go to http://localhost: 4200, you should see your newly created angular app
Step 2: generate a new component
ng g c editor -m=app.module
this is where we are going to put our ckeditor code
Step 3: modify "src/app/app.component.html" file to show editor component content
delete all the code in the file and replace it with
Step 4: Lets bring in angular renderer 2
in the file "src/app/editor/editor.component.ts" make the following imports
import { Component, OnInit, Inject, Renderer2 } from '@angular/core'; import { DOCUMENT } from '@angular/common';
What we are doing here is importing renderer2 , the module from angular that we will use to inject javascript into the the component at load time.
We are also importing DOCUMENT, we will use this to reference the dom as _document in "this" component's context.
Still in the file "src/app/editor/editor.component.ts" add the following code
... ckEditorData; constructor( private _renderer2: Renderer2, @Inject(DOCUMENT) private _document, ) { this.loadCkEditor(); } ...
Here we are adding the dependencies we just mentioned above into the constructor. Notice we are calling the function "this.loadCkEditor();" this is where we will add the code that loads ckEditor at load time. the global variable ckeditorData will hold the data from the editor as we type into it.
Step 5: load CKEditor
Still in the file "src/app/editor/editor.component.ts" add the following code
loadCkEditor() { const script = this._renderer2.createElement('script'); script.type = 'application/javascript'; script.src = 'https://cdn.ckeditor.com/ckeditor5/12.4.0/classic/ckeditor.js'; script.text = ` ${(script.onload = async () => { const CKEditor = (window as any).ClassicEditor; const editor = await CKEditor.create( document.querySelector('#editor'), { toolbar: [ 'heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'blockQuote', 'insertTable', 'undo', 'redo' ] } ); editor.model.document.on('change', () => { this.ckEditorData = JSON.stringify(editor.getData()); }); })} `; this._renderer2.appendChild(this._document.body, script); }
Here in lines 1 - 5 , we tell renderer 2 that we are loading javascript from the CKEditor 5 cdn
In lines 6 - 26 we do some config to our CKEditor , so remember that bar at the top with all the widgets , this is where you define which ones you want to make available to user in the the toolbar array
In lines 27 to the end 33 we make an event handler that gets fired every time the text in the editor changes and save it in the gloabal variable we defined earlier "ckEditorData".
Lastly we use “this._renderer2.appendChild(this._document.body, script);” to bind the script to the dom;
Step 6: hook up the editor in the Dom
in the file “src/app/editor/editor.component.html” add the following code
Here we make a div and give it an Id of editor , the same Id we reference in the renderer 2 script.
Awesome Result
The app should still be getting served on http://localhost:4200, you should see the amazing WYSIWYG editor in all its glory waiting for you to type out some world changing information for the entire Internet to read.
What is even better is if you build it for deployment using angular universal, It will not break.
You can find the source code here.
Thanks for reading.