Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Monaco editor dynamically resizable

I have been searching for a discussion about if it's possible to mimic the html tag textarea's resizing when using Monaco Editor's field all over the Internet but I couldn't find one answering my question.

I'm using the monaco-editor npm package in a React application. Do you have any idea if this is easy to implement?

Thank you in advance!

SOLUTION
With pure css I selected the target html element and just added these properties:

div {
  resize: vertical;
  overflow: auto;
}
like image 328
elenaHristova Avatar asked Oct 30 '17 14:10

elenaHristova


3 Answers

TL;DR: add automaticLayout: true to your editor's configuration.

NL;PR:

Monaco has a built-in auto resize to parent container functionality:

    createEditorWithAutoResize(){
      this.editor = monaco.editor.create(
            this.editorDiv.current, {
            value: "var x = 0;",
            language: 'javascript',
            automaticLayout: true // <<== the important part
       }
      );
    }
    componentDidMount(){this.createEditorWithAutoResize();}
    constructor(props){super(props); this.editorDiv = React.createRef();}
    render(){return <div ref={this.editorDiv} className="editor" ></div>}

And the CSS for the editor (it avoids rendering the editor for the first time with like 10px height):

    .editor{
     height: 100%;
    } 

First tested: v0.10.1, Last tested: v0.32.1

Note: < v0.20.0: The mechanism does not listen to its container size changes, it polls them.

@nrayburn-tech (Monaco Editor's contributor): Version 0.20 uses MutationObserver for all browsers. Version 0.21 and later uses ResizeObserver on supported browsers, otherwise, it uses polling as a fallback.

like image 65
David I. Samudio Avatar answered Oct 23 '22 13:10

David I. Samudio


if you have a reference to the editor you can just call editor.layout() on some resize event. For example, on window resize:

window.onresize = function (){
    editor.layout();
};
like image 15
SimperT Avatar answered Oct 23 '22 12:10

SimperT


this is old question but get the problem to and solved it with react-resize-detector

based on ResizeObserver it feet perfectly to the need (check browser compatibility)

Exemple of component :

import React, { Component } from 'react';
import ReactResizeDetector from 'react-resize-detector';
import * as monaco from 'monaco-editor';

class Editor extends Component {
    constructor(props) {
        super(props)

        this.state = {
            width: 0,
            height: 0,
        }
        this.editor_div = React.createRef()

        this.handle_rezise = this.handle_rezise.bind(this);
    }

    componentDidMount() {
        const editor_model = monaco.editor.createModel('', 'sql');
        this.monaco_editor = monaco.editor.create(this.editor_div.current, this.props.editorOptions);
        this.monaco_editor.setModel(editor_model);
    }

    componentWillUnmount() {
        this.monaco_editor && this.monaco_editor.dispose();
    }

    handle_rezise(width, height) {
        this.monaco_editor.layout({ height, width });
    }

    render() {
        return(
            <div 
                className="editor-container"
                style={{ height: '100%' }}>
                <ReactResizeDetector
                    handleWidth
                    handleHeight
                    onResize={ this.handle_rezise }
                    refreshMode="debounce"
                    refreshRate={100} />
                <div 
                    className="editor"
                    ref={ this.editor_div }
                    style={{ height: '100%' }} />
            </div>
        )
    }
}

export default Editor;

Hope it's help

like image 3
Naej56 Avatar answered Oct 23 '22 13:10

Naej56