Ошибка при попытке реализовать quill-better-table с компонентом редактора quill в Angular

#angular #quill #ngx-quill

#angular #quill #ngx-quill

Вопрос:

Я попробовал несколько способов заставить quill-better-table работать безрезультатно, большинство примеров не для Angular, я получаю сообщение об ошибке «Не удается прочитать свойство ‘insertTable’ неопределенного» Я включу свой код и ошибку ниже, пожалуйста, помогите мне. Примечание: это предназначено для приложения, используемого в производстве.

Это мой HTML-код:

 <div class="card">
  <div ibmGrid>
    <div ibmRow>
      <div ibmCol>
        <button ibmButton="secondary" size="sm" (click)="onInsertTable()">Add table</button>

        <form [formGroup]="editorForm" (ngSubmit)="onSubmit()">
          <div class="form-group">
            <quill-editor [styles]="editorStyle" [modules]="config" formControlName="editor" (onEditorCreated)="editorCreated($event)"></quill-editor>
          </div>
         
          <button ibmButton="primary">Save changes</button>
        </form>
      </div>
    </div>
</div>
 

Это мой код Angular TS:

  import { Component, OnInit, AfterViewInit, ChangeDetectionStrategy } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { DropdownModule, ModalService } from 'carbon-components-angular';
import * as quillBetterTable from 'quill-better-table';


interface Quill {
  getModule(moduleName: string);
}

interface BetterTableModule {
  insertTable(rows: number, columns: number): void;
}

// declare const require: any;
// let Quill: any = null;


@Component({
  selector: 'app-fnl-report',
  templateUrl: './fnl-report.component.html',
  styleUrls: ['./fnl-report.component.scss'],
  // changeDetection: ChangeDetectionStrategy.OnPush
})
export class FnlReportComponent implements OnInit {

  editorForm: FormGroup
  public quill: Quill;

  editorStyle = {
    height: '500px', 
    backgroundColor: '#fff'
  }

  config = {
    toolbar: [
      ['bold', 'italic', 'underline', 'strike'],        // toggled buttons
      ['blockquote', 'code-block'],
      [{ 'header': 1 }, { 'header': 2 }],               // custom button values
      [{ 'list': 'ordered'}, { 'list': 'bullet' }],
      [{ 'script': 'sub'}, { 'script': 'super' }],      // superscript/subscript
      [{ 'indent': '-1'}, { 'indent': ' 1' }],          // outdent/indent
      // [{ 'direction': 'rtl' }],                        // text direction
      [{ 'size': ['small', false, 'large', 'huge'] }],  // custom dropdown
      [{ 'header': [1, 2, 3, 4, 5, 6, false] }],
      [{ 'color': [] }, { 'background': [] }],          // dropdown with defaults from theme
      [{ 'font': [] }],
      [{ 'align': [] }],
      ['clean'],                                        // remove formatting button
      ['link']                                          // link and image, video ['link', 'image', 'video']  
    ]
  }

  constructor() { }

  ngOnInit() {
    this.editorForm = new FormGroup({
      'editor': new FormControl(null)
    });  
  }

  public editorCreated(event: Quill): void {
    this.quill = event;
    // Example on how to add new table to editor
    this.addNewtable();
  }

  private get tableModule(): BetterTableModule {
    return this.quill.getModule("better-table");
  }

  private addNewtable(): void {
    this.tableModule.insertTable(3, 3);
    console.log('Hi');
  }

  onSubmit() {
    console.log(this.editorForm.get('editor').value);
  }

  onInsertTable() {
    // const tableModule = this.quill.getModule('better-table');
    // tableModule.insertTable(3, 3);
  }

}
 

Это мой файл модуля:

 import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { LoadingModule, DropdownModule, GridModule, FileUploaderModule, DialogModule, ButtonModule } from 'carbon-components-angular';
import { Help16Module } from '@carbon/icons-angular/lib/help/16';
import { UploadFilesComponent } from './upload-files/upload-files.component';
import { FnlReportComponent } from './fnl-report/fnl-report.component';
import { ReactiveFormsModule } from '@angular/forms';
import { QuillModule, QuillConfig } from "ngx-quill";
import * as Quill from "quill";
import QuillBetterTable from "quill-better-table";


Quill.register(
  {
    "modules/better-table": QuillBetterTable
  },
  true
);

const quillConfig: QuillConfig = {
  modules: {
    table: false, // disable table module
    "better-table": {
      operationMenu: {
        items: {
          unmergeCells: {
            text: "Another unmerge cells name"
          }
        },
        color: {
          colors: ["#fff", "red", "rgb(0, 0, 0)"], // colors in operationMenu
          text: "Background Colors" // subtitle
        }
      }
    },
    keyboard: {
      bindings: QuillBetterTable.keyboardBindings
    }
  }
};


@NgModule({
  declarations: [
    UploadFilesComponent,
    FnlReportComponent
  ],
  imports: [
    CommonModule,
    LoadingModule,
    DropdownModule,
    GridModule,
    ButtonModule,
    FileUploaderModule,
    Help16Module,
    DialogModule,
    ReactiveFormsModule,
    QuillModule.forRoot(quillConfig)
  ],
  providers:[],
  exports: []
})
export class ImsHubModule { }
 

Это мой импорт css для quill:

 @import '~quill/dist/quill.core.css';
@import '~quill/dist/quill.bubble.css';
@import '~quill/dist/quill.snow.css';
 

Это мои зависимости package.json для quill и quill table:

 "dependencies": {
    "ngx-quill": "^13.0.1",
    "quill": "^1.3.7",
    "quill-better-table": "^1.2.10"
}
 

Это ошибка, которую я получаю:

 FnlReportComponent.html:24 ERROR TypeError: Cannot read property 'insertTable' of undefined
 

Ответ №1:

К сожалению, вы не можете использовать quill-better-table с оболочкой ngx-quill. ngx-quill по-прежнему основан на quilljs версии v1. для quill-better-table требуется quilljs версии v2.0.0-dev.3. Вы можете прочитать об этом в разделе требований: здесь

Я могу поделиться с вами, как я реализовал простую вставку и чтение таблицы в моем случае. Он вдохновлен этой статьей и создан с помощью пользовательского блока. И это неправильный способ добавления элементов в quill. Но мы используем редактор внутри, поэтому мы уверены, что он в надежных руках.

  1. Создайте новый «встраиваемый блок» следующим образом:
 import Quill from 'quill';
const BlockEmbed = Quill.import('blots/block/embed');

    export class TableBlockEmbed extends BlockEmbed {

      static blotName = 'TableBlockEmbed';
      static tagName = 'table';

      static create(value) {
        const node = super.create();
        let valueToReturn = value;
        if (!value.includes('assignedTableId')) {
          const tableId = `assignedTableId-${Date.now()}`;
          valueToReturn = value
            .replace('#tableId', `#${tableId}`)
            .replace('table-layout: fixed;', '');
          node.setAttribute('id', tableId);
        } else {
          const existedId = valueToReturn.match(/#assignedTableId-(d )/i)[1];
          node.setAttribute('id', `assignedTableId-${existedId}`);
        }
        node.innerHTML = this.transformValue(valueToReturn);
        return node;
      }

      static transformValue(value) {
        let handleArr = value.split('n');
        handleArr = handleArr.map(e => e.replace(/^[s] /, '')
          .replace(/[s] $/, ''));
        return handleArr.join('');
      }

      static value(node) {
        return node.innerHTML;
      }
    }
 
  1. Запустите регистрацию нового встроенного блока в конструкторе вашего компонента, который использует ngx-quill:
 constructor() {
    Quill.register(TableBlockEmbed, true);
  }
 
  1. редактор дополнений создал этот код ниже. (вы, конечно, можете добавлять / удалять стили, которые вам нужны. Я добавил, например, margin: 0 auto!важно; потому что я хочу, чтобы таблица всегда была центрирована):
 onEditorCreated(quill: Quill): void {
    quill.clipboard.addMatcher('TABLE', (node, delta) => {
      const Delta = Quill.import('delta');
      const tableTagStyles = node.getAttribute('style');
      return new Delta([
        {
          insert: {
            TableBlockEmbed:
              `<style>#tableId {${tableTagStyles} margin: 0 auto !important; }</style>`   delta.ops[0].insert.TableBlockEmbed
          }
        }
      ]);
    });
  }
 
  1. Я добавил также несколько стилей:
 quill-view,
quill-editor{
  ::ng-deep {
    table {
      width: 100%; // if table has no width - then give it by default 100%
      max-width: 100% !important;
      box-sizing: border-box;
    }
  }
}
 

Я знаю, что это решение — просто обходной путь, но до тех пор, пока я не дождался ngx-quill на основе quill 2, я смог, по крайней мере, предоставить функцию вставки таблиц внутри редактора, которая выглядит довольно красиво.

Пример:

таблица в office word:

введите описание изображения здесь

таблица в ngx-quill:

введите описание изображения здесь

таблица в Excel:

введите описание изображения здесь

таблица в ngx-quill:

введите описание изображения здесь

Комментарии:

1. Для меня это работает нормально, но при редактировании любой ячейки backspace удаляет всю таблицу вместо одного символа.

2. Да, это всего лишь способ разрешить вставку таблиц вообще. Вы можете редактировать некоторый текст внутри таблицы, только выделив некоторый текст и заменив его другим