Monaco-editor: Auto resizing with content size

Created on 10 Aug 2016  路  16Comments  路  Source: microsoft/monaco-editor

I need to show a complete model in the editor without vertical scrolling. I can achieve it by listening to content changes of a model and calling layout with a recomputed height as lineCount * lineHeight. I wonder is the more elegant way to achieve it?

editor-core feature-request

Most helpful comment

At this point, that is the only way. Would be nice to have an autoSize: true|false flag that would do that for you

All 16 comments

you can editor.getScrollHeight(), then set the height of the container (used in the create call) and then editor.layout();

At this point, that is the only way. Would be nice to have an autoSize: true|false flag that would do that for you

I noticed the following issues with auto resizing, disabled scrolling and scrollBeyondLastLine as false:

  • focusing for last line is broken, one can focus only by clicking on the top of line, with one line it gets really annoying;
  • if a editor height is greater than a content height than clicking on the part below content does not focus on the content, would be nice if it focus on the last line.

@akosyakov I'm thinking the mouse hits the horizontal scrollbar. Would you expect the content to have an extra 7px or the height of the horizontal scrollbar to avoid this?

@alexandrudima will try now

@alexandrudima you are right, i've adjusted the formula to add horizontalScrollbarHeight and it looks better. I would expect that it happens automatically if autoSize set to true.

also it would be nice to provide minHeightInLines, so in spite of a content is empty, an editor height can be for example 1.5*lineHeight

Another issue: Page scrolling does not work with auto resize and disabled scrolling.
Steps to reproduce: disable scrolling try to scroll a page down when a mouse is over an editor.

Filed a separate issue for it: https://github.com/Microsoft/monaco-editor/issues/116

@akosyakov I got this working when I add content to the model however, when I delete lines, the container will never shrink. Were you able to work around that?

@jws305 Yes, it works. Could it be that you did not hook it up at right places? We do autoresize whenever an editor configuration, an editor model or a model value changed.

The code that computes a height is here: https://github.com/R-Brain/jupyterlab/blob/master/src/monaco/editor.ts#L470. You can ignore boxSizing.

@akosyakov Thanks! That works much better than what I had come up with:

this.$element.height(0);
this.editor.layout();
let height = this.editor.getScrollHeight();
this.$element.height(height + 7);
this.editor.layout();

@akosyakov That code doesn't seem to exist anymore.
Care to share the original code?

Tnx!

Cool, thanks!
I tried to accomplish the exact same thing, but I couldn't find the line height in the layoutinfo.
Never thought to check the editor interface.

Thanks!

Some additional comments:

I believe that the performant way is to calculate the height using @akosyakov's approach:

let lastResizedLineCount = 0;
model.onDidChangeContent(() => {
    let lineCount = model.getLineCount();
    // Do not invalidate layout if the line count hasn't changed, as this method
    // will be called for every keypress and layouts are too expensive.
    if (lineCount == lastResizedLineCount) {
        return;
    }
    lastResizedLineCount = lineCount;

    const configuration = editor.getConfiguration();
    const lineHeight = configuration.lineHeight;
    const contentHeight = lineHeight * lineCount;

    const horizontalScrollbarHeight = configuration.layoutInfo.horizontalScrollbarHeight;
    const height = contentHeight + horizontalScrollbarHeight;

    editorElement.style.height = `${height}px`;
    editor.layout({
      height,
      width: this.getElement().clientWidth,
    });
});

But this doesn't work with line-wrapping because the line count is dependent on the length of individual lines.

For that, I believe you have to use the line count from the ViewModel:

const lineCount = editor._modelData.viewModel.getLineCount()

Would really like to know if there's a better way which doesn't use the private _modelData member.

Let's track in #794 , which even though is a younger issue, has more upvotes.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

spahnke picture spahnke  路  26Comments

AchimKO picture AchimKO  路  20Comments

jayspadie picture jayspadie  路  16Comments

ascoders picture ascoders  路  22Comments

tylerlong picture tylerlong  路  17Comments