23

I've just started investigating Monaco to be used as the editor for our internal code playground. And I'm unable to figure out how to create a handler for whenever the text in the editor window is changed, either by typing, pasting, or deleting. For context, using the CodeMirror editor, I simply did:

editor.on('change', function(editor, change) {
    render();
});

Here is my JavaScript that creates the basic editor:

    require.config({ paths: { 'vs': '../node_modules/monaco-editor/min/vs' }});
require(['vs/editor/editor.main'], function() 
{
    window.editor = monaco.editor.create(document.getElementById('editor'),                 
    {
        value: [
            'var canvas = document.getElementById("playground");',
            'var ctx = canvas.getContext("2d");',
            'ctx.fillStyle = "#FF00FF";',
            'ctx.fillRect(0,0,150,75);',
        ].join('\n'),
        language: 'javascript'
    });
});

Thanks!

elora
  • 451
  • 1
  • 3
  • 14

4 Answers4

29

I found onDidChangeContent method the other day.

In your example you would attach the listener like this:

window.editor.getModel().onDidChangeContent((event) => {
  render();
});
Asalan
  • 85
  • 2
  • 11
Gil
  • 451
  • 3
  • 8
  • 1
    Thanks! I had finally found onDidChangeContentModel which worked. onDidChangeContent itself didn't work in my case. – elora Feb 16 '18 at 15:36
  • 1
    The difference is that one is a method of the editor and one of a model. Note in my example that the method is called on window.editor.model – Gil Feb 16 '18 at 20:08
  • 8
    This is outdated with the last version, now it works with `editor.getModel().onDidChangeContent` – dv1729 May 16 '19 at 21:52
  • @dv1729 solution didn't work for me directly, but changing it to `editor.getModels()[0].onDidChangeContent` did work – Shan Eapen Koshy Jun 15 '21 at 09:50
23

To expand on Gil's answer, there are two different methods, onDidChangeContent and onDidChangeModelContent.

  • onDidChangeContent is attached to a model, and will only apply to that model
  • onDidChangeModelContent is attached to the editor and will apply to all models

The nice thing is that you can use different onDidChangeContent listeners on multiple models, switch them out with one another, and they'll all preserve their own onChange events. For example, you might have an editor with different models for HTML, CSS, and JS. If you wanted different onChange listeners for each of those, this is easily achievable. At the same time, you can have listeners using onDidChangeModelContent that will apply to all models.

To update his answer, as of the current release (0.15.6), the syntax editor.model doesn't work. You have to use editor.getModel().

Daniel Loureiro
  • 4,595
  • 34
  • 48
Benny Hinrichs
  • 1,393
  • 9
  • 17
  • 2
    It is [`onDidChangeModelContent`](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.icodeeditor.html#ondidchangemodelcontent), not `onDidChangeContentModel` – Markus Weninger Apr 13 '21 at 09:57
  • 1
    @MarkusWeninger I thought I was doing something wrong until I saw your comment. I have edited the answer and fixed the typo. – Daniel Loureiro Jun 27 '21 at 02:24
  • I'd like to point out it wasn't a typo. It was correct for the version from Jan 2019, but since Monaco hasn't had a 1.0 release, they can change the API at any time. – Benny Hinrichs Jun 28 '21 at 18:05
15

After a lot of poking and experimenting, I did find something. I haven't figured out the difference between creating an editor and creating an editor using a model (not that I've looked), but the following works for me:

var monEditor;
require.config({ paths: { 'vs': '../node_modules/monaco-editor/min/vs' }});
require(['vs/editor/editor.main'], function() 
{
    monEditor = monaco.editor.create(document.getElementById('editor'),                 
    {
        value: [
            'var canvas = document.getElementById("playground");',
            'var ctx = canvas.getContext("2d");',
            'ctx.fillStyle = "#FF00FF";',
            'ctx.fillRect(0,0,150,75);',
        ].join('\n'),
        language: 'javascript'
    });
    monEditor.onDidChangeModelContent(function (e) {
        render();
    });
});

Using just onDidChangeContent did not work for me.

elora
  • 451
  • 1
  • 3
  • 14
1

So, anyone looking for a guide on Monaco-editor can refer to this official document. Monaco Editor API

Himanshu Shekhar
  • 1,196
  • 1
  • 16
  • 35