microsoft / monaco-editor

A browser based code editor
https://microsoft.github.io/monaco-editor/
MIT License
40.23k stars 3.58k forks source link

Is there an initialized or ready event? #115

Open dezsiszabi opened 8 years ago

dezsiszabi commented 8 years ago

Hello,

I'm curious if there's an initialized or ready event or something I can listen to when instantiating an editor?

Would be useful in the below case for example:

<script>
    require.config({ paths: { "vs": "node_modules/monaco-editor/min/vs" } });
    require(["vs/editor/editor.main"], function() {
        monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
            validate: false,
            allowComments: false
        });

        var editor = monaco.editor.create(document.getElementById("container"), {
            value: '{ "prop": "Hello world" }',
            language: "json",
            theme: "vs-dark",
            contextmenu: false,
            quickSuggestions: false,
            automaticLayout: true
        });

        editor.getAction("editor.action.format").run();
    });
</script>

Here the line editor.getAction("editor.action.format").run(); doesn't have any effect. The JSON doesn't get formatted and I assume it's because the editor is not fully initialized at that point.

I know I can solve it with setTimeout, but I was wondering if there's any other option.

Thanks in advance, keep up the good work :)

UPDATE:

Adding the below solves it, not the most beautiful solution though :)

var didScrollChangeDisposable = editor.onDidScrollChange(function(event) {
    didScrollChangeDisposable.dispose();
    editor.getAction("editor.action.format").run();
});
alexdima commented 8 years ago

Perhaps we could expose the language registries (https://github.com/Microsoft/vscode/blob/66c13c81fd8d844fa2cba38e03bd719e285a1c7e/src/vs/editor/common/modes.ts#L1026), they fire events when language providers are attached.

fdeitelhoff commented 8 years ago

Hi,

first, many thanks to @dezsiszabi for pointing out one (dirty) solution. It helped me with my approach to automatically trigger a AngularJS function after the monaco editor is fully loaded and displaying some code. Works fine.

I think there should be some "ready" events when the editor is up and running. Or are they already here and I'm missing something out?

AndersMad commented 7 years ago

I'd like to up-vote on this one.. I ended up sing the onDidScrollChange too with a checker on if (!(editor.getModel() as any)._tokenizationSupport) return; (and then a this.didInit check)... awful code - but that works.. But before that one is hit, I also do a require(["vs/editor/common/modes/languageConfigurationRegistry"], (mod: any) => { this._disposables.push(mod.LanguageConfigurationRegistry.onDidChange(() => { ... to modify loaded language :-S

The reason above is that, when language HTML has been async loaded, I do a extend of that (e.g. showing written css colors as colors in html styles and css blocks etc.) so it end up being an unknown/random race to what has been loaded and initialised.

Thanks

jesusvimlet commented 6 years ago

I have the same struggle too. Thanks for show me a solution but I like to bump this requested feature. onReady event would be nice.

DevidCIC commented 6 years ago

OnReady or onLoaded Event would be better.

CoderPoet commented 6 years ago

@dezsiszabi hello~ why I can not use the action 'editor.action.format'.The action is not exist . image image

CoderPoet commented 6 years ago

@dezsiszabi this is supported actions image

tsy77 commented 5 years ago

@dezsiszabi hello~ why I can not use the action 'editor.action.format'.The action is not exist . image image

maybe 'editor.action.formatDocument' is work

tsy77 commented 5 years ago

Perhaps we could expose the language registries (https://github.com/Microsoft/vscode/blob/66c13c81fd8d844fa2cba38e03bd719e285a1c7e/src/vs/editor/common/modes.ts#L1026), they fire events when language providers are attached.

has this event been added? It's really needed because onDidScrollChange will be fired before language providers are attached.

sunzhengxin92 commented 5 years ago

@dezsiszabi this is supported actions image

How can I print the event Lists?

0xAnon101 commented 4 years ago

@sunzhengxin92 window.codeEditor._actions

wangdingwei commented 3 years ago

onDidScrollChange not working in the newest version

lb1129 commented 3 years ago

Is there any progress?

lb1129 commented 3 years ago

Hello,

I'm curious if there's an initialized or ready event or something I can listen to when instantiating an editor?

Would be useful in the below case for example:

<script>
    require.config({ paths: { "vs": "node_modules/monaco-editor/min/vs" } });
    require(["vs/editor/editor.main"], function() {
        monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
            validate: false,
            allowComments: false
        });

        var editor = monaco.editor.create(document.getElementById("container"), {
            value: '{ "prop": "Hello world" }',
            language: "json",
            theme: "vs-dark",
            contextmenu: false,
            quickSuggestions: false,
            automaticLayout: true
        });

        editor.getAction("editor.action.format").run();
    });
</script>

Here the line editor.getAction("editor.action.format").run(); doesn't have any effect. The JSON doesn't get formatted and I assume it's because the editor is not fully initialized at that point.

I know I can solve it with setTimeout, but I was wondering if there's any other option.

Thanks in advance, keep up the good work :)

UPDATE:

Adding the below solves it, not the most beautiful solution though :)

var didScrollChangeDisposable = editor.onDidScrollChange(function(event) {
    didScrollChangeDisposable.dispose();
    editor.getAction("editor.action.format").run();
});

it's not work when codestring is short

sekedus commented 2 years ago

use onDidCreateEditor

  monaco.editor.onDidCreateEditor(function(event) {
    console.log('editor created');
  });

  var editor = monaco.editor.create(document.getElementById("container"), {
    value: '{ "prop": "Hello world" }',
    language: "json",
    theme: "vs-dark",
    contextmenu: false,
    quickSuggestions: false,
    automaticLayout: true
  });
ankurpiparsania commented 2 years ago

if someone needs to really check, if model has been loaded, one may use mutation observer. You should only look for childList of the container, where you loaded monaco editor to keep costs of mutation observing to minimum;

let observer = new MutationObserver((mutations, o) => {

            if (Array.from(mutations).some(mutation => {
                return Array.from(mutation.addedNodes).some(node => node.classList.contains('monaco-editor'));
            })) 
           {
                console.log('editor loaded');

            }
        }).observe(container, { childList: true, })
github-username-number-2 commented 2 years ago

I am trying to add a keydown event listener to the editor, and when using the above 2, the event listener is gone when the editor is fully loaded.

magicds commented 2 years ago

6 years later, has an initialized or ready event supported?

zSp33dy commented 2 years ago

6 years later, has an initialized or ready event supported?

still waiting

enmotion commented 1 year ago

try this hook

Instance.onDidLayoutChange((event:any)=>{
      // console.log('onDidLayoutChange')
      if(MEInstance){
        MEInstance.trigger(
          "anyString",
          "editor.action.formatDocument",
          null
        ); // format code
      }
 })
farskid commented 1 year ago

@alexdima I want to help push this feature forward. Any pointers as to where to start contributing?

mhsattarian commented 1 year ago

I have this monaco editor which gets mounted and unmounted by the user. this is how I could do this:

function formatDocument() {
  editor.getAction('editor.action.formatDocument').run();
}

/// on first initialization
editor.onDidChangeModelLanguageConfiguration(formatDocument);

/// on every initialization
editor.onDidLayoutChange(formatDocument);
Ankit1996-tech commented 1 year ago

@dezsiszabi hello~ why I can not use the action 'editor.action.format'.The action is not exist . image image

const handleEditorDidMount = (editor: any,monaco:any) => { setTimeout( () => editor.getAction('editor.action.formatDocument').run(), 100, ); };

I've used it like this. It worked for json.

imguolao commented 1 year ago

6 years later, has an initialized or ready event supported?

still waiting

Now it's seven years.

Cobular commented 1 year ago

My 2 cents: use retry with exponential backoff, something like this:

export async function promiseRetry<T>(
  promise: () => Promise<T>,
  initial_retry_count: number,
  retry_delay: number,
): Promise<T> {
  async function __promiseRetry(promise: () => Promise<T>, remaining_retry_count: number): Promise<T> {
    try {
      const res = await promise();
      return res;
    } catch (e) {
      if (remaining_retry_count <= 0) {
        throw e;
      }
      setTimeout(() => {
        __promiseRetry(promise, remaining_retry_count - 1);
      }, retry_delay ** (1 + 0.1 * (initial_retry_count - remaining_retry_count + 1)));
    }
  }

  return __promiseRetry(promise, initial_retry_count);
}

Then, when you want to get a worker ref (or anything else that requires it to be loaded):

// So.. there is no way to check when the model is initalized apparently!
// https://github.com/microsoft/monaco-editor/issues/115

// If we accidentally call the `getTypeScriptWorker()` function to early, it throws.
//  Just use retry with exponential backoff to get it!
await promiseRetry(
  async () => {
    const getWorker = await monaco.languages.typescript.getTypeScriptWorker();
    const tsWorker = await getWorker();
    dispatch('fullyLoaded', { model: editor.getModel(), worker: tsWorker });
  },
  5,
  10,
);
OlegGedzjuns commented 6 months ago

6 years later, has an initialized or ready event supported?

still waiting

Now it's seven years.

Happy to celebrate 8 years here 🎉

subhendupsingh commented 5 months ago

is there a workaround for this? All the methods mentioned above don't seem to work.

nehaalrejam commented 5 months ago

Is there a recommended fix for this? Even for me, the given solutions are not working

Update: @mhsattarian's solution works for me!

subhendupsingh commented 5 months ago

Couldn't find a solution, went ahead with the setTimeout hack, working fine as of now.

nikita-fuchs commented 4 months ago

8 years later, here is a solution for everyone who uses the Angular package https://www.npmjs.com/package/ngx-monaco-editor-v2 or the deprecated predecessor, https://www.npmjs.com/package/ngx-monaco-editor

<ngx-monaco-editor 
                [(ngModel)]="code" 
                class="editor leftEditor"     
                [options]="editorOptions"
                (onInit)="initializeEditorObject($event)">

            </ngx-monaco-editor>

there is an (onInit) event, the reference to the Editor object will be contained in there as $event parameter. So in my code, I do

initializeEditorObject = (theEditor: monaco.editor.IStandaloneCodeEditor) => {
  this.editor = theEditor;
  //nice, the editor is initialised !
  this.updateEditorHeight();
} 

Usually these packages use standard stuff under their hood, so just take a look at the source code ! :)

andrew-pidd commented 3 months ago

6 years later, has an initialized or ready event supported?

still waiting

Now it's seven years.

Happy to celebrate 8 years here 🎉

already 9