ngx-ace-signal is a modern Angular signals-based wrapper for the Ace Editor.
It is designed for Angular 20+, supports SSR, and avoids legacy patterns like NgModule, @Input(), or global side effects.
- ✅ Angular signals API (
input(),model(),output()) - ✅ SSR-safe − Ace is only loaded in the browser
- ✅ Dynamic mode & theme loading
- ✅ Component and directive APIs
- ✅ Fully typed config (
AceConfigInterface) - ✅ Works with standalone apps
Example application (GitHub Pages): 👉 https://ace.webart.work
npm install ngx-ace-signal<ace [(value)]="code" [mode]="'javascript'" [theme]="'github'"></ace>code = `console.log("Hello Ace");`;| Input | Type | Default | Description |
|---|---|---|---|
value |
string |
"" |
Editor content (two-way via model()) |
mode |
"text" | "javascript" | string |
"" |
Editor mode |
theme |
"github" | "clouds" | string |
"" |
Editor theme |
disabled |
boolean |
false |
Disables editor |
readOnly |
boolean |
false |
Read-only mode |
config |
AceConfigInterface |
undefined |
Advanced Ace options |
useAceClass |
boolean |
true |
Toggles .ace host class |
<ace (change)="onChange($event)" (focus)="onFocus()" (blur)="onBlur()"></ace>Supported events:
blurfocuscopypastechangechangeCursorchangeSessionchangeSelection
<div ace [mode]="'text'" [theme]="'clouds'" [config]="options">initial text</div>Access the editor API via template reference:
<div ace #editor="ngxAce"></div>editor.ace()?.setValue('Hello');Use provideAce() to define defaults once:
import { provideAce } from 'ngx-ace-signal';
bootstrapApplication(AppComponent, {
providers: [
provideAce({
showLineNumbers: true,
useWorker: false,
}),
],
});You can extend supported modes/themes without touching the library:
import { registerAceMode, registerAceTheme } from 'ngx-ace-signal';
registerAceMode('json', () => import('ace-builds/src-noconflict/mode-json'));
registerAceTheme('monokai', () => import('ace-builds/src-noconflict/theme-monokai'));Then use them normally:
<ace mode="json" theme="monokai"></ace>- Ace is never imported on the server
- All loading happens behind
isPlatformBrowser - Safe to use in Angular Universal / SSR apps
No special setup required.
All supported options are defined in:
AceConfigInterface;This is a thin typed layer over Ace’s native configuration. For full option details, see the official Ace documentation:
ace-builds is CommonJS.
Consumer apps should add:
"allowedCommonJsDependencies": ["ace-builds"]This is expected and documented.
Copy below code into AGENTS.md file of your project while you are using our plugin.
## ngx-ace-signal
- This project uses `ngx-ace-signal`, an Angular 20+ Ace Editor wrapper built around signals and standalone APIs.
- Prefer importing `AceComponent` for `<ace>` usage or `AceDirective` for `[ace]` usage directly into standalone components instead of creating wrapper `NgModule`s.
- Use signal-style bindings that match the library API:
- Two-way content binding is `[(value)]`.
- Inputs include `[mode]`, `[theme]`, `[disabled]`, `[readOnly]`, and `[config]`.
- Outputs include `(change)`, `(focus)`, `(blur)`, `(copy)`, `(paste)`, `(changeCursor)`, `(changeSession)`, and `(changeSelection)`.
- When app-wide defaults are needed, configure them with `provideAce({...})` in application providers instead of duplicating editor config in many components.
- Do not import Ace directly in app code unless there is a documented reason. Prefer the library helpers `registerAceMode()` and `registerAceTheme()` to load extra modes/themes.
- If a feature needs a new mode or theme, register it explicitly, for example:
registerAceMode('json', () => import('ace-builds/src-noconflict/mode-json'));
registerAceTheme('monokai', () => import('ace-builds/src-noconflict/theme-monokai'));
- Keep SSR-safe behavior intact. Do not add server-side imports of `ace-builds`; the library already guards browser-only loading.
- If build tooling warns that `ace-builds` is CommonJS, allow it in Angular build config via `allowedCommonJsDependencies` rather than replacing the editor integration.
- When changing editor behavior, prefer passing options through `config` or `provideAce()` before modifying the library itself.
- If you need direct editor access, use a template ref with `#editor="ngxAce"` and then call `editor.ace()` rather than querying DOM globals.MIT © Web Art Work