html,body {
margin: 0;
padding: 0;
height:100%;
}
#container {
height: 100%;
}
The container always takes 100% of the page size. When I resize the page, however, the monaco editor doesn't resize itself. I want the editor to resize itself so there will never be horizontal or vertical scroll bars. I have done similar things with ACE and CodeMirror. Is it possible with monaco-editor?
@tylerlong Yes, there is a creation option called automaticLayout:
/**
* Enable that the editor will install an interval to check if its container dom node size has changed.
* Enabling this might have a severe performance impact.
* Defaults to false.
*/
automaticLayout?:boolean;
Although convenient, I would personally not use this option as it is implemented by installing an interval that measures the container's size every 100ms. The reason is because the editor has no way of knowing what specifically in your app might cause its container to resize. In your case (when the container size is modified only by the window size), I would add a window.onresize listener and call editor.layout() inside that listener. That will cause the editor to rescan its container size. Even better, if you can somehow compute the size of the container, you can pass the size in to the editor.layout() method.
Although convenient, I would personally not use this option as it is implemented by installing an interval that measures the container's size every 100ms. The reason is because the editor has no way of knowing what specifically in your app might cause its container to resize.
Can we do something like:
$('#container').resize(function(){
editor.layout();
});
Ref: https://api.jquery.com/resize/
I think the code above should be inside this project instead of let users write it themselves.
Maybe it's a better idea to reimplement the automaticLayout?:boolean; option?
From https://api.jquery.com/resize/ I understand that it is a wrapper for the resize event.
From https://www.w3.org/TR/DOM-Level-3-Events/#event-type-resize I understand that the resize event is emitted when the window resizes (not when the element resizes).
I have validated my understanding using the following test page: https://jsfiddle.net/du0d9v9g/1/
$('#element').resize(function(){
console.log('element resized');
alert('element resized!');
});
setTimeout(function() {
// resizing the element
document.getElementById('element').style.width = '200px';
}, 2000);
That is why automaticLayout scans for the size of the container. The size of the container might be changed by the embedder of the editor due to a number of reasons, only one of them being window.onresize. That is what I mean in my above comment:
The reason is because the editor has no way of knowing what specifically in your app might cause its container to resize. In your case (when the container size is modified only by the window size), I would add a window.onresize listener and call editor.layout() inside that listener. That will cause the editor to rescan its container size. Even better, if you can somehow compute the size of the container, you can pass the size in to the editor.layout() method.
I am open to change the implementation of automaticLayout if we find a JS event that tells us when an element has changed its size.
Made some example using transitionend event, works in all major browsers:
https://github.com/nikikante/ResizableElement
demo: https://rawgit.com/nikikante/ResizableElement/master/index.html
Additional testing: Works only on fixed width. Not working with width 100%;
I see there is a commit that referenced this issue on Aug 19. So is this fixed or not?
The automaticlayout option is the only one mentioned here that really worked for me. I'm using the Monaco editor inside a golden-layout module, and everything i tried (including ResizableElement mentioned above) failed. So thank you very much for this option.
This worked for me:
updateDimensions() {
this.editor.layout();
}
componentDidMount() {
window.addEventListener("resize", this.updateDimensions.bind(this));
}
componentWillUnmount() {
window.removeEventListener("resize", this.updateDimensions.bind(this));
}
@zdne GOAT
I'm not sure what else there is to do on our side, so I'm opting to close this issue.
The host of the editor can call editor.layout() when the container size has changed.
If the host of the editor does not want to call editor.layout(), then there is the option automaticLayout (implemented via setInterval that constantly probes for the container's size).
listening resize event on window is better than a interval every 100ms , if it is not too frequently
Just in case anyone happens across this issue and sees the snippet posted by @zdne, I wanted to point out that it has a bug. bind creates and returns a new function on each call, so the result of this...
componentDidMount() {
window.addEventListener("resize", this.updateDimensions.bind(this));
}
componentWillUnmount() {
window.removeEventListener("resize", this.updateDimensions.bind(this));
}
...is that a new function is created and added as a resize listener in componentDidMount, and then _another_ new (_different_) function is created and "removed" (scare-quotes because it was never actually added in the first place) as a resize listener in componentWillMount. What this means is that the listener that was added in componentDidMount is never actually removed, which could result in errors and/or memory leaks. A workaround is to store a reference to the bound function the first time it is created, and then add and remove that same one (using the reference) in the respective methods.
just in case, my needs are different: I want the user to resize it the container - in a standard way and cheap (both on code and peformance) on libraries and performance. This is what I did:
css container : resize: vertical; overflow: auto
and this js :
function installResizeWatcher(el, fn, interval){
let offset = {width: el.offsetWidth, height: el.offsetHeight}
setInterval(()=>{
let newOffset = {width: el.offsetWidth, height: el.offsetHeight}
if(offset.height!=newOffset.height||offset.width!=newOffset.width){
offset = newOffset
fn()
}
}, interval)
}
const typeScriptCodeContainer = document.getElementById('typeScriptCodeContainer')
typeScriptCodeEditor = monaco.editor.create(typeScriptCodeContainer, Object.assign(editorOptions, {value: example.codeValue}))
installResizeWatcher(typeScriptCodeContainer, typeScriptCodeEditor.layout.bind(typeScriptCodeEditor), 2000)
yes, 2 seconds interval and make sure it registers only once. I see there is / was a resize interval on 100ms for the automatic relayout in monaco - IMHO that's too much.
See it in action: https://typescript-api-playground.glitch.me/?example=2
为什么不侦听window.onresize,而是要setInterval ?
[o] window.onresize = installResizeWatcher[x] setInterval(
installResizeWatcher, ###0 )
Sebastián Gurin notifications@github.com 于2018年6月22日周五 上午3:44写道:
in my case my needs are different: I want the user to resize it the
container - in a standard way and cheap (both on code and peformance) on
libraries and performance. This is what I did:css container : resize: vertical; overflow: auto
and this js :
function installResizeWatcher(el, fn, interval){
let offset = {width: el.offsetWidth, height: el.offsetHeight}
setInterval(()=>{
let newOffset = {width: el.offsetWidth, height: el.offsetHeight}
if(offset.height!=newOffset.height||offset.width!=newOffset.width){
offset = newOffset
fn()
}
}, interval)
}
const typeScriptCodeContainer = document.getElementById('typeScriptCodeContainer')
typeScriptCodeEditor = monaco.editor.create(typeScriptCodeContainer, Object.assign(editorOptions, {value: example.codeValue}))
installResizeWatcher(typeScriptCodeContainer, typeScriptCodeEditor.layout, 2000)yes, 2 seconds interval and make sure it registers only once. I see there
is / was a resize interval on 100ms for the automatic relayout in monaco -
IMHO that's too much.—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/Microsoft/monaco-editor/issues/28#issuecomment-399204447,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AhaCeDd_efQc5w2ydm6YCN0YTCWiUYHmks5t--l5gaJpZM4I-QpD
.
automaticLayout doesn't work when using css grid and reducing window size as ace-editor "fixes" it's height so grid layout engine assumes it cannot reduce it's size
@ alexandrudima There is a js event for element resize now. Check the links. First one would do the job.
https://developers.google.com/web/updates/2016/10/resizeobserver
https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
Hi,
get the same problem here and solved it with this :
react-resize-detector
@atilkan it's based on resizeobserver
Take care to the browser compatibility (I don't care in my project and don't have test it on any other brother than Chrome)
My editor 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;
New to react this code could be better, but hope this help someone.
@ alexandrudima There is a js event for element resize now. Check the links. First one would do the job.
https://developers.google.com/web/updates/2016/10/resizeobserver
https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
@alexandrudima so you would be open to a PR that implements automaticLayout using ResizeObserver?
Most helpful comment
@tylerlong Yes, there is a creation option called
automaticLayout:Although convenient, I would personally not use this option as it is implemented by installing an interval that measures the container's size every 100ms. The reason is because the editor has no way of knowing what specifically in your app might cause its container to resize. In your case (when the container size is modified only by the window size), I would add a
window.onresizelistener and calleditor.layout()inside that listener. That will cause the editor to rescan its container size. Even better, if you can somehow compute the size of the container, you can pass the size in to theeditor.layout()method.