PeterFromCologne
PeterFromCologne

Reputation: 10463

Monaco Editor How to load CompletionItems from server?

I got an angular 8 app with the fantastic monaco editor embedded for some formula editing. it works well so far but the list of suggestions = CompletionItems needs to change dynamically.

I am using the ngx-monaco-editor module and provide my language definition in the app module:

MonacoEditorModule.forRoot(MyMonacoLanguageConfig)

which is configured similar to this:

const MonacoAirLanguageConfig: NgxMonacoEditorConfig = {
    onMonacoLoad: function () {
        monaco.languages.register({ id: 'myCoolLang' });
        monaco.languages.setLanguageConfiguration('myCoolLang', { ...});
        monaco.languages.registerCompletionItemProvider('myCoolLang', {
            provideCompletionItems: (model, position) => {
                return {
                    suggestions: [
                        {
                            label: 'ThisHasToBeReplaced',
                            kind: monaco.languages.CompletionItemKind.Function,
                            insertText: 'ThisHasToBeReplacedWithSomethingCool()',
                            insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet
                        }]
                };
            }
        });
    }
};
export default MonacoAirLanguageConfig;

Then I am using the monaco editor in my components

    <ngx-monaco-editor [options]="editorOptions" (onInit)="initLanguage($event)"></ngx-monaco-editor>

I could call the server in provideCompletionItems but I can't reference my services nor do I have the context from the component where the monaco editor is used. I tried to change the language registration in the onInit event, but thats too late it seems.

I am lost. Sorry :-/ and thanks for any help.

Upvotes: 0

Views: 2231

Answers (2)

Louis L
Louis L

Reputation: 433

It seems that you're looking for a language server. If I understand your question right, you'd like to get completion items from the server.

You can have a look at monaco-languageclient, this npm package can help you connect Monaco editor with a language server. There is also a language server example written by javascript, I believe you can find any other Monaco language server written by other languages as well if your back-end server is not using Node.js. The completion logic is here, you can return your completion item by customizing this function:

protected completion(params: TextDocumentPositionParams): Thenable<CompletionList | null> {
    const document = this.documents.get(params.textDocument.uri);
    if (!document) {
        return Promise.resolve(null);
    }
    const jsonDocument = this.getJSONDocument(document);
    return this.jsonService.doComplete(document, params.position, jsonDocument);
}

If you're looking for an example to show how to connect Monaco editor with a language server, I have a repository angular-monaco-languageclient. Hope it can help you.

Upvotes: 2

PeterFromCologne
PeterFromCologne

Reputation: 10463

Solution/Workaround I document what I did to achieve asynchronously getting completion items. I am pretty sure it was not intended like this and I will update if I find a better way or get a better answer.

When the ngx module raises the onInit event with the editor instance

(onInit)="initEditor($event)"

I create a model for the editor and then I call the server to get the completionItems and put them in a model property. When the user starts asking for completion items the provideCompletionItems is called and I get the completion items from the model.

  initEditor(editor) {
    let editorModel = editor.getModel();
    <call webserver>
      .subscribe(completionItems => editorModel['completionItems'] = completionItems);

and in the language setup:

monaco.languages.registerCompletionItemProvider('air', {
    provideCompletionItems: (model, position) => {
        return {
            suggestions: model.completionItems
        };
    });

Upvotes: 1

Related Questions