Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/jean-merelis/ngx-monaco-editor
Monaco Code Editor for Angular
https://github.com/jean-merelis/ngx-monaco-editor
Last synced: 23 days ago
JSON representation
Monaco Code Editor for Angular
- Host: GitHub
- URL: https://github.com/jean-merelis/ngx-monaco-editor
- Owner: jean-merelis
- License: mit
- Created: 2024-04-09T13:56:36.000Z (8 months ago)
- Default Branch: master
- Last Pushed: 2024-07-03T12:21:21.000Z (5 months ago)
- Last Synced: 2024-11-12T05:37:43.487Z (about 1 month ago)
- Language: TypeScript
- Size: 464 KB
- Stars: 3
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: license
Awesome Lists containing this project
- awesome-angular - ngx-monaco-editor - Monaco Code Editor for Angular. (Table of contents / Third Party Components)
- fucking-awesome-angular - ngx-monaco-editor - Monaco Code Editor for Angular. (Table of contents / Third Party Components)
- fucking-awesome-angular - ngx-monaco-editor - Monaco Code Editor for Angular. (Table of contents / Third Party Components)
README
# NgxMonacoEditor is a Monaco Editor Component for Angular.
Supports all the options available in monaco-editor [Monaco Editor Options](https://microsoft.github.io/monaco-editor/typedoc/variables/editor.EditorOptions.html)
We will try to follow the MAJOR.MINOR versions of Angular to make it easier to identify compatibility. That's why our lib started with version 17 and not 1.
Angular 17.3 => v17.3.x
Angular 18 => v18.x.x## Setup
### Installation
Install from npm repository:
```
npm install monaco-editor @jean-merelis/ngx-monaco-editor --save
```### Provide a `MonacoLoader`
You can use `DefaultMonacoLoader` or create your own loader implementing the `MonacoLoader` interface.
`DefaultMonacoLoader` expects Monaco to be in the 'vs' folder of your domain. Ie. `http://localhost:4200/vs/`
For that add the following snipt in `angular.json````json
{
"apps": [
{
"assets": [
{ "glob": "**/*",
"input": "node_modules/monaco-editor/min/vs",
"output": "vs"
},
],
}
],
}
```You can provide your own configuration for `DefaultMonacoLoader`, but don't forget to change angular.js as well.
```typescript
// providing your own configuration
const monacoLoader = new DefaultMonacoLoader({paths: {vs: 'path/to/vs'}});@Component({
selector: 'app-root',
standalone: true,
templateUrl: './app.component.html',
styleUrl: './app.component.scss',
imports: [
FormsModule, ReactiveFormsModule,
NgxMonacoEditorComponent
],
providers: [
{provide: NGX_MONACO_LOADER_PROVIDER, useValue: monacoLoader} // <<<
]
})
export class AppComponent {
}
```### Global Editor configuration
You can provide a global configuration for yours editors.````typescript
export interface NgxMonacoEditorConfig {
defautlOptions?: StandaloneEditorConstructionOptions;
runInsideNgZone?: boolean
}
```````typescript
@Component({
selector: 'app-root',
standalone: true,
templateUrl: './app.component.html',
styleUrl: './app.component.scss',
imports: [
NgxMonacoEditorComponent
],
providers: [
{
provide: NGX_MONACO_EDITOR_CONFIG,
useValue: {
runInsideNgZone: false,
defautlOptions: {
minimap: {enabled: true}
}
}
}
]
})
export class AppComponent {
}
```### Sample
Include NgxMonacoEditorComponent in the `imports` of the component or module where you want to use the editor. (eg: app.module.ts). Add the provide the `MonacoLoader`:```typescript
import {Component} from '@angular/core';
import {
DefaultMonacoLoader,
EditorInitializedEvent,
NgxMonacoEditorComponent,
NGX_MONACO_LOADER_PROVIDER
} from "@jean-merelis/ngx-monaco-editor";@Component({
selector: 'app-root',
standalone: true,
templateUrl: './app.component.html',
styleUrl: './app.component.scss',
imports: [
NgxMonacoEditorComponent
],
providers: [
{provide: NGX_MONACO_LOADER_PROVIDER, useFactory: () => new DefaultMonacoLoader()}
]
})
export class AppComponent {
editorOptions = {theme: 'vs-dark', language: 'javascript'};
code: string = 'function helloWorld() {\nconsole.log("Hello world!");\n}';
}
``````html
```### Events
The output event (editorInitialized) emits an EditorInitializedEvent that exposes the editor instance, languages, and worker objects from Monaco API
which can be used to perform custom operations in the editor.
```htmlSet focus in the editor
``````typescript
export class AppComponent {
editorOptions = {theme: 'vs-dark', language: 'typescript'};
code: string = "const helloWorld = () => 'Hello world';"
events: string[] = [];// Object from Monaco API
private editor: any;
private monaco: any;editorInitialized(evt: EditorInitializedEvent) {
this.events.push("editorInitialized");
this.editor = evt.editor;
this.monaco = evt.monaco;
}onFocus() {
this.events.push("focus");
}onBlur() {
this.events.push("blur");
}
}
```## Testing with NgxMonacoEditorHarness
```typescript
import { NgxMonacoEditorHarness, MonacoEditorHarnessFilters } from "@jean-merelis/ngx-monaco-editor/testing";
```Harness for interacting with NgxMonacoEditor in tests.
You may want to run your tests with fakeAsync, so you need to configure to run Monaco Editor inside NgZone.
Then, in the last line of the test, call the `discardPeriodicTasks()` functionConfigure your test to wait for monacoLoader to complete. See the example below:
```typescript
@Component({
selector: 'wrapper',
standalone: true,
imports: [
CommonModule,
FormsModule,
ReactiveFormsModule,
NgxMonacoEditorComponent,
],
template: `
`
})
export class YourWrapperComponent {
code = model("");
code2 = model("");
}describe("NgxMonacoEditorComponent", () => {
let fixture: ComponentFixture;
let loader: HarnessLoader;beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
YourWrapperComponent,
NgxMonacoEditorComponent
],
providers: [
{provide: NGX_MONACO_LOADER_PROVIDER, useFactory: () => new DefaultMonacoLoader()},// If you need to run your tests with fakeAsync then run inside NgZone
{provide: NGX_MONACO_EDITOR_CONFIG, useValue: {runInsideNgZone: true}}
]
}).compileComponents();fixture = TestBed.createComponent(YourWrapperComponent);
loader = TestbedHarnessEnvironment.loader(fixture);// get MonacoLoader instance and wait to complete.
const monacoLoader = TestBed.inject(NGX_MONACO_LOADER_PROVIDER);
await monacoLoader.monacoLoaded();
fixture.detectChanges();
});it("should get NgxMonacoEditorHarness by testid", async () => {
const ngxMonaco = await loader.getHarnessOrNull(NgxMonacoEditorHarness.with({testid: "editor-2"}));
expect(ngxMonaco).toBeDefined();
});it("should emit focus event when get focus by click", async () => {
const ngxMonaco = await loader.getHarness(NgxMonacoEditorHarness);
await ngxMonaco.focus();
expect(await ngxMonaco.isFocused()).toBeTrue();
});it("should emit blur event when lose focus", async () => {
fixture.componentInstance.ngxEditor()?.focus()
const ngxMonaco = await loader.getHarness(NgxMonacoEditorHarness);
expect(await ngxMonaco.isFocused()).toBeTrue();await ngxMonaco.blur();
expect(await ngxMonaco.isFocused()).toBeFalse();
});it("should emit value when editor value changes", async () => {
const theCode = "const helloWorld = () => 'Hello world';";const ngxMonaco = await loader.getHarness(NgxMonacoEditorHarness);
await ngxMonaco.setValue(theCode);
expect(fixture.componentInstance.code()).toBe(theCode);
});it("should get text from editor", async () => {
const theCode = "const helloWorld = () => 'Hello world';";
fixture.componentInstance.code.set(theCode)
const ngxMonaco = await loader.getHarness(NgxMonacoEditorHarness);
expect(await ngxMonaco.getText()).toBe(theCode);
});
});```
#### Alternative
You can also use the NxMonacoEditorFakeComponent in your tests. This component does not create a real Monaco editor.
For that, configure the NxMonacoEditorFakeComponent in TestBed, instead NxMonacoEditorComponent.NxMonacoEditorFakeComponent has your own harness, NxMonacoEditorFakeHarness
```typescript
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
YourWrapperComponent,
NgxMonacoEditorFakeComponent
],// >>> this is not necessary for NgxMonacoEditorFakeComponent <<<
// providers: [
// {provide: NGX_MONACO_LOADER_PROVIDER, useFactory: () => new DefaultMonacoLoader()}
// ]
}).compileComponents();fixture = TestBed.createComponent(YourWrapperComponent);
loader = TestbedHarnessEnvironment.loader(fixture);
// >>> this is not necessary for NgxMonacoEditorFakeComponent <<<
// const monacoLoader = TestBed.inject(NGX_MONACO_LOADER_PROVIDER);
// await monacoLoader.monacoLoaded();fixture.detectChanges();
});
```