Skip to content

astronautlabs/monaco

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

89 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@/monaco

Monaco Editor Component for Angular

Version

Stable
This software is ready for production use.

Setup

Which version should I use for my version of Angular?
As new Angular versions are released, the major version of this library will always match the major version of Angular.

npm install monaco-editor @astronautlabs/monaco@12 --save # eg, for Angular 12

You must include the monaco-editor assets in the build so they can be loaded at runtime:

// in projects.[project-name].architect.build:
{
  "options": {
    {
      "assets": [
        { "glob": "**/*", "input": "node_modules/monaco-editor", "output": "assets/monaco-editor" }
      ],
      ...
    }
    ...
  },
  ...
}

Referencing Monaco Types

Important: Monaco is loaded dynamically at runtime. You should only use import type or /// <reference ...> when accessing types from the monaco-editor package to avoid loading Monaco twice which can cause reference confusion.

However, Monaco's monaco global cannot be represented to Typescript using, for instance, import type * as monaco from 'monaco-editor'.

The other solution is to use /// <reference ...>, but unfortunately the type declarations found by Typescript when using // <reference types="monaco-editor" /> is the editor API which is incorrect.

A working solution is the following:

/// <reference path="../../node_modules/monaco-editor/monaco.d.ts" />
monaco.languages // <-- Correct Typescript types and no undefined variable "monaco" error

Unfortunately this means you will need to vary this directive based on where a source file is within your application.

Add the Angular Module

Include MonacoEditorModule:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { MonacoEditorModule } from '@astronautlabs/monaco';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    MonacoEditorModule.forRoot({
      // Options
    })
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {
}

Make sure to also import MonacoEditorModule (without .forRoot()) in each module that you use <ngx-monaco-editor>

Using the Editor

In most cases you'll want to specify options for particular instances of Monaco:

import { Component } from '@angular/core';
import type * as monaco from 'monaco-editor';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html'
})
export class AppComponent {
  editorOptions: monaco.editor.IStandaloneEditorConstructionOptions = {
    theme: 'vs-dark', 
    language: 'javascript'
  };

  code: string = 'function x() {\nconsole.log("Hello world!");\n}';
}

HTML

<ngx-monaco-editor [options]="editorOptions" [(ngModel)]="code"></ngx-monaco-editor>

Using the Diff Editor

import { Component } from '@angular/core';
import { DiffEditorModel } from '@astronautlabs/monaco';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html'
})
export class AppComponent {
  options = {
    theme: 'vs-dark'
  };
  originalModel: DiffEditorModel = {
    code: 'heLLo world!',
    language: 'text/plain'
  };

  modifiedModel: DiffEditorModel = {
    code: 'hello orlando!',
    language: 'text/plain'
  };
}

HTML

<ngx-monaco-diff-editor [options]="options" [originalModel]="originalModel" [modifiedModel]="modifiedModel"></ngx-monaco-diff-editor>

Styling

To match height of container element add height: 100% and wrap in container

<div style="height: 500px">
    <ngx-monaco-editor style="height: 100%" [options]="editorOptions" [(ngModel)]="code"></ngx-monaco-editor>
</div>

Add class to editor tag. (eg. class="my-code-editor")

<ngx-monaco-editor class="my-code-editor" [options]="editorOptions" [(ngModel)]="code"></ngx-monaco-editor>

Add styling in css/scss file:

.my-code-editor {
  .editor-container {
    height: calc(100vh - 100px);
  }
}

Set automaticLayout option to adjust editor size dynamically. Recommended when using in modal dialog or tabs where editor is not visible initially.

Events

Output event (onInit) expose editor instance that can be used for performing custom operations on the editor.

<ngx-monaco-editor [options]="editorOptions" [(ngModel)]="code" (onInit)="onInit($event)"></ngx-monaco-editor>
export class AppComponent {
  editorOptions = {theme: 'vs-dark', language: 'javascript'};
  code: string= 'function x() {\nconsole.log("Hello world!");\n}';
  onInit(editor) {
      let line = editor.getPosition();
      console.log(line);
    }
}

Configuration

forRoot() method of MonacoEditorModule accepts config of type NgxMonacoEditorConfig.

import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';

import { MonacoEditorModule, NgxMonacoEditorConfig } from '@astronautlabs/monaco';
import { AppComponent } from './app.component';

const monacoConfig: NgxMonacoEditorConfig = {
  baseUrl: 'app-name/assets', // configure base path cotaining monaco-editor directory after build default: './assets'
  defaultOptions: { scrollBeyondLastLine: false }, // pass default options to be used
  onMonacoLoad: () => { console.log((<any>window).monaco); } // here monaco object will be available as window.monaco use this function to extend monaco editor functionalities.
};

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    MonacoEditorModule.forRoot(monacoConfig)
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {
}

Language Defaults

onMonacoLoad property of NgxMonacoEditorConfig can be used to configure language defaults.

import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';

import { MonacoEditorModule, NgxMonacoEditorConfig } from '@astronautlabs/monaco';
import { AppComponent } from './app.component';

export function onMonacoLoad() {

  console.log((window as any).monaco);

  const uri = monaco.Uri.parse('a://b/foo.json');
  monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
    validate: true,
    schemas: [{
      uri: 'http://myserver/foo-schema.json',
      fileMatch: [uri.toString()],
      schema: {
        type: 'object',
        properties: {
          p1: {
            enum: ['v1', 'v2']
          },
          p2: {
            $ref: 'http://myserver/bar-schema.json'
          }
        }
      }
    }, {
      uri: 'http://myserver/bar-schema.json',
      fileMatch: [uri.toString()],
      schema: {
        type: 'object',
        properties: {
          q1: {
            enum: ['x1', 'x2']
          }
        }
      }
    }]
  });

}

const monacoConfig: NgxMonacoEditorConfig = {
  baseUrl: 'assets',
  defaultOptions: { scrollBeyondLastLine: false },
  onMonacoLoad
};

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    MonacoEditorModule.forRoot(monacoConfig)
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {
}

Now pass model config of type NgxEditorModel to Editor Component

@Component({
  selector: 'app-root',
  template: `<ngx-monaco-editor [options]="options" [model]="model"></ngx-monaco-editor>`,
  styles: []
})
export class AppComponent {
  options = {
    theme: 'vs-dark'
  };
  
  jsonCode = [
    '{',
    '    "p1": "v3",',
    '    "p2": false',
    '}'
  ].join('\n');

  model: NgxEditorModel = {
    value: this.jsonCode,
    language: 'json',
    uri: monaco.Uri.parse('a://b/foo.json')
  };
}

Resources

About

Monaco Editor component for Angular

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • TypeScript 86.3%
  • JavaScript 12.1%
  • HTML 1.3%
  • CSS 0.3%