Angular’s component lifecycle maps cleanly onto init()/destroy(): mount in ngAfterViewInit, once the template’s ViewChild is guaranteed to exist, and tear down in ngOnDestroy.
The editor component
// editor.component.ts
import {
Component,
ElementRef,
ViewChild,
AfterViewInit,
OnDestroy,
} from "@angular/core";
import { init, type EditorHandle } from "@maildeno/editor/init";
import { HttpClient } from "@angular/common/http";
@Component({
selector: "app-email-editor",
standalone: true,
template: `<div #container></div>`,
})
export class EmailEditorComponent implements AfterViewInit, OnDestroy {
@ViewChild("container") containerRef!: ElementRef<HTMLDivElement>;
private handle: EditorHandle | null = null;
constructor(private http: HttpClient) {}
async ngAfterViewInit(): Promise<void> {
this.handle = await init({
container: this.containerRef.nativeElement,
capabilities: { export: ["html", "mjml", "json"] },
onSave: (payload: { templateId: string | null }) => {
console.log("Saved", payload);
const target = handle?.getHtml(); // handle?.getReactEmail() or handle?.getMjml()
console.log(target);
},
onSendTestEmail: async ({ to, subject, html }) => {
await fetch("/api/send-test", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ to, subject, html }),
});
},
});
}
ngOnDestroy(): void {
this.handle?.destroy();
this.handle = null;
}
}
ViewChild isn’t resolved until after the first change-detection pass, which is exactly what AfterViewInit guarantees — mounting any earlier would hit a null container.
A note on zones
@maildeno/editor manages its own internal Vue reactivity inside a shadow root; it doesn’t run through Angular’s change detection, and it doesn’t need to. You generally won’t need NgZone.runOutsideAngular() here — the editor isn’t triggering Angular change-detection cycles on every internal keystroke the way, say, a manually-driven third-party chart redraw might.
Where to go next
-
Storage adapters — persist templates and images through an Angular service
-
Test email integration — the full send-test pattern
-
@maildeno/editorreference — fullEditorHandleAPI