quill-better-table icon indicating copy to clipboard operation
quill-better-table copied to clipboard

Is there any way to display operationMenu buttons in quill's toolbar instead of the right click pop up ?

Open Denis-Dev-2020 opened this issue 7 months ago • 0 comments

this is my best failed try :

import { Component, ViewChild, Output, EventEmitter, AfterViewInit, Inject, PLATFORM_ID, ElementRef } from '@angular/core';
import { FormControl, FormGroup, Validators, ReactiveFormsModule, NgForm, FormsModule } from '@angular/forms';
import { CommonModule, isPlatformBrowser } from '@angular/common';
import { combineLatest } from 'rxjs';
import { first } from 'rxjs/operators';
import Quill from 'quill';
import QuillBetterTable from 'quill-better-table'
import { Post } from '../../models/Post';
import { AuthService } from "../../services/auth.service";
import { PostService } from "../../services/post.service";
import { DatamediatorpostsService } from '../../services/datamediator/datamediatorposts.service';
import DOMPurify from 'dompurify';

@Component({
  selector: 'app-createpost',
  standalone: true,
  imports: [CommonModule, ReactiveFormsModule, FormsModule],
  templateUrl: './createpost.component.html',
  styleUrls: ['./createpost.component.css']
})
export class CreatepostComponent implements AfterViewInit {
  @ViewChild("editor", { static: false }) editorElementRef!: ElementRef;
  @Output() create: EventEmitter<any> = new EventEmitter();
  selectedTopic!: number;
  selectedSubtopic!: number;

  form: FormGroup;
  quillEditor: any;

  constructor(
    @Inject(PLATFORM_ID) private platformId: object,
    private authService: AuthService,
    private postService: PostService,
    private datamediatorpostsService: DatamediatorpostsService
  ) {
    this.form = this.createFormGroup();

    this.datamediatorpostsService.getSelectedTopic$().subscribe(topic => {
      if (topic != null) {
        this.selectedTopic = topic;
      }
    });

    this.datamediatorpostsService.getSelectedSubTopic$().subscribe(subtopic => {
      if (subtopic != null) {
        this.selectedSubtopic = subtopic;
      }
    });
  }

  ngAfterViewInit(): void {
    if (isPlatformBrowser(this.platformId) && this.editorElementRef) {
      this.initializeQuillEditor();
    }
  }

async initializeQuillEditor(): Promise<void> {
  const { default: Quill } = await import('quill');
  const { default: QuillBetterTable } = await import('quill-better-table');

  Quill.register('modules/better-table', QuillBetterTable, true);

  this.quillEditor = new Quill(this.editorElementRef.nativeElement, {
    theme: 'snow',
    modules: {
      table: false,
      'better-table': {
        operationMenu: {
          items: {
            insertColumnRight: false,
            insertColumnLeft: {
              text: 'Insert Column',
            },
            insertRowUp: {
              text: 'Insert Row Up',
            },
            insertRowDown: {
              text: 'Insert Row Down',
            },
            mergeCells: false,
            unmergeCells: false,
            deleteColumn: {
              text: 'Delete Selected Column',
            },
            deleteRow: {
              text: 'Delete Selected Row',
            },
            deleteTable: {
              text: 'Delete Table',
            }
          }
        }
      },
      toolbar: {
        container: [
          ['bold', 'italic', 'underline', 'strike'],
          ['blockquote', 'code-block'],
          [{ 'header': 1 }, { 'header': 2 }],
          [{ 'list': 'ordered' }, { 'list': 'bullet' }],
          [{ 'script': 'sub' }, { 'script': 'super' }],
          [{ 'indent': '-1' }, { 'indent': '+1' }],
          [{ 'direction': 'rtl' }],
          [{ 'size': ['small', false, 'large', 'huge'] }],
          [{ 'header': [1, 2, 3, 4, 5, 6, false] }],
          [{ 'color': [] }, { 'background': [] }],
          [{ 'font': [] }],
          [{ 'align': [] }],
          ['clean'],
          [{ 'better-table': true }],
          ['insertColumnLeft', 'insertRowUp', 'deleteTable']
        ],
        handlers: {
          'better-table': () => {
            const tableModule: any = this.quillEditor.getModule('better-table');
            if (tableModule && tableModule.options) {
              tableModule.options.show();
            } else {
              console.error('Better Table Module or operationMenu is not defined');
            }
          },
          'insertColumnLeft': () => {
            const tableModule: any = this.quillEditor.getModule('better-table');
            if (tableModule && tableModule.options) {
              tableModule.options.insertColumnLeft();
            } else {
              console.error('Better Table Module or operationMenu is not defined');
            }
          },
          'insertRowUp': () => {
            const tableModule: any = this.quillEditor.getModule('better-table');
            if (tableModule && tableModule.options) {
              tableModule.options.insertRowUp();
            } else {
              console.error('Better Table Module or operationMenu is not defined');
            }
          },
          'deleteTable': () => {
            const tableModule: any = this.quillEditor.getModule('better-table');
            if (tableModule && tableModule.options) {
              tableModule.operationMenu.deleteTable();
            } else {
              console.error('Better Table Module or operationMenu is not defined');
            }
          }
        }
      }
    }
  });

  console.log('Quill editor initialized with full better-table configuration:', this.quillEditor);

  this.quillEditor.on('text-change', () => {
    const formBodyControl = this.form.get('body');
    if (formBodyControl) {
      formBodyControl.setValue(this.quillEditor.root.innerHTML);
    } else {
      console.error('Form control "body" is not defined');
    }
  });

  this.editorElementRef.nativeElement.addEventListener('contextmenu', (event: MouseEvent) => {
    event.preventDefault();
    const tableModule: any = this.quillEditor.getModule('better-table');
    if (tableModule && tableModule.operationMenu) {
      tableModule.operationMenu.show(event.clientX, event.clientY);
    } else {
      console.error('Better Table Module or operationMenu is not defined');
    }
  });
}


  onInsertTable() {
    const tableModule = this.quillEditor.getModule('better-table');
    if (tableModule) {
      tableModule.insertTable(5, 5);
    } else {
      console.error('Better Table Module is not defined');
    }
  }

  createFormGroup(): FormGroup {
    const formGroup = new FormGroup({
      title: new FormControl('', [
        Validators.required,
        Validators.minLength(5)
      ]),
      body: new FormControl('', [
        Validators.required,
        Validators.minLength(10)
      ])
    });
    return formGroup;
  }

  onSubmit(formData: Pick<Post, "title" | "body">): void {
    const userId = this.authService.userId;
    if (userId) {
      formData.body = DOMPurify.sanitize(formData.body);
      this.postService.createPost(this.selectedTopic, this.selectedSubtopic, formData, userId).subscribe(() => {
        this.create.emit(null);
        this.form.reset();
      });
    } else {
      console.error('Authorization error');
    }
  }
}

it seems the i cannot access (or don't know how to access) operationMenu functionality so i could handle the methods in my handler

Denis-Dev-2020 avatar Jun 26 '24 21:06 Denis-Dev-2020