tinymce / tinymce-angular

Official TinyMCE Angular Component
MIT License
320 stars 93 forks source link

Various script errors when loading tinymce inside a dynamic modal component #235

Closed solomon23 closed 2 years ago

solomon23 commented 3 years ago

What is the current behavior?

This is super busted for me and I'm not sure what's going on. it works fine if I just inject it into the page, but I have a component modal I need to attach it to that dynamically pops open and once I do that it blows up with

image

Which is code here to try to load the page's stylesheets but comes back undefined and blows up on length

        }, d = function() {
                var e;
                e = d,
                function() {
                    for (var e = m.styleSheets, t = e.length; t--; ) {
                        var n = e[t].ownerNode;
                        if (n && n.id === r.id)
                            return l(),
                            1
                    }
                }() || (Date.now() - u < b ? Wr.setTimeout(e) : f())

then if i close and re-open the modal i get this error

image

which goes into here somewhere

image

I tried the dev version and that just gives me other script errors.

It doesn't matter how I make the editor but this is what I'm trying to use

<editor
    apiKey="key"
    [init]="{
    height: 500,
    menubar: false,
    plugins: 'mentions lists paste help wordcount',
    outputFormat: 'html',
    toolbar:
      'undo redo | formatselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | removeformat '
  }"
  ></editor>

I tried using the cloud version and using it locally with the same results

Can you not dynamically load a component that contains the tinymce editor ?

Please provide the steps to reproduce and if possible a minimal demo of the problem via codesandbox.io or similar.

What is the expected behavior?

Which versions of TinyMCE/TinyMCE-Angular, and which browser / OS are affected by this issue? Did this work in previous versions of TinyMCE or TinyMCE-Angular?

exalate-issue-sync[bot] commented 3 years ago

Ref: INT-2529

jscasca commented 3 years ago

Any chance you can build a small replication of how you are creating the component? A sandbox replication helps us a lot when trying to reproduce the issue you are having

solomon23 commented 3 years ago

Ok i got it to repro here https://codesandbox.io/s/romantic-bird-iynl5?file=/src/app/editor.component.ts

What's blowing it up is when the component with the content projection ngIf hides it until the timeout is ready. Even if you remove the timeout and leave it to ngIf false - it'll blow up with the open script error. Doing it this way you'll see both of them if you click the button twice

jscasca commented 3 years ago

Sorry for the delay but is the modal component file supposed to be empty? I can't get the sandbox working

jscasca commented 3 years ago

Nvm that, got it working. Let me dig into this a bit more

jscasca commented 3 years ago

Oh, so you are trying to use content-projection.

So the bad news is that the wrapper doesn't work well with content projection. We do have a workaround in our sotrybook examples using template outlets: https://github.com/tinymce/tinymce-angular/blob/main/stories/contentprojection/ContentProjection.component.ts

Here you can see the working exmpale

ricardosobrado commented 3 years ago

Hello! I tried to use this workaround and I manage to load the editor but the toolbar icons are not shown. Below is the code related with the editor. Can someone please give me some idea why this is happening?

2021-06-21_11h28_22

this is my code: Template:

<div>
   ...
<ng-container [ngTemplateOutlet]="showEditor ? editorTemplate : placeHolder" [ngTemplateOutletContext]="{ $implicit: editorInitialization }"> </ng-container>
</div>

<ng-template #placeHolder>
  <p>I am a placeholder.</p>
</ng-template>

<ng-template #editorTemplate let-editorInitalization>
  <editor
      apiKey="xxxxxxx"
      [init]=editorInitialization>
  </editor>
</ng-template>

Component:

  showEditor = true;
  editorInitialization: any;

  this.editorInitialization = {
        base_url: '/tinymce',
        branding: false,
        suffix: '.min',
        height: 200,
        menubar: true,
        dialog_type : 'modal',
        plugins: [
          'advlist autolink lists link image charmap print preview anchor',
          'searchreplace visualblocks code fullscreen',
          'insertdatetime media table paste code help wordcount'
        ],
        toolbar:
          'undo redo | formatselect | bold italic backcolor | \
          alignleft aligncenter alignright alignjustify | \
          bullist numlist outdent indent | removeformat | help'
    };
ricardosobrado commented 3 years ago

I found a workaround to make tinyMce working with modals.

Template:

<div>
    <editor *ngIf="showEditor"  [init]="tinyMceConfig"> 
    </editor>
</div> 

Component:

ngAfterViewInit() {
this.ngxSmartModalService.getModal(ComponentsIds.stringEditorModalComponent)
  .onOpen.subscribe((modal: NgxSmartModalComponent) => {
      this.showEditor = false;

      setTimeout(() => {
        this.configureTinyMce();
        this.showEditor = true;
      });

  });
}

configureTinyMce() {
    this.tinyMceConfig = {
          base_url: '/tinymce',
          suffix: '.min',
          menubar: false,
          branding: false,
          /**
           * This is needed to prevent console errors
           * if you're hosting your own TinyMCE
           */
          content_css: '/tinymce/skins/ui/oxide/content.min.css',
          height: 200,
          image_advtab: true,
          imagetools_toolbar: `
            rotateleft rotateright |
            flipv fliph |
            editimage imageoptions`,
          importcss_append: !0,
          inline: false,
          dialog_type : 'modal',
          paste_data_images: !0,
          // /**
          //  * This is needed to prevent console errors
          //  * if you're hosting your own TinyMCE
          //  */
          skin_url: '/tinymce/skins/ui/oxide',
          toolbar: `
            insertText |
            copy undo redo formatselect |
            bold italic strikethrough forecolor backcolor |
            link | alignleft aligncenter alignright alignjustify |
            numlist bullist outdent indent |
            removeformat`,
          setup: (editor) => {
            editor.ui.registry.addButton('insertText', {
              text: 'Press Me To Insert Text!',
              onAction: () => {
                editor.insertContent('<strong>Hello World!</strong>');
              }
            });
          }
      };
  }

The trick consists in set

this.showEditor = false;

followed by

setTimeout(() => {
        this.configureTinyMce();
        this.showEditor = true;
      });

everytime the modal is called. Hope this can help someone! :)