使用 Angular JS 中的 CKEditor 内容更新文本区域值

Updating textarea value with CKEditor content in Angular JS

本文关键字:更新 文本 区域 Angular JS 中的 CKEditor 使用      更新时间:2023-09-26

我正在使用最新的CKEditor(标准版),并基于此问题,我已经实现了这样的角度指令,

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 模式下键入内容时,它工作正常,在这里我将键入的内容获取到文本区域的 ng 模型。

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

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

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

在这里演示。

您的指令运行良好。

有一个名为 sourcearea 的插件,用于控制 CKEditor 在源模式下的行为。我看不到该插件的代码中触发任何事件以处理输入。虽然有两个事件可以用来捕获 CKEditor何时返回图形用户界面模式。这些事件是ariaWidgetdataReady

我已经更新了您的示例以使用 dataReady 事件,因此它会在切换回来时更新文本区域。我还更改了 pasteState 事件以进行更改,正如 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);
      };
    }
  };
});

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

编辑:将小提琴链接更新为正确的版本

我知道

这个问题已经得到了回答,但我想我会插话,我将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

对于咖啡脚本文盲,这里是编译的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 集成对我的项目至关重要,所以如果我发现更多的"陷阱",我将更新这个答案。

我希望

这个问题与我的相似。CK编辑器有自己的元素,它注入到DOM中,并且Angular已经渲染,因此您需要为它过渡到代码编辑器时设置一个侦听器。如果您没有侦听更改,则 Angular 无法正确绑定,因为它不知道 DOM 中的更改。我遇到了类似的东西,tinymce和弹出的模态。

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

对我来说

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

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