与knockoutjs内嵌CKEditor的整合

问题描述 投票:6回答:3

所以,我想联编辑从CKEditor的与Knockout.js整合。我能够成功加载CKEditor的和knockout.js。

我似乎无法得到ko.observable更新的属性:

<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>

下面是HTML:

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

该结果的console.log总是显示“ABC”不管你更新与否。注:我也尝试过data-bind="text: editorText"

jquery knockout.js ckeditor
3个回答
12
投票

你必须编写自定义绑定处理程序,以便您的观察特性与CKEditor的实例链接。

首先,你可以从自定义绑定发现here开始。其中一个帖子中包含自定义绑定,虽然我不知道它的工作原理。你必须检查。我复制下来这里,学分不要去我当然是:

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);
    }
} 

然后一个典型的应用是在HTML:

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

其次,你可以检查出最初写的瑞恩·尼迈耶和其他人才更新custom binding handler for TinyMCE。也许TinyMCE可以工作为你而不是CKEditor的?


3
投票

为了回答您的具体问题,你就需要跟踪,其中一个编辑从以便更新不会被触发两次来了。当观察到正在从编辑器不更新你不想在编辑器中重新更新的可观察的突然变化。同样的想法时,编辑器将更新观察到的,你不希望观察的再次通知编辑器。我用布尔跟踪他们。编辑器无关的代码如下:

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;
    }
});

我有一个项目,我是尽我所能得到行内编辑与CKEditor的。我终于放弃了,并试图用TinyMCE的相同类型的代码和解决方案工作。下面的示例使用淘汰赛2.3.0,4.0.8 TinyMCE的和jQuery 1.10.2。 jQuery的可以用常规文档ID访问所取代,但使用jQuery作为快速代码拐杖。结合代码如下:

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;
                }
            });
        }
    }
}

要使用它只是将其绑定到一个div。像这样

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

工作示例可以在这里http://jsfiddle.net/dhQk/2xjKc/我希望这有助于找到。

EDIT:

它看起来像CKEditor的版本的作品毕竟。我不得不使用不同的CDN。的链接,这是http://jsfiddle.net/dhQk/CSwr6/


0
投票

任何人试图用CKEditor的5要做到这一点,下面的工作(传统应用)

ko.bindingHandlers.wysivalue = {
    init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        let showToolbarBinding = allBindings.get('toolbar');
        let showToolbar = ko.unwrap(showToolbarBinding);
        let ckConfig=showToolbar?{toolbar: ["undo", "redo", "bold", "italic", "blockQuote", "ckfinder",  "heading", "link", "numberedList", "bulletedList", "insertTable", "tableColumn", "tableRow", "mergeTableCells"]}
        :{toolbar: []};

        let heightBinding = allBindings.get('height');
        let height = ko.unwrap(heightBinding);
        if (!height) height='250px'

        let isReadOnlyBinding = allBindings.get('readOnly');
        var isReadOnly = ko.unwrap(isReadOnlyBinding);

        let onFieldDataChanged = allBindings.get('onFieldDataChanged');

        var value = valueAccessor();
        var valueUnwrapped = ko.unwrap(value);

        ClassicEditor
        .create(element, ckConfig )
        .then( editor => {
            // var TableList=Array.from( editor.ui.componentFactory.names() );
            editors.set( element, editor );
            editor.isReadOnly = isReadOnly;
            editor.ui.view.editable.editableElement.style.height = height;
            if (ko.isObservable(value)) {
                var isSubscriberChange = false;
                var isEditorChange = true;
                editor.setData(valueUnwrapped);
                var isEditorChange = false;

                editor.model.document.on( 'change:data', (eventInfo, eventName, newValue, oldValue) => {
                    if (!isSubscriberChange) {
                        isEditorChange = true;
                        value(editor.getData());
                        if (onFieldDataChanged) onFieldDataChanged();
                        isEditorChange = false;
                    }
                } );

                value.subscribe(function (newValue) {
                    if (!isEditorChange) {
                        isSubscriberChange = true;
                        editor.setData(newValue);
                        isSubscriberChange = false;
                    }
                });
            }
        } )
        .catch( error => {
            console.error( error );
        } );
    },
}
© www.soinside.com 2019 - 2024. All rights reserved.