How can I use AngularJS data binding with CKEditor?

Question!

How should I go about this?

I was able to get the data into CKEditor by using a textarea with the name attribute matching my model and a script tag with ng:bind-template to call CKEDITOR.replace.

I then made a CKEditor plugin that detects changes and writes them back to the textarea. The problem is that the textarea looses its event handlers when CKEditor initializes and CKEditor doesn't pickup changes to the textarea. This makes me think that I am approaching this the wrong way.

Next I tried using ng:eval-order="LAST" ng:eval="setupCKEditor()" and setting up the editor from the setupCKEditor() function. This didn't work because even with ng:eval-order="LAST" the function is still run before the nodes are created.

I have found that adding a setTimeout(function () {...},0) around the CKEDITOR.replace helps. Now the only problem is that when it changes the model it doesn't repaint the screen until another field is edited.

scope.$root.$eval(); seems to fix that.

Update

We ended up abandoning this since we could never get it to reliably work. We switched to TinyMCE with Angular-UI for a while and then ended up building something custom.



Answers

This sort of works with the onchange plugin from http://alfonsoml.blogspot.com/2011/03/onchange-event-for-ckeditor.html.

angular.directive("my:ckeditor", function (expression, compiledElement) {
    return function fn(element) {
        var scope = this;

        setTimeout(function () {
            CKEDITOR.replace("editor-" + index, {extraPlugins: 'onchange'});

            scope.$watch("layers[" + index + "].src", function () {
                if (!CKEDITOR.instances["editor-" + index]) return;
                if (scope[expression] == CKEDITOR.instances["editor-" + index].getData()) return;
                CKEDITOR.instances["editor-" + index].setData(scope[expression]);
            });

            CKEDITOR.instances["editor-" + index].on("change", function () {
                scope[expression] = CKEDITOR.instances["editor-" + index].getData();
                scope.$root.$eval();
            });
        }, 0);
    };
});

Update

This has only been tested on v0.10.6



For completeness, attached is a module to provide an angular directive. I've not used it yet, so I can not comment on how well it works/integrates.



This video can help you solving your question :)
By: admin