Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ngx-monaco-editor - unable to set layout size when container changes (using tab panel)

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.

like image 490
mindparse Avatar asked May 24 '16 12:05

mindparse


3 Answers

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>
like image 147
Akash Avatar answered Nov 02 '22 08:11

Akash


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.

like image 37
Amirhossein Mehrvarzi Avatar answered Nov 02 '22 07:11

Amirhossein Mehrvarzi


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.

like image 1
Jeff Wilkerson Avatar answered Nov 02 '22 08:11

Jeff Wilkerson