Angular,ng-ckeditor和editor-destroy-iframe错误

时间:2018-01-30 16:10:50

标签: angular ckeditor

该帖子是关于ng2-ckeditor@1.1.13的,载有ckeditor@4.8.0。

虽然有一些关于SO的文章有这个问题,但我相信这仍然是一个悬而未决的问题。请不要将此帖子标记为重复。

复制问题:1)使用 ckeditor 指令实例化DOM元素。 2)远离视图,以便托管 ckeditor 的Angular组件被销毁。你可以在Javascript控制台中得到这个:

ckeditor.js:19 [CKEDITOR] Error code: editor-destroy-iframe.

github上有一个closed bug没有明显或可接受的解决方案,除非我错过了。如果有解决方案,我们应该在这篇文章中记录,因为它不完整或模糊不清。

问题显然是Angular框架在 ckeditor 本身被销毁之前销毁 iframe 元素。这会导致诊断消息。

一个建议的解决方案涉及使用名为 divarea 的插件。根据我的理解,这会将 iframe 替换为 div 元素。这有问题的原因是托管页面中的CSS元素将与CKEDITOR使用的CSS混合在一起。

另一个提议的解决方案涉及以下代码片段:

for (name in CKEDITOR.instances) {
    CKEDITOR.instances[name].destroy(true);
}

SO posting提及此问题并询问可以插入此代码的位置。没有Angular生命周期事件似乎有效。即使这样做也不是一个可接受的解决方案,因为它会破坏所有CKEDITOR实例,并且在我的应用程序中,页面上可能存在多个可能在路由器事件中存活的情况。

沿着这些方向,我发现我可以找到"我的"我的Angular组件中的CKEDITOR实例包含这些步骤。在模板中:

  <ckeditor id="content"
            #editor
            [(ngModel)]="editorContent"
            [config]="{}"
            debounce="500"
            name="content"
  ></ckeditor>

除了建立局部变量的 #editor 指令外,这是标准的。然后在组件中,您可以构建一个这样的方法:

declare const CKEDITOR: any;

@Component() ....

  @ViewChild('editor') ckeditor: CKEditorComponent;

  destroyEditor() {
     var name = this.ckeditor.instance.name;
     CKEDITOR.instances[name].destroy(true);
  }

所以问题是:在哪里调用 destroyEditor 函数? (其他问题是 destroy(true)方法是否是正确的方法。)

ngOnDestroy 调用它不起作用。从路由器捕获事件也没有工作。还有其他建议吗?

2 个答案:

答案 0 :(得分:2)

我正在使用Angular 6,这就是我所做的。

我以此方式以编程方式破坏了iFrame

请注意::我不希望有任何编辑者在场,所以我将它们全部销毁了。需要注意的是,如果用户导航离开并返回到CKEDITOR,则您将销毁一个新实例。 (editor2 ... 3 ... 4 ... 5等)我不在乎实例int,所以我销毁了所有实例,并根据用户交互的需要,让angular根据需要创建了新实例。

destroyEditor(){
      let editor = window['CKEDITOR'];
      if(editor.instances){
        for(var editorInstance in editor.instances){
         editor.instances[editorInstance].destroy();
        }
       }
      }

这将使您可以在任何退出条件下销毁iframe。当用户离开编辑器导航时,我会在设置更改UI视图并完成离开编辑器的导航的值之前调用此权限。

  • 它将离开一个文本区域。
  • 如果您正确设置了时间,则用户将不会看到它。

此时您会注意到,您仍然从ckeditor.component.js在控制台中收到错误消息

  • 这是您必须修改 库文件。
  • 这是因为CKEditorComponent.prototype.ngOnDestroy函数中的if条件仅检查实例,而不检查实例名称是否存在。
  • 即使实例已被销毁,该实例似乎始终对我评估为true。 (例如:editor1,editor2,editor3等)
  • 发生ngDestroy时,实例名称不存在...因为...您已经销毁了它。

在以下文件中进行此更改。

\node_modules\ng2-ckeditor\lib\src\ckeditor.component.js

这将专门检查实例名称,而不会尝试销毁...,因为您已经销毁了它。

CKEditorComponent.prototype.ngOnDestroy = function () {
        var _this = this;
        //if (this.instance) {
        if(CKEDITOR.instances[_this.instance.name]) {
            setTimeout(function () {
                _this.instance.removeAllListeners();
                CKEDITOR.instances[_this.instance.name].destroy();
                _this.instance.destroy();
                _this.instance = null;
            });
        }
    };

答案 1 :(得分:1)

如果不需要修改node_module下的JS文件,就像我这样,请从ngOnDestroy()调用以下函数:

public destroyEditor(): void {
  const editor = window['CKEDITOR'];
  if (editor.instances) {
      for (const editorInstance in editor.instances) {
          if (editor.instances.hasOwnProperty(editorInstance) && 
              editor.instances[editorInstance]) {
              editor.instances[editorInstance].destroy();
              editor.instances[editorInstance] = {
                  destroy: () => true,
              };
          }
      }
}

请注意,销毁后,当要从本机函数销毁组件时,会将一个伪对象分配给收集项以防止JS错误。 该组件必须实现OnDestroy接口和destroyEditor()函数,如下所示:

export class RichTextEditorComponent implements OnDestroy {
    public ngOnDestroy(): void {
        this.destroyEditor();
    }
}

相关问题