Angular 7+Ckeditor 5基礎機能統合

47922 ワード

主に2つの機能を実現します:画像は文章の内容をサービス側にアップロードして保存します
メモのみ、参考まで
環境パラメータ
  • @angular/cli 7.3.2
  • macOS 10.14.3
  • nodejs v9.0.0
  • その他の情報はpackageを参照してください.json

  • 環境構築
    まず、angular足場を使用してプロジェクトを初期化します(@angular/cliをグローバルにインストールする必要があります)
    npm install -g @angular/cli
    ng new ckeditor-angular
    

    次に、Ckeditor 5関連依存をインストールし、プロジェクトルートディレクトリに入る
    npm install --save @ckeditor/ckeditor5-angular
    npm install --save @ckeditor/ckeditor5-build-classic
    npm install --save @ckeditor/ckeditor5-ui
    

    最初の2つは必須で、3つ目は保存機能プラグインを作成するためにインストールされています
    インストール後、エディタを使用してプロジェクトを開きます.私はIntellij IDEAを使用しています.
    src/app/app.module.tsにCKEditorModuleを追加し、以下のようにする.
    プレゼンテーションの便宜上、src/app/app.component.htmlsrc/app/app.component.cssを削除し、htmlコンテンツはsrc/app/app.component.tsで作成され、第1版のコードの具体的なコードは以下の通りである.
    // src/app/app.component.ts
    import {Component} from '@angular/core';
    import * as ClassicEditor from '@ckeditor/ckeditor5-build-classic';
    
    @Component({
      selector: 'app-root',
      template: `
        
        
      `
    })
    export class AppComponent {
      public Editor = ClassicEditor;
    }
    

    入力ng serve効果の表示
    これで環境構築完了
    Ckeditorの構成
    2つの構成を完了します:1、中国文化;2、自分で設定するボタンの数のタイプ
    中国文化
    パケットパスnode_modules/@ckeditor/ckeditor5-build-classic/build/translationsに沿って探していくと、zh-cn.jsがtsファイルに追加するとともに、構成オブジェクトconfigが追加され、コンポーネントckeditorに伝達する、app.component.tsは以下のように修正する
    import {Component} from '@angular/core';
    import * as ClassicEditor from '@ckeditor/ckeditor5-build-classic';
    import '@ckeditor/ckeditor5-build-classic/build/translations/zh-cn.js';
    
    @Component({
      selector: 'app-root',
      template: `
        
        
      `
    })
    export class AppComponent {
      public Editor = ClassicEditor;
      //     
      public config = {
        language: 'zh-cn'
      };
    }
    
    

    効果は以下の通りです.
    設定ボタン
    これもそのconfigオブジェクトに配置されています.画像をアップロードするボタンと太めのボタンを追加しましょう.真ん中に区切り記号を1つ記入して、以下のように配置されています.
    //....
    export class AppComponent {
      public Editor = ClassicEditor;
      public config = {
        //     
        language: 'zh-cn',
        toolbar: ['imageUpload', '|', 'bold']
      };
    }
    

    効果は以下の通りです.
    詳細については、公式サイトのドキュメントを参照してください.
    画像をアップロードする機能を追加
    テストファイルサーバの構築
    まず、ファイルアップロードダウンロード機能を簡単に提供するnodejsサーバを構築します.
    ここではルートディレクトリの下にフォルダfile-serverを新規作成し、その中に入りexpressなどの依存をインストールします.
    #   file-server     
    npm init
    npm install --save express
    npm install --save express-fileupload
    npm install --save body-parser 
    

    新しいapp.jsファイルは、その中に基礎コードを記入します.アップロードファイルのフォルダとしてuploadsフォルダを新規作成
    const express = require('express');
    const fileUpload = require('express-fileupload');
    const app = express();
    const path = require('path');
    
    const PORT = 8000;
    
    //     post  
    const bodyParser = require('body-parser')
    app.use(bodyParser.json());
    app.post('/upload/content', function(req, res) {
      console.log(req.body)
      //         
      res.send(req.body)
    })
    
    //          
    app.use(fileUpload());
    
    //       
    app.use('/uploads',express.static('uploads'))
    
    //          
    app.post('/upload', function(req, res) {
      let sampleFile;
      let uploadPath;
    
      if (Object.keys(req.files).length == 0) {
        res.status(400).send('No files were uploaded.');
        return;
      }
    
      console.log('req.files >>>', req.files); // eslint-disable-line
    
      //              file
      sampleFile = req.files.file;
    
      //           ,     
      const filename = (new Date().getTime()) + sampleFile.name;
    
      uploadPath = path.join(__dirname, 'uploads', filename);
    
      sampleFile.mv(uploadPath, function(err) {
        if (err) {
          return res.status(500).send(err);
        }
    
      res.send({default: path.join('uploads', filename)})
      });
    });
    
    app.listen(PORT, function() {
      console.log('Express server listening on port ', PORT); // eslint-disable-line
    });
    
    

    appを起動します.js、8000ポートの傍受;uplaodsフォルダに画像ファイルを入れ、ブラウザでアクセスできます.成功を表します.
    前後が貫通する
    何の構成もしないとフロントエンドはドメイン間でバックエンドファイルサーバにアクセスできません.ここでangularのserverを構成する必要があります.
    ckeditor-angularルートディレクトリの下にファイルproxyを新規作成します.config.json、次のような構成を行います
    {
      "/uploads/*": {
        "target": "http://localhost:8000",
        "secure": false,
        "changeOrigin": true,
        "logLevel": "debug"
      },
      "/upload/*": {
        "target": "http://localhost:8000",
        "secure": false,
        "changeOrigin": true,
        "logLevel": "debug"
      }
    }
    

    1つ目はGETピクチャのすべての要求であり、2つ目はPOSTピクチャのすべての要求である.ng serveを再起動しますが、このプロファイルを読み込む必要があります.
    ng serve --proxy-config proxy.config.json
    

    appを変更します.component.tsコンテンツは、画像にアクセスさせる
    //...
    @Component({
      selector: 'app-root',
      template: `
        
        
      `
    })
    //...
    

    効果は次のとおりです.アクセスに成功しました.
    アップロード画像プラグインの作成
    app.component.ts兄弟ディレクトリの下にファイルを作成するfile upload.ckeditor.tsは、アップロードプラグインを記述し、ほぼフレームワークは以下の通りである.
    /**
     *       
     */
    export class FileUploadAdapter {
    
      constructor(loader) {
        //    
      }
      upload() {
        //     
      }
      abort() {
        //     
      }
    }
    
    /**
     *     ,   ckeditor  
     */
    export function CustomUploadAdapterPlugin(editor) {
      editor.plugins.get('FileRepository').createUploadAdapter = (loader) => {
        return new FileUploadAdapter(loader);
      };
    }
    
    

    最後に、appに2番目の関数を追加する.component.tsのconfigオブジェクト(ここで再構築し、constructorにconfigオブジェクトの初期化を配置する)の一部のコードは以下の通りです.
    // .........
      constructor(private http: HttpClient) {
        this.config = {
          //     
          language: 'zh-cn',
          toolbar: ['imageUpload', '|', 'bold'],
          //      
          extraPlugins: [CustomUploadAdapterPlugin]
        };
      }
    // ........
    

    まず、この2番目の関数のeditorloaderはckeditor注入であり、私たちの使用者とは関係ありません.次に、それらは何の関係もないため、angular送信httpモジュールの初期化にもangular管理と注入があり、私たちとは関係なく、fileuploadにあると言っています.ckeditor.tsでangularのモジュールを使うのはちょっと面倒です.関数パラメータを使用して入力する方法も使いにくいようで、thisの役割ドメインが変わったようです.
    私が与えた解決策はconfigオブジェクトのパラメータとして入力し、fileupload.ckeditor.tsファイルではeditor.config.get()により取得する、app.component.tsファイルは以下の通り、app.module.tsでimportにHttpClientModuleを追加
    もちろん、サービスを自分で作成してhttpの機能をカプセル化して注入することもできます
    import {Component} from '@angular/core';
    import * as ClassicEditor from '@ckeditor/ckeditor5-build-classic';
    import '@ckeditor/ckeditor5-build-classic/build/translations/zh-cn.js';
    import {HttpClient} from '@angular/common/http';
    import {CustomUploadAdapterPlugin} from './fileupload.ckeditor';
    
    @Component({
      selector: 'app-root',
      template: `
        
        
      `
    })
    export class AppComponent {
      public Editor = ClassicEditor;
      public config
    
      constructor(private http: HttpClient) {
        this.config = {
          //     
          language: 'zh-cn',
          toolbar: ['imageUpload', '|', 'bold'],
          //   http
          http,
          extraPlugins: [CustomUploadAdapterPlugin]
        };
      }
    }
    

    fileupload.ckeditor.ts完全コードは以下の通りである
    export class FileUploadAdapter {
      loader;
      http;
      editor;
      constructor(loader, editor) {
        this.loader = loader;
        this.editor = editor;
        //      http  
        this.http = this.editor.config.get('http');
      }
      upload() {
        const data = new FormData();
        //   name file,   app.js   req.files.file    
        data.append('file', this.loader.file);
        return new Promise((resolve, reject) => {
    
          this.http.post(
            '/upload',
            data)
            .subscribe(
              (resp) => {
                console.log(resp)
                resolve({
                  default: resp.default
                });
              },
              (err) => reject(err));
        });
      }
      abort() {
      }
    }
    export function CustomUploadAdapterPlugin(editor) {
      editor.plugins.get('FileRepository').createUploadAdapter = (loader) => {
        //   editor        
        return new FileUploadAdapter(loader, editor);
      };
    }
    

    FileUploadAdapterでは、いくつかの注意点があります.
    1.自作多情設定header Content-Type:multipart/form-data2.注意ckeditorへのresolveが入力したオブジェクトのdefault属性に対応するピクチャへのパスを返す
    テストを行い、アップロードに成功し、file-server/uploadsにさっきアップロードしたファイルがあることを確認します.
    このファイルアップロードサービスの作成が完了しました
    書き込み保存機能
    この要件はckeditorのボタンリストに保存オプションを追加し、クリックしてサーバにデータを転送することです.ここのテストサーバもfile-serverを使用します.
    作成機能ボタン
    新しいファイルckeditor.tsは、以下のコードを記述する
    import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';
    /**
     *           
     */
    export function SaveFilePlugin(editor) {
      //         save   
      editor.ui.componentFactory.add( 'save', locale => {
        const view = new ButtonView( locale );
        //       ,        
        view.set( {
          label: '  ',
          withText: true,
        } );
        //        
        view.on( 'execute', () => {
          console.log('      ');
        } );
        return view;
      } );
    }
    

    appを変更します.component.ts,部分は以下の通りである.
    // .......
      constructor(private http: HttpClient) {
        this.config = {
          language: 'zh-cn',
          //      save   
          toolbar: ['imageUpload', '|', 'bold', '|', 'save'],
          http,
          //    SaveFilePlugin
          extraPlugins: [CustomUploadAdapterPlugin, SaveFilePlugin]
        };
      }
    // ......
    

    テストは下図のようで、ボタンをクリックした後にコンソールは以下の出力があります
    コンテンツの取得
    ここでは、ngModelを使用してckeditorの内容を取得することができ、appに注意する.module.tsでimportがFormsModuleモジュールを追加
    app.component.ts修正部分は以下の通りである
    // ......
    @Component({
      selector: 'app-root',
      template: `
        
        
      `
    })
    export class AppComponent {
      public Editor = ClassicEditor;
      public config
      article = {content: ''};
    // ......
    }
    

    前後が貫通する
    私はappでできることを望んでいます.component.tsで文章をアップロードする論理を実現する.ここでは、閉包技術を用いてこの関数をsavefileに注入することができる.ckeditor.tsファイルのSaveFilePluginでは、thisの役割ドメインを以下のように保持します.
    app.component.ts修正部分は以下の通りである
    //.....
    constructor(private http: HttpClient) {
        this.config = {
          //     
          language: 'zh-cn',
          toolbar: ['imageUpload', '|', 'bold', '|', 'save'],
          http,
          //        config ,   editor.config.get     
          uploadContent: () => this.uploadContent(),
          extraPlugins: [CustomUploadAdapterPlugin, SaveFilePlugin]
        };
      }
    
      /**
       *        
       */
      uploadContent() {
        this.http.post('/upload/content', this.article)
          .subscribe((resp) => {
            console.log(resp);
          }, (err) => {
            console.log(err);
          });
      }
    //.....
    

    savefile.ckeditor.ts修正部分は以下の通りである
    // .....
        view.on( 'execute', () => {
          const func = editor.config.get('uploadContent');
          //           ,   
          func();
        } );
    // .....
    

    ボタンをクリックしてアップロードし、バックグラウンドサーバの出力を表示します.
    まとめ
    完全なコード
    たくさんの穴を踏んで、まとめてみましたが、公式文書はやはり重要です.
  • Rich text editor component for Angular 2+
  • Custom image upload adapter