2013-04-29 52 views
6

所以我试图从CKEditor集成内联编辑与Knockout.js。我能够成功加载CKEditor和knockout.js。嵌入式CKEditor与knockoutjs集成

我似乎无法得到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"

+1

html绑定是[不是双向](https://github.com/SteveSanderson/knockout/issues/430)。你需要创建自己的[contenteditable自定义绑定](http://stackoverflow.com/questions/7904522/knockout-content-editable-custom-binding)。 – nemesv 2013-04-29 17:26:56

+0

就是这样。谢谢! – jmogera 2013-04-29 17:33:22

+0

还有Froala,它不会把你的CSS内联。淘汰赛插件:https:// github。com/froala/knockout-froala – 2015-11-03 17:24:18

回答

11

您必须编写自定义绑定处理程序,以便将您的observable属性与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?

+0

它适用于内联编辑吗? – jmogera 2013-04-29 17:40:14

+0

犯错,我真的不知道。我首先需要去CKEditor4的网站了解“内联编辑”的意思:-)但看到它的最好方法是编写代码:-) – Jalayn 2013-04-29 17:42:49

+3

Steve Sanderson是knockoutJs的创建者,Ryan Niemeyer只是一个很棒的的家伙。 – 2013-07-22 13:46:45

2

要回答您的具体问题,您需要跟踪编辑的来源,以便更新不会触发两次。当observable不是从编辑器更新时,您不希望编辑器中的突然更改重新更新observable。当编辑器更新observable时,同样的想法,你不希望observable再次通知编辑器。我习惯布尔人跟踪他们。编辑不可知的代码如下:

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,并且解决方案工作。下面的例子使用knockout 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/