How to setup Ace editor in Angular?
Tags: anguar, aceeditor, javascript, typescript
Published: 2020-10-27 09:50:04

---
title: How to setup Ace editor in Angular?
published: true
description: In this article, I will show you how to ⚡ quickly setup ✏️ Ace editor in 🅰️ Angular without any other 3rd party libraries.
tags: anguar,aceeditor,javascript,typescript
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/6qi9qbmvcsxzqxv9i1ka.png
canonical_url: https://blog.shhdharmen.me/how-to-setup-ace-editor-in-angular
---

In this article, I will show you how to ⚡ quickly setup ✏️ [Ace editor](https://ace.c9.io/) in 🅰️ Angular without any other 3rd party libraries.

## ✏️ Ace Editor

Ace is an embeddable code editor written in JavaScript. It matches the features and performance of native editors such as Sublime, Vim and TextMate. It can be easily embedded in any web page and JavaScript application. Ace is maintained as the primary editor for [Cloud9 IDE](https://c9.io/) and is the successor of the Mozilla Skywriter (Bespin) project.

Both [Cloud9 IDE](https://c9.io/) and [Mozilla](https://mozilla.org/) are actively developing and maintaining Ace.

## 👨‍💻 Let's talk Coding

### 📁 Create a workspace

Open up your terminal and:

```bash
npm i -g @angular/cli
ng new ace-angular --defaults --minimal
```

> 👉 Do not use `--minimal` option in production applications, it creates a workspace without any testing frameworks. You can read more about [CLI options](https://angular.io/cli/new#options).

At this point, your folder structure should look like this and it is going to be same till the end:

![Folder structure](https://cdn.hashnode.com/res/hashnode/image/upload/v1603781791166/vkIrLe8CY.png)

### ⏬ Install Ace editor

We will install pre-packaged version of Ace from [npm](https://www.npmjs.com/package/ace-builds):

```bash
npm i ace-builds
```

### 🛠️ Setup editor

One advantage of using *ace-builds* package directly in Angular is that they already provide support for Typescript. You can check in their [repo](https://github.com/ajaxorg/ace-builds), they have their type definitions files at place:

![type definitions files](https://cdn.hashnode.com/res/hashnode/image/upload/v1603782170636/5u0zW1EvI.png)

#### 📄 app.component.ts

Clear all the content of the file and start with below:

```typescript
import { AfterViewInit, Component, ElementRef, ViewChild } from "@angular/core";

// 1️⃣
import * as ace from "ace-builds";

// 2️⃣
@Component({
  selector: "app-root",
  template: `
    <div
      class="app-ace-editor"
      #editor
      style="width: 500px;height: 250px;"
    ></div>
  `,
  styles: [
    `
      .app-ace-editor {
        border: 2px solid #f8f9fa;
        box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
      }
    `,
  ],
})
export class AppComponent implements AfterViewInit {

  // 3️⃣
  @ViewChild("editor") private editor: ElementRef<HTMLElement>;

  // 4️⃣
  ngAfterViewInit(): void {
    ace.config.set("fontSize", "14px");
    const aceEditor = ace.edit(this.editor.nativeElement);
    aceEditor.session.setValue("<h1>Ace Editor works great in Angular!</h1>");
  }
}
```

Let's see what's happening here:

1. First, we are importing `ace` from `ace-builds` package.
2. Then, we are setting HTML template. Note that `height` and `width` are required, otherwise editor won't load. I have also added styling, you can skip that if you want.
3. After above, we are querying our editor using `@ViewChild`
4. 
  i. To access queried child of `@ViewChild`, we need to use `ngAfterViewInit` life-cycle hook. Becuase view queries are set before the ngAfterViewInit callback is called.

  ii. We are setting default font-size of editor to `14px`. There are lots of configuration options which Ace editor provides, please check them [here](https://github.com/ajaxorg/ace/wiki/Configuring-Ace)

  iii. Then, we are attaching Ace editor to our `#editor` element.

  iv. And last, we are setting up the default value. You can check the the how-tos of Ace editor at its [how-to guide](https://ace.c9.io/#nav=howto).


Let's look at the output:

![ace editor in angular output](https://cdn.hashnode.com/res/hashnode/image/upload/v1603784072485/CDXlxdPY7.png)

Congratulations 🎉🎉🎉. You have completed the setup of Ace editor. 👏👏👏.

### 🔭 Further usage

In real-world scenarios, you would also want to enable syntax highlighting and get the value from editor. Let's see it in action.

#### 🌄 Set theme and syntax highlighting

In *app.component.ts* make below changes:

```typescript
...
ngAfterViewInit(): void {
    ace.config.set("fontSize", "14px");
    const aceEditor = ace.edit(this.editor.nativeElement);
    aceEditor.session.setValue("<h1>Ace Editor works great in Angular!</h1>");

  // 🚨 Added
  aceEditor.setTheme('ace/theme/twilight');
  aceEditor.session.setMode('ace/mode/html');
  }
```

Cool. Let's see the output in the browser:

![ace editor in angular output](https://cdn.hashnode.com/res/hashnode/image/upload/v1603784072485/CDXlxdPY7.png)

As you can see, highlighting and syntax aren't enabled. Let's see if there is any error in browser console:

![browser console error](https://cdn.hashnode.com/res/hashnode/image/upload/v1603784945878/hf7spRiph.png)

Error says: *Unable to infer path to ace from script src, use ace.config.set('basePath', 'path') to enable dynamic loading of modes and themes or with webpack use ace/webpack-resolver*, which means Ace is not able to find relevant files for themes and syntax highlighting.

You see, they have already given a solution, too in the error console. That is to use: `ace.config.set('basePath', 'path')`. By default ace detects the url for dynamic loading by finding the script node for ace.js. This doesn't work if ace.js is not loaded with a separate script tag, and in this case it is required to set url explicitely. And the url should be pointing to a folder that contains ace nodes.

Thanks to [unpkg.com](https://unpkg.com/), we can get the needed URL:

```
https://unpkg.com/ace-builds@1.4.12/src-noconflict
```

Let's update it in our code:

```typescript
...
ngAfterViewInit(): void {
    ace.config.set("fontSize", "14px");

    // 🚨 Added
    ace.config.set('basePath', 'https://unpkg.com/ace-builds@1.4.12/src-noconflict');

    const aceEditor = ace.edit(this.editor.nativeElement);
    aceEditor.session.setValue("<h1>Ace Editor works great in Angular!</h1>");

    aceEditor.setTheme('ace/theme/twilight');
    aceEditor.session.setMode('ace/mode/html');
  }
```

Check the output:

![ace editor output after setting basepath](https://cdn.hashnode.com/res/hashnode/image/upload/v1603785676107/jdRY_J9cv.png)

#### ✍️ Get value from editor

```typescript
...
ngAfterViewInit(): void {
    ace.config.set("fontSize", "14px");
    ace.config.set(
      "basePath",
      "https://unpkg.com/ace-builds@1.4.12/src-noconflict"
    );
    const aceEditor = ace.edit(this.editor.nativeElement);
    aceEditor.session.setValue("<h1>Ace Editor works great in Angular!</h1>");
    aceEditor.setTheme("ace/theme/twilight");
    aceEditor.session.setMode("ace/mode/html");

    // 🚨 Added
    aceEditor.on("change", () => {
      console.log(aceEditor.getValue());
    });
  }
```

I think it's clear from the code how to get value 😉. You should check all the events supported by Ace editor. Thanks to Typescript and VS Code, you can see it while editing:

![supported events](https://cdn.hashnode.com/res/hashnode/image/upload/v1603786033832/u1au7zu0W.png)

Let's see the output:

![ace editor in action](https://cdn.hashnode.com/res/hashnode/image/upload/v1603790330226/I8GdULMM0.gif)

Cool, with that we are done 👍

The final version of *app.component.ts* looks like below:

```typescript
import { AfterViewInit, Component, ElementRef, ViewChild } from "@angular/core";
import * as ace from "ace-builds";

@Component({
  selector: "app-root",
  template: `
    <div
      class="app-ace-editor"
      #editor
      style="width: 500px;height: 250px;"
    ></div>
  `,
  styles: [
    `
      .app-ace-editor {
        border: 2px solid #f8f9fa;
        box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
      }
    `,
  ],
})
export class AppComponent implements AfterViewInit {
  @ViewChild("editor") private editor: ElementRef<HTMLElement>;

  ngAfterViewInit(): void {
    ace.config.set("fontSize", "14px");
    ace.config.set(
      "basePath",
      "https://unpkg.com/ace-builds@1.4.12/src-noconflict"
    );
    const aceEditor = ace.edit(this.editor.nativeElement);
    aceEditor.session.setValue("<h1>Ace Editor works great in Angular!</h1>");
    aceEditor.setTheme("ace/theme/twilight");
    aceEditor.session.setMode("ace/mode/html");
    aceEditor.on("change", () => {
      console.log(aceEditor.getValue());
    });
  }
}

```

## Conclusion

We saw how we can simply use Ace editor in Angular without any 3rd party library usage.

Code is available at Github repo: [shhdharmen/ace-angular](https://github.com/shhdharmen/ace-angular)

[![ReadMe Card](https://github-readme-stats.vercel.app/api/pin/?username=shhdharmen&repo=ace-angular)](https://github.com/shhdharmen/ace-angular)

### Thank You

for reading my article. Let me know your thoughts in the comments section.

I am also available on twitter as [@shhdharmen](https://twitter.com/shhdharmen) if you want to say hi 👋.