Search code examples
knockout.jsckeditor

How to update ckeditor data when binding it as knockout observable?


I am trying to work with ckeditor as a knockout.js observable and I am running into some trubles. For a start here is my code:

ko.bindingHandlers.CKEDITOR = {
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
         var ckEditorValue = valueAccessor();
         var id = $(element).attr('id');
         var options = allBindings().EditorOptions;
         var instance = CKEDITOR.replace(id, {
             on: {
                 change: function () {
                     // This moves the caret to the start of the editor on each key pressed
                     ckEditorValue(instance.getData());
                 }
             }
         });
         // instance.setData(ckEditorValue());
     },
update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
         var id = $(element).attr('id');
         var ckEditorValue = valueAccessor();
         CKEDITOR.instances[id].setData(ckEditorValue());
     }
};

The problem I'm facing with this code is that on each key I press and the change event is firing the caret moves to the tope start position of the editor. I tried calling the blur event instead of the change event but it doesn't fire when I click the save button, it fires only when I click on a blank place or moving to a nother control.

How can I keep my observable updated then ?


Solution

  • I've had a similar issue with a different editor, and solved it by removing the update handler and replacing it with a manual subscription. This way, you can introduce some shared state that says 'skip this update, that was me':

    ko.bindingHandlers.CKEDITOR = {
      init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        var ckEditorValue = valueAccessor();
        var id = $(element).attr('id');
        var options = allBindings().EditorOptions;
        var ignoreChanges = false;
    
        var instance = CKEDITOR.replace(id, {
          on: {
            change: function() {
              ignoreChanges = true;
              ckEditorValue(instance.getData());
              ignoreChanges = false;
            }
          }
        });
    
        ckEditorValue.subscribe(function(newValue) {
          if (!ignoreChanges) {
            instance.setData(newValue);
          }
        });
    
      }
    };