Monaco-editor: getModelMarkers not working to get list of errors

Created on 2 Jun 2018  路  11Comments  路  Source: microsoft/monaco-editor

I'm trying to get list of validation errors generated by monaco editor and do some custom operations, my current implementation is working but it's not an ideal solution, I'm looking for something like where i can use getModelMarkers instead of setModelMarkers which i'm using currently shown below.

updateEditorText(val) {
            const setModelMarkers = monaco.editor.setModelMarkers;
            monaco.editor.setModelMarkers = (model, owner, markers) => {
                debugger;
                setModelMarkers.call(monaco.editor, model, owner, markers);
                if (markers.length === 0) {
                    this.containsValidationErrors = false;
                    this.setJsonText(val);
                } else {
                    this.containsValidationErrors = true;
                }
            };
        },

I found we can do like

monaco.editor.getModelMarkers({}).map(m => m.message).join(', ')

but when i try to use it in my function above instead of setModelMarkers it does'nt work and throws errors. Please suggest How can i use monaco.editor.getModelMarkers

Most helpful comment

Fixed my issue by grabbing the editor off of the window rather than from the ngx-monaco-editor on-load callback.

(<any>window).monaco.editor.getModelMarkers({});

All 11 comments

Can you provide a simple example that demonstrates your problem using the Monaco Playground?

but when i try to use it in my function above instead of setModelMarkers it does'nt work and throws errors.

Alternatively, what are these errors you speak of?

@rcjsuen thanks for responding on this issue.
Just to clarify issue, Look at the following simple function which i updated from setModelMarkers to getModelMarkers and try to log the errors list

updateEditorText(val) {
   console.log(monaco.editor.getModelMarkers({}).map(m => m.message).join(', '));           
},

It gives me the error
TypeError: monaco.editor.getModelMarkers is not a function

Just an fyi, This is a Vuejs application and i'm note sure how can i run the Vuejs code in Monaco playground. Do you think i'm doing something stupid in here. My understanding is like it's working for setModelMarkers as i mentioned in previous post, it should also work for getModelMarkers??

Hi, @imzubair10. This code works fine for me. I see stuff printed in the console.

// The Monaco Editor can be easily created, given an
// empty container and an options literal.
// Two members of the literal are "value" and "language".
// The editor takes the full size of its container.

let model = monaco.editor.createModel("function hello() {\n}", "javascript");

monaco.editor.create(document.getElementById("container"), {
    model
});

monaco.editor.setModelMarkers(model, "owner", [
    {
        startLineNumber: 1,
        startColumn: 1,
        endLineNumber: 1,
        endColumn: 2,
        message: "error",
        severity: monaco.MarkerSeverity.Error
    }
]);

console.log(monaco.editor.getModelMarkers());

@rcjsuen that's so weird, i tried it again but it didn't work and throws same error you can see below,

getmodel-monaco-error

My understanding, by looking at the error in the screen shot, it makes me feel monaco editor is controlled by editor.main.js file and it does'nt have getModelMarkers function, it might sound stupid to you but that's what i guess, if it's the case , do i need to update editor.main.js file and how can i update that file though??

Just an fyi, i've defined a separate Monaco Editor component like below,

export const TMonacoEditor = Vue.extend({
    name: 't-monaco-editor',
    props: {
        code: { type: String, default: '// code \n' },
        language: { type: String, default: 'javascript' },
        theme: { type: String, default: 'vs' }, // vs, hc-black
        width: { type: [String, Number], default: '100%' },
        height: { type: [String, Number], default: '100%' },
        dataSchema: {
            required: false
        } as PropOptions<MonacoSchema>
    },
    data() {
        return {
            monaco: null,
            editor: null
        };
    },
    mounted() {
        this.fetchEditor();
    },
    destroyed() {
        if (!!this.editor) {
            this.editor.dispose();
        }
    },
    computed: {
        style(): object {
            const { width, height } = this;
            const fixedWidth = width.toString().indexOf('%') !== -1 ? width : `${width}px`;
            const fixedHeight = height.toString().indexOf('%') !== -1 ? height : `${height}px`;
            return {
                width: fixedWidth,
                height: fixedHeight,
                border: '1px solid #eaeaea'
            };
        },
        editorOptions(): object {
            return {
                selectOnLineNumbers: true,
                roundedSelection: false,
                cursorStyle: 'line',
                automaticLayout: false,
                glyphMargin: true,
                readOnly: this.isReadOnly,
                value: this.code,
                language: this.language,
                theme: this.theme
            };
        }
    },
    watch: {
        isReadOnly(newVal) {
            this.editor && this.editor.updateOptions({ readOnly: this.isReadOnly });
        },
        code(newVal) {
            if (!Utils.deepEqual(newVal, this.editor.getValue())) {
                this.editor.setValue(newVal);
            }
        }
    },
    methods: {
        fetchEditor() {
            if (!this.monaco) {
                const loaderScript = window.document.createElement('script');
                loaderScript.type = 'text/javascript';
                loaderScript.src = '../../client/webpack/lib/vs/loader.js';
                loaderScript.addEventListener('load', () => {
                    const configPathJs = window.document.createElement('script');
                    configPathJs.type = 'text/javascript';
                    configPathJs.src = '../../client/webpack/lib/vs/monacoLoader.js';
                    window.document.body.appendChild(configPathJs);
                    const interval = setInterval(() => {
                        if (typeof monacoEditorLoaded !== 'undefined') {
                            this.createMonaco();
                            this.$emit('mounted', this.editor);
                            clearInterval(interval);
                        }
                    }, 100);
                });
                window.document.body.appendChild(loaderScript);
            } else {
                this.createMonaco();
            }
        },
        createMonaco() {
            //Only create a Monaco model when schema is passed as prop
            if (this.dataSchema) {
                monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
                    validate: true,
                    schemas: [{
                        fileMatch: [this.dataSchema.id],
                        schema: {
                            type: 'object',
                            properties: this.dataSchema.value,
                            required: ['type', 'version'],
                            additionalProperties: false
                        }
                    }]
                });

                if (!monaco.editor.getModel(this.dataSchema.id)) {
                    const model = monaco.editor.createModel(this.code, 'json', this.dataSchema.id);
                    this.editorOptions['model'] = model;
                }
            }

            this.editor = monaco.editor.create(this.$el, this.editorOptions);
            this.editor.onDidChangeModelContent(event =>
                this.$emit('codeChange', this.editor.getValue())
            );

            this.monaco = monaco;
        }
    },
    render(h): VNode {
        return <div style={this.style} />;
    }
});

Please run my code in the Monaco Playground and verify that it works there for you.

When i run your code it works in the Monaco Playground, but i'm not sure why when i run it in my project it does'nt work and throws error

TypeError: monaco.editor.getModelMarkers is not a function

So, I'm not sure why it's not able to find function getModelMarkers ()

@imzubair10 where's the updateEditorText/getModelMarkers being called in your Vue setup? That didn't seem to be in the component you posted above. It almost seems like you've isolated the scope of that code from your Monaco instance. Can you access any other monaco objects/methods there?

So it's actually a version issue that we are using currently. So, I want to use monaco editor npm package. This is my current monaco editor Vue.js component implementation, how should i use monaco-editor npm package in this component. What would i need to update in heere

MonacoEditor.tsx file

export const TMonacoEditor = Vue.extend({
    name: 't-monaco-editor',
    props: {
        code: { type: String, default: '// code \n' },
        language: { type: String, default: 'javascript' },
        theme: { type: String, default: 'vs' }, // vs, hc-black
        width: { type: [String, Number], default: '100%' },
        height: { type: [String, Number], default: '100%' },
        dataSchema: {
            required: false
        } as PropOptions<MonacoSchema>
    },
    data() {
        return {
            monaco: null,
            editor: null
        };
    },
    mounted() {
        this.fetchEditor();
    },
    destroyed() {
        if (!!this.editor) {
            this.editor.dispose();
        }
    },
    computed: {
        style(): object {
            const { width, height } = this;
            const fixedWidth = width.toString().indexOf('%') !== -1 ? width : `${width}px`;
            const fixedHeight = height.toString().indexOf('%') !== -1 ? height : `${height}px`;
            return {
                width: fixedWidth,
                height: fixedHeight,
                border: '1px solid #eaeaea'
            };
        },
        editorOptions(): object {
            return {
                selectOnLineNumbers: true,
                roundedSelection: false,
                cursorStyle: 'line',
                automaticLayout: false,
                glyphMargin: true,
                readOnly: this.isReadOnly,
                value: this.code,
                language: this.language,
                theme: this.theme
            };
        }
    },
    watch: {
        isReadOnly(newVal) {
            this.editor && this.editor.updateOptions({ readOnly: this.isReadOnly });
        },
        code(newVal) {
            if (!Utils.deepEqual(newVal, this.editor.getValue())) {
                this.editor.setValue(newVal);
            }
        }
    },
    methods: {
        fetchEditor() {
            if (!this.monaco) {
                const loaderScript = window.document.createElement('script');
                loaderScript.type = 'text/javascript';
                loaderScript.src = '../../client/webpack/lib/vs/loader.js';
                loaderScript.addEventListener('load', () => {
                    const configPathJs = window.document.createElement('script');
                    configPathJs.type = 'text/javascript';
                    configPathJs.src = '../../client/webpack/lib/vs/monacoLoader.js';
                    window.document.body.appendChild(configPathJs);
                    const interval = setInterval(() => {
                        if (typeof monacoEditorLoaded !== 'undefined') {
                            this.createMonaco();
                            this.$emit('mounted', this.editor);
                            clearInterval(interval);
                        }
                    }, 100);
                });
                window.document.body.appendChild(loaderScript);
            } else {
                this.createMonaco();
            }
        },
        createMonaco() {
            //Only create a Monaco model when schema is passed as prop
            if (this.dataSchema) {
                monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
                    validate: true,
                    schemas: [{
                        fileMatch: [this.dataSchema.id],
                        schema: {
                            type: 'object',
                            properties: this.dataSchema.value,
                            required: ['type', 'version'],
                            additionalProperties: false
                        }
                    }]
                });

                if (!monaco.editor.getModel(this.dataSchema.id)) {
                    const model = monaco.editor.createModel(this.code, 'json', this.dataSchema.id);
                    this.editorOptions['model'] = model;
                }
            }

            this.editor = monaco.editor.create(this.$el, this.editorOptions);
            this.editor.onDidChangeModelContent(event =>
                this.$emit('codeChange', this.editor.getValue())
            );

            this.monaco = monaco;
        }
    },
    render(h): VNode {
        return <div style={this.style} />;
    }
});

I have a similar issue in Angular, using ngx-monaco-editor which depends on the latest version of monaco-editor.

global-error-handler.ts:29 TypeError: this.editor.getModelMarkers is not a function

Did you close this because you worked out a fix @imzubair10 ?

Fixed my issue by grabbing the editor off of the window rather than from the ngx-monaco-editor on-load callback.

(<any>window).monaco.editor.getModelMarkers({});

Hey @JoshYaxley, good to know that you were able to figure out the fix at your end, just an fyi, my issue is that we're using older version of Monaco Editor 0.8.2 and this getModelMarkers api is not available in that version

Was this page helpful?
0 / 5 - 0 ratings