KillerCodeMonkey / ngx-quill

Angular (>=2) components for the Quill Rich Text Editor
MIT License
1.78k stars 260 forks source link

Custom toolbar select giving Typescript error at Compile #1918

Closed justinbkay closed 2 months ago

justinbkay commented 2 months ago

Hello,

I have tried this code out in a CDN version of quill 2.0 and it works fine. I'm attempting to add a custom drop down to the toolbar.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Quill Custom Dropdown</title>
    <link
      href="https://cdn.jsdelivr.net/npm/quill@2/dist/quill.snow.css"
      rel="stylesheet"
    />
    <script src="https://cdn.jsdelivr.net/npm/quill@2/dist/quill.js"></script>
    <style>
      .ql-snow .ql-custom-dropdown.ql-picker {
        width: 144px;
        padding-left: 8px;
      }
    </style>
  </head>
  <body>
    <!-- Create the editor container -->
    <div id="editor"></div>

    <!-- Custom Dropdown Module -->
    <script>

      const quill = new Quill("#editor", {
        theme: "snow",
        modules: {
          toolbar: {
            container: [
              [{ header: [1, 2, false] }],
              [{ font: [] }],
              [{ "custom-dropdown": ["", "hamburger", "hotdog", "coke"] }],
              ["bold", "italic", "underline"],
              ["image", "code-block"],
            ],
            handlers: {
              "custom-dropdown": function (value) {
                const range = this.quill.getSelection(); // Get current cursor position
                if (range) {
                  this.quill.insertText(range.index, value, "user"); // Insert the selected value
                  this.quill.setSelection(range.index + value.length); // Move the cursor after the inserted text
                }
                console.log("Custom dropdown value:", value);
              },
            },
          },
        },
      });
      const customDropdownItems = Array.prototype.slice.call(
        document.querySelectorAll(".ql-custom-dropdown .ql-picker-item"),
      );

      customDropdownItems.forEach(
        (item) => (item.textContent = item.dataset.value),
      );

      document.querySelector(".ql-custom-dropdown .ql-picker-label").innerHTML =
        "Tags" +
        document.querySelector(".ql-custom-dropdown .ql-picker-label")
          .innerHTML;
    </script>
  </body>
</html>

When I try the same in my Angular version with ngx-quill, it seems fine in the editor, no typescript issues, but when it gets compiled, I get this error:

✘ [ERROR] NG2: Type '{ table: boolean; toolbar: { container: (string[] | { font: never[]; }[] | { size: (string | boolean)[]; }[] | { customStyles: number[]; }[] | { script: string; }[] | ({ color: never[]; background?: undefined; } | { background: never[]; color?: undefined; })[] | { ...; }[] | { ...; }[] | { ...; }[] | { ...; }[])[]; ...' is not assignable to type 'QuillModules'.
  Types of property 'toolbar' are incompatible.
    Type '{ container: (string[] | { font: never[]; }[] | { size: (string | boolean)[]; }[] | { customStyles: number[]; }[] | { script: string; }[] | ({ color: never[]; background?: undefined; } | { background: never[]; color?: undefined; })[] | { ...; }[] | { ...; }[] | { ...; }[] | { ...; }[])[]; handlers: { ...; }; }' is not assignable to type 'string | boolean | QuillToolbarConfig | { container?: string | string[] | QuillToolbarConfig | undefined; handlers?: { [key: string]: any; } | undefined; } | undefined'.
      Type '{ container: (string[] | { font: never[]; }[] | { size: (string | boolean)[]; }[] | { customStyles: number[]; }[] | { script: string; }[] | ({ color: never[]; background?: undefined; } | { background: never[]; color?: undefined; })[] | { ...; }[] | { ...; }[] | { ...; }[] | { ...; }[])[]; handlers: { ...; }; }' is not assignable to type '{ container?: string | string[] | QuillToolbarConfig | undefined; handlers?: { [key: string]: any; } | undefined; }'.
        Types of property 'container' are incompatible.
          Type '(string[] | { font: never[]; }[] | { size: (string | boolean)[]; }[] | { customStyles: number[]; }[] | { script: string; }[] | ({ color: never[]; background?: undefined; } | { background: never[]; color?: undefined; })[] | { ...; }[] | { ...; }[] | { ...; }[] | { ...; }[])[]' is not assignable to type 'string | string[] | QuillToolbarConfig | undefined'.
            Type '(string[] | { font: never[]; }[] | { size: (string | boolean)[]; }[] | { customStyles: number[]; }[] | { script: string; }[] | ({ color: never[]; background?: undefined; } | { background: never[]; color?: undefined; })[] | { ...; }[] | { ...; }[] | { ...; }[] | { ...; }[])[]' is not assignable to type 'string[]'.
              Type 'string[] | { font: never[]; }[] | { size: (string | boolean)[]; }[] | { customStyles: number[]; }[] | { script: string; }[] | ({ color: never[]; background?: undefined; } | { background: never[]; color?: undefined; })[] | { ...; }[] | { ...; }[] | { ...; }[] | { ...; }[]' is not assignable to type 'string'.
                Type 'string[]' is not assignable to type 'string'. [plugin angular-compiler]`

This is my toolbar code:
`const toolbarOptions = [
  [{ font: [] }],
  [{ size: ['small', false, 'large', 'huge'] }],
  [{ customStyles: [1, 2] }],
  ['bold', 'italic', 'underline', 'strike'],
  [{ script: 'sub' }, { script: 'super' }],
  [{ color: [] }, { background: [] }],
  [{ list: 'ordered' }, { list: 'bullet' }, { list: 'check' }],
  [{ align: [] }],
  ['blockquote'],
  ['image'],
  [{ indent: '-1' }, { indent: '+1' }],
  [{ direction: 'rtl' }],
  ['table-better'],
];

modules = {
    table: false,
    toolbar: {
      container: toolbarOptions,
      handlers: {
        customStyles: function (value: any, quillInstance: any) {
          if (value) {
            console.log(`Selected: ${value}`);
          }
        },
      },
    },
...

This is Angular 18.1.0 and ngx-quill 26.0.5.

Best regards, Justin

KillerCodeMonkey commented 2 months ago

can you please try v26.0.6?

justinbkay commented 2 months ago

Hi, this is on 26.0.6

✘ [ERROR] NG2: Type '{ table: boolean; toolbar: { container: (string[] | { font: never[]; }[] | { size: (string | boolean)[]; }[] | { customStyles: number[]; }[] | { script: string; }[] | ({ color: never[]; background?: undefined; } | { background: never[]; color?: undefined; })[] | { ...; }[] | { ...; }[] | { ...; }[] | { ...; }[])[]; ...' is not assignable to type 'QuillModules'.
  Types of property 'toolbar' are incompatible.
    Type '{ container: (string[] | { font: never[]; }[] | { size: (string | boolean)[]; }[] | { customStyles: number[]; }[] | { script: string; }[] | ({ color: never[]; background?: undefined; } | { background: never[]; color?: undefined; })[] | { ...; }[] | { ...; }[] | { ...; }[] | { ...; }[])[]; handlers: { ...; }; }' is not assignable to type 'string | boolean | QuillToolbarConfig | { container?: string | string[] | QuillToolbarConfig | Record<string, string | string[]>[] | undefined; handlers?: { ...; } | undefined; } | undefined'.
      Type '{ container: (string[] | { font: never[]; }[] | { size: (string | boolean)[]; }[] | { customStyles: number[]; }[] | { script: string; }[] | ({ color: never[]; background?: undefined; } | { background: never[]; color?: undefined; })[] | { ...; }[] | { ...; }[] | { ...; }[] | { ...; }[])[]; handlers: { ...; }; }' is not assignable to type '{ container?: string | string[] | QuillToolbarConfig | Record<string, string | string[]>[] | undefined; handlers?: { [key: string]: any; } | undefined; }'.
        Types of property 'container' are incompatible.
          Type '(string[] | { font: never[]; }[] | { size: (string | boolean)[]; }[] | { customStyles: number[]; }[] | { script: string; }[] | ({ color: never[]; background?: undefined; } | { background: never[]; color?: undefined; })[] | { ...; }[] | { ...; }[] | { ...; }[] | { ...; }[])[]' is not assignable to type 'string | string[] | QuillToolbarConfig | Record<string, string | string[]>[] | undefined'.
            Type '(string[] | { font: never[]; }[] | { size: (string | boolean)[]; }[] | { customStyles: number[]; }[] | { script: string; }[] | ({ color: never[]; background?: undefined; } | { background: never[]; color?: undefined; })[] | { ...; }[] | { ...; }[] | { ...; }[] | { ...; }[])[]' is not assignable to type 'string[]'.
              Type 'string[] | { font: never[]; }[] | { size: (string | boolean)[]; }[] | { customStyles: number[]; }[] | { script: string; }[] | ({ color: never[]; background?: undefined; } | { background: never[]; color?: undefined; })[] | { ...; }[] | { ...; }[] | { ...; }[] | { ...; }[]' is not assignable to type 'string'.
                Type 'string[]' is not assignable to type 'string'. [plugin angular-compiler]
KillerCodeMonkey commented 2 months ago

for now i would just type your custom toolbar dropdown as any. i have to check, what typings are really allowed

KillerCodeMonkey commented 2 months ago

should be fixed in 26.0.7

feel free to reopen if it is not

anisabboud commented 2 months ago

Getting the following errors with ngx-quill 26.0.7 & Angular 18.2.0:

image

✘ [ERROR] TS2411: Property 'indent' of type 'string | undefined' is not assignable to 'string' index type 'string | number | boolean | (string | number | boolean)[]'. [plugin angular-compiler]

    node_modules/ngx-quill/config/quill-editor.interfaces.d.ts:13:4:
      13 │     indent?: string;
         ╵     ~~~~~~

✘ [ERROR] TS2411: Property 'list' of type 'string | undefined' is not assignable to 'string' index type 'string | number | boolean | (string | number | boolean)[]'. [plugin angular-compiler]

    node_modules/ngx-quill/config/quill-editor.interfaces.d.ts:14:4:
      14 │     list?: string;
         ╵     ~~~~

✘ [ERROR] TS2411: Property 'direction' of type 'string | undefined' is not assignable to 'string' index type 'string | number | boolean | (string | number | boolean)[]'. [plugin angular-compiler]

    node_modules/ngx-quill/config/quill-editor.interfaces.d.ts:15:4:
      15 │     direction?: string;
         ╵     ~~~~~~~~~

✘ [ERROR] TS2411: Property 'header' of type 'number | (number | boolean)[] | undefined' is not assignable to 'string' index type 'string | number | boolean | (string | number | boolean)[]'. [plugin angular-compiler]

    node_modules/ngx-quill/config/quill-editor.interfaces.d.ts:16:4:
      16 │     header?: number | Array<boolean | number>;
         ╵     ~~~~~~

✘ [ERROR] TS2411: Property 'color' of type 'string | string[] | undefined' is not assignable to 'string' index type 'string | number | boolean | (string | number | boolean)[]'. [plugin angular-compiler]

    node_modules/ngx-quill/config/quill-editor.interfaces.d.ts:17:4:
      17 │     color?: string[] | string;
         ╵     ~~~~~

✘ [ERROR] TS2411: Property 'background' of type 'string | string[] | undefined' is not assignable to 'string' index type 'string | number | boolean | (string | number | boolean)[]'. [plugin angular-compiler]

    node_modules/ngx-quill/config/quill-editor.interfaces.d.ts:18:4:
      18 │     background?: string[] | string;
         ╵     ~~~~~~~~~~

✘ [ERROR] TS2411: Property 'align' of type 'string | string[] | undefined' is not assignable to 'string' index type 'string | number | boolean | (string | number | boolean)[]'. [plugin angular-compiler]

    node_modules/ngx-quill/config/quill-editor.interfaces.d.ts:19:4:
      19 │     align?: string[] | string;
         ╵     ~~~~~

✘ [ERROR] TS2411: Property 'script' of type 'string | undefined' is not assignable to 'string' index type 'string | number | boolean | (string | number | boolean)[]'. [plugin angular-compiler]

    node_modules/ngx-quill/config/quill-editor.interfaces.d.ts:20:4:
      20 │     script?: string;
         ╵     ~~~~~~

✘ [ERROR] TS2411: Property 'font' of type 'string | string[] | undefined' is not assignable to 'string' index type 'string | number | boolean | (string | number | boolean)[]'. [plugin angular-compiler]

    node_modules/ngx-quill/config/quill-editor.interfaces.d.ts:21:4:
      21 │     font?: string[] | string;
         ╵     ~~~~

✘ [ERROR] TS2411: Property 'size' of type '(string | boolean)[] | undefined' is not assignable to 'string' index type 'string | number | boolean | (string | number | boolean)[]'. [plugin angular-compiler]

    node_modules/ngx-quill/config/quill-editor.interfaces.d.ts:22:4:
      22 │     size?: Array<boolean | string>;
         ╵     ~~~~
KillerCodeMonkey commented 2 months ago

do you get this with the demo repo as well?

KillerCodeMonkey commented 2 months ago

can you try 26.0.8 please?

justinbkay commented 2 months ago

26.0.7 is working for me and 26.0.8. 1 issue though. When I implement the handler, it is giving a typescript error.

TS2339: Property 'quill' does not exist on type '{ 'custom-dropdown': (value: string) => void; }'.

I'm working around this with //@ts-expect-error

'custom-dropdown': function (value: string) {
          if (value) {
            //@ts-expect-error
            const cursorPosition = this.quill.getSelection().index;
            //@ts-expect-error
            this.quill.insertText(cursorPosition, value);
            //@ts-expect-error
            this.quill.setSelection(cursorPosition + value.length); // Place cursor after inserted text
          }
},
KillerCodeMonkey commented 2 months ago

can you please share the whole config or component?

KillerCodeMonkey commented 2 months ago

btw. i guess i can not help you there, but it should work when you use this[quill].

quill exists in the context of the handler methods on this but the compiler does not know anything about it.

{
  toolbar: {
    container: [...],
    handlers: {
      'custom-dropdown': function (value: string) {
        const quill = this['quill']
        if (value && quill) {
          const cursorPosition = quill.getSelection().index;
          quill.insertText(cursorPosition, value);
          quill.setSelection(cursorPosition + value.length); // Place cursor after inserted text
        }
      }
    }
  }
}
justinbkay commented 2 months ago

That does work, but I still have to use //@ts-expect-error for the const quill = this['quill']; line.

KillerCodeMonkey commented 2 months ago

Stange, maybe it is a tsconfig setting. In my Demo repo it is not needed

Am 22. August 2024 17:16:19 MESZ schrieb Justin @.***>:

That does work, but I still have to use @.***for theconst quill = this['quill'];` line.

-- Reply to this email directly or view it on GitHub: https://github.com/KillerCodeMonkey/ngx-quill/issues/1918#issuecomment-2304958436 You are receiving this because you modified the open/close state.

Message ID: @.***>

anisabboud commented 2 months ago

can you try 26.0.8 please?

The errors I mentioned in node_modules/ngx-quill/config/quill-editor.interfaces.d.ts are gone in version 26.0.8. Thank you!