5

I am struggling with an instance of an ngx-monaco-editor inside a primeng tab panel which seems to loses its size calculations when switching to another tab, changing the model value bound to the editor and then switching back to the initial tab again.

https://stackblitz.com/edit/primeng9-tabs-monaco-editor

Steps to replicate using URL above:

  • The 'Editor' tab will be initially selected
  • Select 'Tab 2'
  • Click the 'change code' button
  • Change back to the 'Editor' tab and now see that the editor has shrunk in size

Before:

enter image description here

After:

enter image description here

Inspecting in the Dom, the originally assigned style is still present.

As you can see from the source code in my sample app, I also tried using the editor's layout method in the tab change event to attempt to force a recalculation of the size based on the container but this has made no difference

Interestingly if I resize the window this does seem to trigger the editor component to resize again correctly.

Amirhossein Mehrvarzi
  • 18,024
  • 7
  • 45
  • 70
mindparse
  • 6,115
  • 27
  • 90
  • 191

3 Answers3

9

Not sure what the root cause is but using *ngIf on the editor container fixes the problem. Please take a look at this -

handleTabChange(tabChangeEvent: { originalEvent: Event; index: number }) {
    if (tabChangeEvent.index === 0) {
      //this.monacoEditor.editor.layout();
      this.showEditor = true;
    } else {
      this.showEditor = false;
    }
  }

Then in your template -

<div style="height: 500px" *ngIf="showEditor">
            <ngx-monaco-editor #monacoEditor style="height:100%;" [options]="editorOptions" [(ngModel)]="code">
            </ngx-monaco-editor>
        </div>
Akash
  • 4,412
  • 4
  • 30
  • 48
2

First of all, note that the issue is not related to angular component. This is all about Monaco editor.

How Monaco finds its actual layout?

Consider a page with a visible Monaco editor inside a container. When Monaco editor is loaded, it sets the layout size according to visible view. So what happens if you request an update on Monaco when is inside a hidden container? Obviously, there's no visible view for Monaco to set its layout props. The editor sets layout according to hidden view! This is why you see a dot instead of area. Now when this view comes to visible state, the editor doesn't update the layout even by calling .layout() method or setting automaticLayout: true in options. You may trigger by resizing the browser, updating editor again or some Angular tricks.

Now you understand how it works. So please avoid updating Monaco when is inside an invisible view. Let this to be done after containing view become visible.

Amirhossein Mehrvarzi
  • 18,024
  • 7
  • 45
  • 70
2

Using *ngIf will initialize / destroy the ngx-monaco-editor component, which may or may not be helpful.

When I have a component containing a ngx-monaco-editor, I create the following function that I call whenever I need to resize the monaco editor.

    resizeComponents() {
        setTimeout(() => {
            window.dispatchEvent(new Event('resize'));
        }, 200);
    }

EXAMPLE OF USE:

View

<div (click)="onTabChange('myTab')">Change Tab</div>

Component

onTabChange(myTab) {
   
    // execute tab change logic
    this.resizeComponents()
}

Again, this is an alternative approach in case you don't want to re-initialize the editor.

Jeff Wilkerson
  • 376
  • 2
  • 18