Integrated CKEditor integration with knockoutjs

So, I'm trying to integrate Inline Editing from CKEditor using Knockout.js. I can successfully download CKEditor and knockout.js.

I just can't get ko.observable to update the property:

<script type="text/javascript"> var viewModel = function () { var self = this; self.editorText = ko.observable('ABC'); self.testNewValue = function () { console.log(this.editorText()); }; } ko.applyBindings(new viewModel()); </script> 

Here is the html:

 <div id="editable" contenteditable="true" data-bind="html: editorText"> </div> <div> <input type="button" data-bind="click: testNewValue" value="test" /> </div> 

The result of console.log always shows "ABC" regardless of whether it is updated or not. Note. I also tried data-bind="text: editorText"

+6
source share
2 answers

You must write your own binding handler so that your observable property is associated with the CKEditor instance.

First you can start with the custom binding found here . One of the posts contains a user binding, although I'm not sure if it works. You must check. I copied it here, loans do not suit me, of course:

 ko.bindingHandlers.ckEditor = { init: function (element, valueAccessor, allBindingsAccessor, viewModel) { var txtBoxID = $(element).attr("id"); var options = allBindingsAccessor().richTextOptions || {}; options.toolbar_Full = [ ['Source', '-', 'Format', 'Font', 'FontSize', 'TextColor', 'BGColor', '-', 'Bold', 'Italic', 'Underline', 'SpellChecker'], ['NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote', 'CreateDiv', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock', '-', 'BidiLtr', 'BidiRtl'], ['Link', 'Unlink', 'Image', 'Table'] ]; // handle disposal (if KO removes by the template binding) ko.utils.domNodeDisposal.addDisposeCallback(element, function () { if (CKEDITOR.instances[txtBoxID]){ CKEDITOR.remove(CKEDITOR.instances[txtBoxID]); } }); $(element).ckeditor(options); // wire up the blur event to ensure our observable is properly updated CKEDITOR.instances[txtBoxID].focusManager.blur = function () { var observable = valueAccessor(); observable($(element).val()); }; }, update: function (element, valueAccessor, allBindingsAccessor, viewModel) { var val = ko.utils.unwrapObservable(valueAccessor()); $(element).val(val); } } 

Typical use will then be in HTML:

 <textarea id="txt_viewModelVariableName" data-bind="ckEditor: viewModelVariableName"></textarea> 

Secondly, you can check out the custom binding engine for TinyMCE , originally written by Ryan Niemeyer and updated by other talented people. Maybe TinyMCE might work for you instead of CKEditor?

+11
source

To answer your specific question, you will need to keep track of where the editing is coming from so that the update does not start twice. When an observable is updated from outside the editor, you do not want a sudden change in the editor to re-update the observable. The same idea, when the editor updates the observable, you do not want the observable to notify the editor again. I used to track them. Agnostic code below:

 var isObservableChange = false; var isEditorChange = false; editor.change = function () { if(!isObservableChange){ isEditorChange = true; observable(editor.data); isEditorChange = false; } }; observable.subscribe(function (newValue) { if(!isEditorChange){ isObservableChange = true; editor.data = observable(); isObservableChange = false; } }); 

I had a project in which I tried to do inline editing using CKEditor. I finally gave up and tried TinyMCE with the same type of code, and the solution worked. The following example uses knockout 2.3.0, tinymce 4.0.8, and jquery 1.10.2. Jquery can be replaced with normal document access, but I use jquery as a crutch for quick code. The binding code is as follows:

 ko.bindingHandlers.wysiwyg = { init: function (element, valueAccessor, allBindingsAccessor, viewModel) { var value = valueAccessor(); var valueUnwrapped = ko.unwrap(value); var allBindings = allBindingsAccessor(); var $element = $(element); $element.attr('id', 'wysiwyg_' + Date.now()); if (ko.isObservable(value)) { var isSubscriberChange = false; var isEditorChange = true; $element.html(value()); var isEditorChange = false; tinymce.init({ selector: '#' + $element.attr('id'), inline: true, plugins: [ "advlist autolink lists link image charmap print preview anchor", "searchreplace visualblocks code fullscreen", "insertdatetime media table contextmenu paste" ], toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image", setup: function (editor) { editor.on('change', function () { if (!isSubscriberChange) { isEditorChange = true; value($element.html()); isEditorChange = false; } }); } }); value.subscribe(function (newValue) { if (!isEditorChange) { isSubscriberChange = true; $element.html(newValue); isSubscriberChange = false; } }); } } } 

To use it, just bind it to the div. So

 <div data-bind="wysiwyg: test"></div> 

A working example can be found here http://jsfiddle.net/dhQk/2xjKc/ Hope this helps.

EDIT:

It seems that the CKEditor version works in the end. I just had to use another cdn. The link for this is http://jsfiddle.net/dhQk/CSwr6/

+2
source

Source: https://habr.com/ru/post/943893/


All Articles