Skip to content

Code editor component for Angular applications.

License

Notifications You must be signed in to change notification settings

ngstack/code-editor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@ngstack/code-editor

Code editor component for Angular applications.

Based on the Monaco editor that powers VS Code.

Buy Me A Coffee

Installing

npm install @ngstack/code-editor

Integrating with Angular CLI project

Import CodeEditorModule into your main application module:

import { CodeEditorModule } from '@ngstack/code-editor';

@NgModule({
  imports: [CodeEditorModule.forRoot()]
})
export class AppModule {}

If you want to use a specific version of the Monaco editor, use editorVersion parameter. If not provided, the component is always going to use the latest version.

For a full list of Monaco versions and changes, please refer to the official CHANGELOG.md file

@NgModule({
  imports: [
    CodeEditorModule.forRoot({
      editorVersion: '0.44.0'
    })
  ]
})
export class AppModule {}

Update template to use the ngs-code-editor:

<ngs-code-editor [theme]="theme" [codeModel]="model" [options]="options" (valueChanged)="onCodeChanged($event)"></ngs-code-editor>

Update component controller class and provide corresponding properties and events:

export class AppComponent {
  theme = 'vs-dark';

  model: CodeModel = {
    language: 'json',
    uri: 'main.json',
    value: '{}'
  };

  options = {
    contextmenu: true,
    minimap: {
      enabled: true
    }
  };

  onCodeChanged(value) {
    console.log('CODE', value);
  }
}

Input Properties

Name Type Default Value Description
theme string vs Editor theme. Supported values: vs, vs-dark or hc-black.
options Object {...} Editor options.
readOnly boolean false Toggles readonly state of the editor.
codeModel CodeModel Source code model.

The codeModel property holds the value that implements the CodeModel interface:

export interface CodeModel {
  language: string;
  value: string;
  uri: string;

  dependencies?: Array<string>;
  schemas?: Array<{
    uri: string;
    schema: Object;
  }>;
}

Editor Options

For available options see IEditorConstructionOptions docs.

The following options are used by default when Editor Component gets created:

{
  "lineNumbers": true,
  "contextmenu": false,
  "minimap": {
    "enabled": false
  }
}

Output Events

Name Argument Type Description
loaded Raised when editor finished loading all its components.
valueChanged string An event emitted when the text content of the model have changed.
modelContentChanged IModelContentChangedEvent An event emitted when the contents of the underlying editor model have changed
codeModelChanged CodeModelChangedEvent An event emitted when the code model value is changed.

Component API

Name Description
editor returns the instance of the underlying Monaco ICodeEditor
runAction(id, args) runs the editor actions, for example editor.action.formatDocument
formatDocument() shortcut function to format the document

Editor Service

The component comes with a separate CodeEditorService service that provides additional APIs for the underlying monaco editor:

Name Description
monaco get the global monaco instance
typingsLoaded An event emitted when code typings are loaded
loaded An event emitted when the monaco instance is loaded
setTheme(themeName) Switches to a theme

Typings

The editor is able to resolve typing libraries when set to the Typescript or Javascript language.

Use dependencies property to provide a list of libraries to resolve

<ngs-code-editor [codeModel]="model" ...> </ngs-code-editor>

And in the controller class:

export class MyEditorComponent {
  codeModel: CodeModel = {
    language: 'typescript',
    uri: 'main.ts',
    value: '',
    dependencies: ['@types/node', '@ngstack/translate', '@ngstack/code-editor']
  };
}

Run your application, it may take a few seconds to resolve dependencies. It is performed in the background (web worker), so you can type your code.

Try pasting the following snippet at runtime:

import { TranslateModule, TranslateService } from '@ngstack/translate';
import { CodeEditorModule } from '@ngstack/code-editor';
import * as fs from 'fs';

export class MyClass {
  constructor(translate: TranslateService) {}
}

You should have all the types resolved and auto-completion working.

JSON schemas

You can associate multiple schemas when working with JSON files.

<ngs-code-editor [codeModel]="model" ...> </ngs-code-editor>

Provide the required schemas like in the example below.

export class MyEditorComponent {
  codeModel: CodeModel = {
    language: 'json',
    uri: 'main.json',
    value: '{ "test": true }',
    schemas: [
      {
        uri: 'https://custom/schema.json',
        schema: {
          type: 'object',
          properties: {
            type: {
              enum: ['button', 'textbox']
            }
          }
        }
      }
    ]
  };
}

The schemas get automatically installed and associated with the corresponding file.

Accessing Code Editor Instance

You can access the Code Editor component instance API from other components when using with the @ViewChild:

  private _codeEditor: CodeEditorComponent;

  @ViewChild(CodeEditorComponent, { static: false })
  set codeEditor(value: CodeEditorComponent) {
    this._codeEditor = value;
  }

  get codeEditor(): CodeEditorComponent {
    return this._codeEditor;
  }

The code above allows you to use the code editor within the *ngIf, for example:

<ng-container *ngIf="selectedModel">
  <ngs-code-editor [codeModel]="selectedModel"></ngs-code-editor>
</ng-container>

Other components can now have access to the editor instance:

<button mat-icon-button title="Format code" (click)="codeEditor?.formatDocument()">
  <mat-icon>format_align_left</mat-icon>
</button>

Example: auto-formatting on load

<ngs-code-editor [codeModel]="selectedModel" [options]="options" (codeModelChanged)="onCodeModelChanged($event)"></ngs-code-editor>
import { CodeModelChangedEvent } from '@ngstack/code-editor';

onCodeModelChanged(event: CodeModelChangedEvent) {
  setTimeout(() => {
    event.sender.formatDocument();
  }, 100);
}

Offline Setup

Editor

You can run the editor in the offline mode with your Angular CLI application using the following steps:

Install the monaco-editor:

npm install monaco-editor

Update the angular.json file and append the following asset rule:

{
  "glob": "**/*",
  "input": "../node_modules/monaco-editor/min",
  "output": "./assets/monaco"
}

Update the main application module and setup the service to use the custom baseUrl when application starts:

import { CodeEditorModule } from '@ngstack/code-editor';

@NgModule({
  imports: [
    CodeEditorModule.forRoot({
      baseUrl: 'assets/monaco'
    })
  ]
})
export class AppModule {}

Typings Worker

Update the angular.json file and append the following asset rule:

{
  "glob": "**/*.js",
  "input": "../node_modules/@ngstack/code-editor/workers",
  "output": "./assets/workers"
}

Then update the CodeEditorService configuration at the application startup:

@NgModule({
  imports: [
    CodeEditorModule.forRoot({
      typingsWorkerUrl: 'assets/workers/typings-worker.js'
    })
  ]
})
export class AppModule {}

Lazy Loading

To enable Lazy Loading use CodeEditorModule.forRoot() in the main application, and CodeEditorModule.forChild() in all lazy-loaded feature modules.

For more details please refer to Lazy Loading Feature Modules