In this article, I will show you how to ⚡ quickly setup ✏️ Ace editor 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 and is the successor of the Mozilla Skywriter (Bespin) project.
Both Cloud9 IDE and Mozilla are actively developing and maintaining Ace.
👨💻 Let's talk Coding
📁 Create a workspace
Open up your terminal and:
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.
At this point, your folder structure should look like this and it is going to be same till the end:
⏬ Install Ace editor
We will install pre-packaged version of Ace from npm:
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, they have their type definitions files at place:
📄 app.component.ts
Clear all the content of the file and start with below:
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:
- First, we are importing
ace
fromace-builds
package. - Then, we are setting HTML template. Note that
height
andwidth
are required, otherwise editor won't load. I have also added styling, you can skip that if you want. - After above, we are querying our editor using
@ViewChild
-
i. To access queried child of
@ViewChild
, we need to usengAfterViewInit
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
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.
Let's look at the output:
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:
...
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:
As you can see, highlighting and syntax aren't enabled. Let's see if there is any error in browser console:
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, we can get the needed URL:
https://unpkg.com/ace-builds@1.4.12/src-noconflict
Let's update it in our code:
...
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:
✍️ Get value from editor
...
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:
Let's see the output:
Cool, with that we are done 👍
The final version of app.component.ts looks like below:
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
Thank You
for reading my article. Let me know your thoughts in the comments section.
I am also available on twitter as @shhdharmen if you want to say hi 👋.
Top comments (0)