Contribute to this guide

guide(传统) Angular 富文本编辑器组件

⚠️ 我们更改了安装方法,此传统指南是为了方便用户保留的。如果您正在寻找当前的 CKEditor 5 Angular 集成,请参阅最新的 CKEditor 5 集成 指南。

npm version

CKEditor 5 包含 即用型编辑器构建CKEditor 5 框架,构建基于该框架。

目前,CKEditor 5 的 Angular 组件仅支持通过构建集成 CKEditor 5。由于无法 调整 angular-cli 中的 webpack 配置,因此无法集成 从源代码构建的 CKEditor 5

# 支持的 Angular 版本

由于 Angular 库输出格式的重大更改,@ckeditor/ckeditor5-angular 包发布了以下版本以支持各种 Angular 生态系统

CKEditor 5 版本 Angular 版本 详细信息
积极支持的版本
^6 13+ 需要版本 37 或更高版本的 CKEditor 5。
过去版本(不再维护)
^5 13+ 需要版本 13+ 或更高版本的 Angular。较低版本不再维护。
^5 13+ 需要版本 13+ 或更高版本的 Angular。较低版本不再维护。
^4 9.1+ 需要版本 34 或更高版本的 CKEditor 5。
^3 9.1+ 需要版本 14 或更高版本的 Node.js。
^2 9.1+ 迁移到 TypeScript 4。声明文件不向后兼容。
^1 5.x - 8.x Angular 版本不再维护。

所有可用的 Angular 版本都 列在 npm 上,可以在那里提取。

# 快速入门

在您现有的 Angular 项目中,安装 CKEditor 5 WYSIWYG 编辑器组件 for Angular

npm install --save @ckeditor/ckeditor5-angular

如果您没有现有的项目,可以使用 Angular CLI 创建一个新项目。

安装一个 CKEditor 5 预定义构建创建一个自定义构建

本教程假设您选择了 @ckeditor/ckeditor5-build-classic

npm install --save @ckeditor/ckeditor5-build-classic

@ckeditor/ckeditor5-angular 包需要以下对等依赖项,版本至少为 37.0.0

请记住,它们必须与编辑器构建具有相同的版本。

安装所有必需的对等依赖项

npm install --save @ckeditor/ckeditor5-core @ckeditor/ckeditor5-engine @ckeditor/ckeditor5-utils @ckeditor/ckeditor5-watchdog

现在,将 CKEditorModule 添加到其组件将在模板中使用 <ckeditor> 组件的模块。

// app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { CKEditorModule } from '@ckeditor/ckeditor5-angular';

import { AppComponent } from './app.component';

@NgModule( {
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    CKEditorModule
  ],
  providers: [],
  bootstrap: [ AppComponent ]
} )
export class AppModule { }

在您的 Angular 组件中导入编辑器构建,并将其分配给一个 public 属性,以便模板可以访问它

// app.component.ts

import { Component } from '@angular/core';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';

@Component( {
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
} )
export class AppComponent {
  title = 'angular';
  public Editor = ClassicEditor;
}

最后,在模板中使用 <ckeditor> 标签运行富文本编辑器

<!-- app.component.html -->

<ckeditor [editor]="Editor" data="<p>Hello, world!</p>"></ckeditor>

重建您的应用程序,CKEditor 5 应该会显示“Hello, world!”。

# 使用文档编辑器构建

如果您想使用 文档编辑器构建,您需要 手动将工具栏添加到 DOM

// app.component.ts

import { Component } from '@angular/core';
import DecoupledEditor from '@ckeditor/ckeditor5-build-decoupled-document';

@Component( {
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
} )
export class AppComponent {
  title = 'angular';
  public Editor = DecoupledEditor;

  public onReady( editor: DecoupledEditor ): void {
    const element = editor.ui.getEditableElement()!;
    const parent = element.parentElement!;

    parent.insertBefore(
      editor.ui.view.toolbar.element!,
      element
    );
  }
}

然后,在模板中

<!-- app.component.html -->

<ckeditor [editor]="Editor" data="<p>Hello, world!</p>" (ready)="onReady($event)"></ckeditor>

# 使用自定义 CKEditor 5 构建

如果您想将更多插件添加到现有构建中,或自定义无法使用 编辑器配置 控制的内容,您需要先创建一个自定义构建,如 从源代码构建编辑器 指南中所述。

完成上述教程后,您应该会得到一个生成的 ckeditor.js 文件(以及相应的翻译文件)。在下一步中,您应该将其复制到 src 目录中,并将其导入到组件文件中。

// app.component.ts

import * as Editor from 'path/to/the/ckeditor';

@Component( {
    // ...
} )
export class MyComponent {
    public Editor = Editor;
    // ...
}

请注意,要允许导入 JavaScript 文件而不提供其相应的类型,您需要在 tsconfig.json 文件中将 allowJs 设置为 true。另外,确保您将目标设置为 ES6 或更高版本,否则您可能会遇到 奇怪的转译错误 在生产构建中。

// tsconfig.json

"compilerOptions": {
    "allowJs": true,
    "target": "es2015"
    // other options
}

如果您无法将目标设置为高于 es5,请尝试设置 "buildOptimizer": false,这将生成一个更大的,但正确的生产构建。

# 集成在线构建器构建的版本

本指南假设您使用 CKEditor 5 在线构建器 创建了一个包含编辑器构建的 zip 存档。

将其解压缩到您的应用程序的主目录中。包含编辑器构建的目录不能放置在 src/ 目录中,因为 Node 会返回错误。因此,我们建议将目录放置在 src/node_modules/ 文件夹旁边

├── ckeditor5
│   ├── build
│   ├── sample
│   ├── src
│   ├── ...
│   ├── package.json
│   └── webpack.config.js
├── node_modules
├── src
├── ...
└── package.json

然后,将位于 ckeditor5 目录中的包添加为项目的依赖项

npm install ./ckeditor5

现在,在您的应用程序中导入构建

// app.component.ts

import { Component } from '@angular/core';
import Editor from 'ckeditor5-custom-build/build/ckeditor';

@Component( {
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
} )
export class AppComponent {
  title = 'customEditor';
  public Editor = Editor;
}

# 使用带协作插件的编辑器

在 Angular 应用程序中集成 协作插件 的最简单方法是首先创建一个自定义构建,然后从 Angular 应用程序中导入它。请参见 使用自定义 CKEditor 5 构建

#ngModel 集成

该组件实现了 ControlValueAccessor 接口,并与 ngModel 配合使用。以下是如何使用它

在您的组件中创建一些模型以与编辑器共享

@Component( {
    // ...
} )
export class MyComponent {
    public model = {
        editorData: '<p>Hello, world!</p>'
    };
    // ...
}

在模板中使用该模型来启用双向数据绑定

<ckeditor [(ngModel)]="model.editorData" [editor]="Editor"></ckeditor>

# 支持的 @Input 属性

CKEditor 5 的 Angular 富文本编辑器组件支持以下 @Input 属性

# editor (必需)

Editor 提供静态 create() 方法来创建编辑器实例

<ckeditor [editor]="Editor"></ckeditor>

# config

编辑器的 配置

<ckeditor [config]="{ toolbar: [ 'heading', '|', 'bold', 'italic' ] }" ...></ckeditor>

# data

编辑器的初始数据。它可以是静态值

<ckeditor data="<p>Hello, world!</p>" ...></ckeditor>

或者共享父组件的属性

@Component( {
    // ...
} )
export class MyComponent {
    public editorData = '<p>Hello, world!</p>';
    // ...
}
<ckeditor [data]="editorData" ...></ckeditor>

# tagName

将在其上创建富文本编辑器的 HTML 元素的标签名称。

默认标签是 <div>

<ckeditor tagName="textarea" ...></ckeditor>

# disabled

控制编辑器的 只读 状态

@Component( {
    // ...
} )
export class MyComponent {
    public isDisabled = false;
    // ...
    toggleDisabled() {
        this.isDisabled = !this.isDisabled
    }
}
<ckeditor [disabled]="isDisabled" ...></ckeditor>

<button (click)="toggleDisabled()">
    {{ isDisabled ? 'Enable editor' : 'Disable editor' }}
</button>

# watchdog

ContextWatchdog 类的一个实例,它负责为多个编辑器实例提供相同的上下文,并在发生崩溃时重启整个结构。

import CKSource from 'path/to/custom/build';

const Context = CKSource.Context;
const Editor = CKSource.Editor;
const ContextWatchdog = CKSource.ContextWatchdog;

@Component( {
    // ...
} )
export class MyComponent {
    public editor = Editor;
    public watchdog: any;
    public ready = false;

    ngOnInit() {
        const contextConfig = {};

        this.watchdog = new ContextWatchdog( Context );

        this.watchdog.create( contextConfig )
            .then( () => {
                this.ready = true;
            } );
    }
}
<div *ngIf="ready">
    <ckeditor [watchdog]="watchdog" ...></ckeditor>
    <ckeditor [watchdog]="watchdog" ...></ckeditor>
    <ckeditor [watchdog]="watchdog" ...></ckeditor>
</div>

# editorWatchdogConfig

如果未使用watchdog属性,则默认使用EditorWatchdogeditorWatchdogConfig属性允许传递配置给该看门狗。

@Component( {
    // ...
} )
export class MyComponent {
    public myWatchdogConfig = {
        crashNumberLimit: 5,
        // ...
    };
    // ...
}
<ckeditor [editorWatchdogConfig]="myWatchdogConfig" ...></ckeditor>

# disableTwoWayDataBinding

允许禁用双向数据绑定机制。默认值为false

引入此选项的原因是在大型文档中存在性能问题。默认情况下,在使用ngModel指令时,每当编辑器的数据发生变化时,组件都必须同步编辑器实例和连接属性之间的数据。这会导致调用editor.getData()函数,这会导致在大型文档中键入时出现大规模的减速。

此选项允许集成者禁用默认行为,仅按需调用editor.getData()方法,从而避免了减速。您可以在相关问题中阅读更多内容。

# 支持的@Output属性

以下@Output属性由CKEditor 5 富文本编辑器组件(适用于Angular)支持。

# ready

编辑器准备就绪时触发。它对应于editor#ready事件。
它会与编辑器实例一起触发。

请注意,此方法可能会被多次调用。除了初始化之外,它还会在编辑器在崩溃后重新启动时被调用。不要在内部保留对编辑器实例的引用,因为它将在重新启动的情况下发生变化。相反,您应该使用watchdog.editor属性。

# change

编辑器的内容发生变化时触发。它对应于editor.model.document#change:data事件。
它会与包含编辑器和 CKEditor 5 change:data 事件对象的的对象一起触发。

<ckeditor [editor]="Editor" (change)="onChange($event)"></ckeditor>
import * as ClassicEditor from '@ckeditor/ckeditor5-build-classic';
import { ChangeEvent } from '@ckeditor/ckeditor5-angular/ckeditor.component';

@Component( {
    // ...
} )
export class MyComponent {
    public Editor = ClassicEditor;

    public onChange( { editor }: ChangeEvent ) {
        const data = editor.getData();

        console.log( data );
    }
    ...
}

# blur

编辑器的编辑视图失去焦点时触发。它对应于editor.editing.view.document#blur事件。
它会与包含编辑器和 CKEditor 5 blur 事件数据的对象一起触发。

# focus

编辑器的编辑视图获得焦点时触发。它对应于editor.editing.view.document#focus事件。
它会与包含编辑器和 CKEditor 5 focus 事件数据的对象一起触发。

# error

编辑器崩溃时触发。一旦编辑器崩溃,内部看门狗机制将重新启动编辑器并触发ready事件。

在 ckeditor5-angular v7.0.1之前,此事件不会在编辑器初始化期间崩溃时触发。

# 样式

CKEditor 5 富文本编辑器组件(适用于Angular)可以使用组件样式表或全局样式表进行样式设置。了解如何使用这两种方法设置 CKEditor 5 组件的高度。

# 通过组件样式表设置高度

首先,在父组件的目录中创建一个 (S)CSS 文件,并使用:host::ng-deep伪选择器对给定编辑器部分进行样式设置。

/* src/app/app.component.css */

:host ::ng-deep .ck-editor__editable_inline {
    min-height: 500px;
}

然后,在父组件中添加对上述样式表的相对路径。

/* src/app/app.component.ts */

@Component( {
    // ...
    styleUrls: [ './app.component.css' ]
} )

# 通过全局样式表设置高度

要使用全局样式表对组件进行样式设置,请先创建它。

/* src/styles.css */

.ck-editor__editable_inline {
    min-height: 500px;
}

然后,将其添加到angular.json配置文件中。

"architect": {
    "build": {
        "options": {
            "styles": [
                { "input": "src/styles.css" }
            ]
        }
    }
}

# 设置占位符

要在主可编辑元素中显示占位符,请在 CKEditor 5 富文本编辑器组件配置中设置placeholder字段。

@Component( {
    // ...
} )
export class MyComponent {
    public config = {
        placeholder: 'Type the content here!'
    }
}

# 访问编辑器实例

CKEditor 5 富文本编辑器组件提供了满足大多数用例所需的全部功能。如果需要访问完整的 CKEditor 5 API,您可以通过一个额外的步骤获取编辑器实例。

为此,创建一个指向<ckeditor>组件的模板引用变量#editor

<ckeditor #editor [editor]="Editor" ...></ckeditor>

然后使用由@ViewChild( 'editor' )修饰的属性获取<ckeditor>组件,并在需要时访问编辑器实例。

@Component()
export class MyComponent {
    @ViewChild( 'editor' ) editorComponent: CKEditorComponent;

    public getEditor() {
        // Warning: This may return "undefined" if the editor is hidden behind the `*ngIf` directive or
        // if the editor is not fully initialised yet.
        return this.editorComponent.editorInstance;
    }
}

编辑器创建是异步的,因此editorInstance在编辑器创建之前不可用。如果您想对刚创建的编辑器进行更改,更好的选择是在ready事件中获取 CKEditor 5 实例。

# 本地化

CKEditor 5 富文本编辑器组件可以通过两个步骤进行本地化。

# 加载翻译文件

首先,您需要将翻译文件添加到捆绑包中。此步骤可以通过两种方式实现。

通过在您的组件文件中直接导入给定语言的翻译。

import '@ckeditor/ckeditor5-build-classic/build/translations/de';
import * as ClassicEditor from '@ckeditor/ckeditor5-build-classic';
// More imports.
// ...

通过将翻译文件的路径添加到angular.json中的"scripts"数组中。

"architect": {
    "build": {
        "options": {
            "scripts": [ "node_modules/@ckeditor/ckeditor5-build-classic/build/translations/de.js" ]
        }
    }
}

# 配置语言

然后,您需要配置编辑器以使用给定语言。

@Component( {
    // ...
} )
export class MyComponent {
    public Editor = ClassicEditor;
    public config = {
        language: 'de'
    };
}

有关高级用法,请参阅设置 UI 语言指南。

# 常见问题

# zone.js

在升级到新的 Angular 版本时,zone.js 库存在一个可重复出现的错误。ngOnDestroy 处理程序会崩溃并抛出

ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'data-ck-expando' of undefined
TypeError: Cannot read property 'data-ck-expando' of undefined

解决方法:在polyfills.js中使用import zone.js/dist/zone.js而不是import 'zone.js'来导入 zone.js。
更多详细信息

# 贡献和报告问题

CKEditor 5 富文本编辑器组件(适用于Angular)的源代码在 GitHub 上的https://github.com/ckeditor/ckeditor5-angular中提供。