6

そのため、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"

4

3 に答える 3

12

You have to write your custom binding handler in order for your observable property to be linked with an instance of CKEditor.

First, you could start from the custom binding found here. One of the posts contains a custom binding, though I'm not sure it works. You have to check. I copied it down here, credits do not go to 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);
    }
} 

A typical use then would be in the HTML:

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

Secondly, you could check out the custom binding handler for TinyMCE initially written by Ryan Niemeyer and updated by other talented people. Maybe TinyMCE could work out for you instead of CKEditor ?

于 2013-04-29T17:35:14.863 に答える
3

特定の質問に答えるには、更新が2回トリガーされないように、編集がどこから来たのかを追跡する必要があります。オブザーバブルがエディターからではなく更新されている場合、エディターの突然の変更によってオブザーバブルが再更新されることは望ましくありません。エディターがオブザーバブルを更新するときも同じ考えです。オブザーバブルがエディターに再度通知することは望ましくありません。私はそれらを追跡するためにブール値を使用していました。エディターに依存しないコードは次のとおりです。

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、tinymce 4.0.8、および 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/ にあります。

編集:

やはりCKEditor版は動くようです。別のcdnを使用する必要がありました。そのリンクはhttp://jsfiddle.net/dhQk/CSwr6/です

于 2013-10-18T03:36:07.250 に答える