/ angularjs

How to use CKEditor in AngularJS with custom directive

In this article learn how to use CKEditor in AngularJS with custom directive and ng-ckeditor, richtext editors are really important piece of plugins when it comes to doing more than just a text field, there are loads of options when choosing a plugin like the ever so popular TinyMCE, CKeditor, QuillJS. There are plenty of other options as well but none of them are as refined and stable as these.

In this article we'll talk only about the CKeditor my personal favorite, it is super easy to integrate in a standard HTML web-page setting.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>CKEditor</title>
    <script src="//cdn.ckeditor.com/4.5.6/standard/ckeditor.js"></script>
</head>
<body>
    <textarea name="editor1"></textarea>
    <script>
        CKEDITOR.replace( 'editor1' );
    </script>
</body>
</html>

*excerpt sourced from ckeditor documentation

That was easy isn't it? yes it is! that was everything required to set it up in a standard html page, but we won't be focusing on that, we want to integrate CKeditor with AngularJS and want to be able to use Angular's two way data binding, which is not possible using the above method, Angular just wouldn't know what you are trying to do because CKeditor and other editors as well work in an embedded iframe.

There are two ways that I personally go about when i'm solving this problem:

  • Write my own custom directive to listen and write for changes
  • Use ng-ckeditor a plugin/directive to make CKeditor work.

Either way we are using a directive, either you write it on your own, that suits your need or use a plugin written by someone else, whatever floats your boat. I've used both in separate occasions and got my job done.

Method 1 (writing custom directive):

In this method we write our own directive, what we want that directive to do is simply listen for changes and write them to the ng-model.

angular.module("CKEditorExample", [])
.directive('ckEditor', function () {
    return {
        require: '?ngModel',
        link: function (scope, elm, attr, ngModel) {
            var ck = CKEDITOR.replace(elm[0]);
            if (!ngModel) return;
            ck.on('instanceReady', function () {
                ck.setData(ngModel.$viewValue);
            });
            function updateModel() {
                scope.$apply(function () {
                ngModel.$setViewValue(ck.getData());
            });
        }
        ck.on('change', updateModel);
        ck.on('key', updateModel);
        ck.on('dataReady', updateModel);

        ngModel.$render = function (value) {
            ck.setData(ngModel.$viewValue);
        };
    }
};
});

If you notice these three lines:

ck.on('change', updateModel);
ck.on('key', updateModel);
ck.on('dataReady', updateModel);

These are listening for events happening in the directive/editor and then updating the model with new data, that's the two way data flow.

Now when we need to use this directive in our Angular app, we still need to include the main ck-editor plugin as shown in the first code excerpt.

Method 2 (using ng-ckeditor directive)

ng-ckeditor is written by Github user Vitalii Savchuk does pretty much the same thing, I personally haven't dived in the code or what this plugin actually has under the hood but it gets the job done none the less.

Installation:

bower install ng-ckeditor

// you would still need to include the base plugin script
<script src="//cdn.ckeditor.com/4.5.6/standard/ckeditor.js"></script>   

Setting up:

// injecting dependency
angular.module('myApp', ['ngCkeditor'])

// setup editor custom settings
$scope.editorOptions = {
    // settings more at http://docs.ckeditor.com/#!/guide/dev_configuration
};

Usage:

<textarea ckeditor="editorOptions" ng-model="modelName"></textarea>

Both of these methods are easy to integrate but it depends which one would you want, I personally prefer to be less dependent on something else because I feel it becomes a difficult job to manage all those dependencies and their compatibility with each other over time but that's my personal opinion on this, a lot of people live by the principle: "Why reinvent the wheel when you already have one" it's totally valid in a lot of cases but just doesn't work everytime.

Check out the working JSbin example of the two methods:

See the Pen Angular CKEditor Example with custom directive and ng-ckeditor by Naveen Singh (@official_naveen) on CodePen.

Hope this helps. Happy Coding!

Naveen Singh

Naveen Singh

I am Full Stack Developer from India who loves design, I use Python and Javascript to curb my cravings, with additional dosages of various web and mobile frameworks.

Read More