14

我正在使用最新的 CKEditor (Standard Version) 并且基于这个 问题,我已经实现了一个像这样的角度指令,

var cmsPlus = angular.module('cmsPlus', []);

cmsPlus.directive('ckEditor', function() {
  return {
    require: '?ngModel',
    link: function(scope, elm, attr, ngModel) {
      var ck = CKEDITOR.replace(elm[0]);

      if (!ngModel) return;

      ck.on('pasteState', function() {
        scope.$apply(function() {
          ngModel.$setViewValue(ck.getData());
        });
      });

      ngModel.$render = function(value) {
        ck.setData(ngModel.$viewValue);
      };
    }
  };
});

当我在 CKEditor GUI 模式下输入内容时它工作正常,在这里我将输入的内容输入到 textarea 的 ng-model。

但是当我切换到代码编辑器时,即使切换回 GUI 也没有得到更新的内容。需要在图形模式下再次键入内容。

我的指令有什么问题?或者我可以用其他一些 CKEditor 事件扩展这个指令吗?

我想为表单提交或其他内容添加更多事件。

演示在这里。

4

4 回答 4

27

您的指令运行良好。

有一个名为sourcearea的插件可以控制 CKEditor 在源模式下的行为。我看不到在该插件的代码中触发任何事件以处理输入。当 CKEditor 返回 GUI 模式时,我们可以使用两个事件来捕获。事件是ariaWidgetdataReady

我已经更新了您的示例以使用dataReady事件,因此它会在切换回来时更新 textarea。我还将pasteState事件更改为change,正如Dan Caragea 所说,它是在 4.2 版中引入的。 更新的小提琴可以在这里找到

我发现一个几乎可行的解决方案是监听关键事件并更新模型。它几乎就在那里,因为似乎该事件仅在按下旧键时才被触发。所以最后一个键总是丢失。

var cmsPlus = angular.module('cmsPlus', []);

cmsPlus.directive('ckEditor', function() {
  return {
    require: '?ngModel',
    link: function(scope, elm, attr, ngModel) {
      var ck = CKEDITOR.replace(elm[0]);

      if (!ngModel) return;

      ck.on('instanceReady', function() {
        ck.setData(ngModel.$viewValue);
      });

      function updateModel() {
          scope.$apply(function() {
              ngModel.$setViewValue(ck.getData());
          });
      }

      ck.on('change', updateModel);
      ck.on('key', updateModel);
      ck.on('dataReady', updateModel);

      ngModel.$render = function(value) {
        ck.setData(ngModel.$viewValue);
      };
    }
  };
});

无论如何,也许您可​​以从中弄清楚如何解决最后一个关键问题。快到了!

编辑:更新小提琴链接到正确版本

于 2013-09-27T14:13:32.933 回答
9

我知道这个问题已经得到解答,但我想我会加入将 CKEditor 4.4.4 与 angularjs 1.2 集成所需做的事情。这是我在咖啡脚本中的代码:

'use strict'

angular.module 'core', []

.directive 'ckeditor', ->
    require: '?ngModel'
    link: (scope, element, attrs, ngModel) ->
        config =
            # CKEditor config goes here

        editor = CKEDITOR.replace element[0], config

        return unless ngModel

        editor.on 'instanceReady', ->
            editor.setData ngModel.$viewValue

        updateModel = ->
            scope.$apply ->
                ngModel.$setViewValue editor.getData()

        editor.on 'change', updateModel
        editor.on 'dataReady', updateModel
        editor.on 'key', updateModel
        editor.on 'paste', updateModel
        editor.on 'selectionChange', updateModel

        ngModel.$render = ->
            editor.setData ngModel.$viewValue

对于coffeescript 文盲,这里是编译好的javascript:

'use strict';
angular.module('core', []).directive('ckeditor', function() {
    return {
      require: '?ngModel',
      link: function(scope, element, attrs, ngModel) {
        var config, editor, updateModel;
        config = {
            // CKEditor config goes here
        }
        editor = CKEDITOR.replace(element[0], config);
        if (!ngModel) {
          return;
        }
        editor.on('instanceReady', function() {
          return editor.setData(ngModel.$viewValue);
        });
        updateModel = function() {
          return scope.$apply(function() {
            return ngModel.$setViewValue(editor.getData());
          });
        }};
        editor.on('change', updateModel);
        editor.on('dataReady', updateModel);
        editor.on('key', updateModel);
        editor.on('paste', updateModel);
        editor.on('selectionChange', updateModel);
        return ngModel.$render = function() {
          return editor.setData(ngModel.$viewValue);
        };
      }
    };
  }
);

然后在 HTML 中:

<textarea ckeditor data-ng-model="myModel"></textarea>

现在来解释一下。

为了完整性,我添加了粘贴和选择更改处理程序,但事实证明选择更改处理程序是必要的。我发现如果我选择了所有并点击删除,那么——在没有将焦点从编辑器上移开的情况下——提交了表单,提交时模型中没有反映的更改。选择更改处理程序解决了这个问题。

将 CKEditor 与 angularjs 集成对我的项目来说是关键任务,所以如果我发现更多“陷阱”,我会更新这个答案。

于 2014-09-01T06:47:32.673 回答
0

我希望这个问题与我的相似。CK 编辑器有自己的元素,它会注入到 DOM 中,并且 Angular 已经呈现,因此您需要设置一个侦听器,以便它转换到代码编辑器时。如果您没有监听更改,那么 Angular 将无法正确绑定,因为它不知道 DOM 中的更改。我遇到了与 tinymce 和弹出的模态类似的东西。

这是与我的问题相关的另一个资源

于 2013-09-25T16:46:31.300 回答
0

对我来说,@Mjonir74 的回答有效,但是一旦我在一个页面上有多个编辑器实例并且还必须考虑编辑模式而不仅仅是创建模式,当你回到页面时事情开始无法正常工作包含编辑器。基本上在编辑模式下,你第一次访问页面时,一切都很好,文本在编辑器中是应该的。但是对同一页面的任何连续访问都会使编辑器为空,没有文字。

这是它为我工作的方式:

    app.directive('appWysiwygBlock', function() {
    return {
        require: 'ngModel',
        restrict: 'E',
        templateUrl: 'modules/app/templates/directives/wysiwyg-block.html',
        scope: {
            error: '=',
            config: '='
        },
        link: function(scope, element, attrs, ngModel) {

            if (typeof CKEDITOR == 'undefined' || !ngModel) {
                return;
            }

            scope.required = attrs.required || false;
            scope.cols = attrs.cols || 6;

            scope.label = attrs.label || attrs.name;
            scope.name = attrs.name || scope.label;
            if (scope.name) {
                scope.name = scope.name.toLowerCase().replace(/[^a-z0-9]/gi, '_');
            }

            var defaultConfig, config, editor, updateModel;

            config = scope.config || {};
            defaultConfig = {
                customConfig: '/modules/app/ckeditor-config.js'
            };

            config = element.extend({}, defaultConfig, config);
            editor = CKEDITOR.replace(element.find('textarea:first')[0], config);

            updateModel = function() {
                return scope.$apply(function() {
                    return ngModel.$setViewValue(editor.getData());
                });
            };

            editor.on('instanceReady', function() {
                editor.on('change', updateModel);
                editor.on('dataReady', updateModel);
                editor.on('key', updateModel);
                editor.on('paste', updateModel);
                editor.on('selectionChange', updateModel);
                return editor.setData(ngModel.$viewValue);
            });

            return ngModel.$render = function() {
                return editor.setData(ngModel.$viewValue);
            };
        }
    };
});

我用它作为

<app-wysiwyg-block label="Description" name="description" ng-model="item.description" error="fieldErrors.description" required="true" cols="12"></app-wysiwyg-block>

页面中的任意次数,并且在所有模式下都可以正常工作。

于 2016-02-16T08:51:34.723 回答