Embed BuilderJS in Angular: the drag-and-drop page builder library
Looking for an Angular page builder library you can self-host and own outright? BuilderJS is a framework-agnostic, vanilla-JavaScript drag-and-drop editor for HTML email and landing pages that drops into any Angular component. It is not an npm package and has no module export — you load it as a global browser script that attaches window.Builder, then instantiate it inside your component's mount hook. This guide shows the exact, copy-paste mount pattern: render three container divs in your template, declare the global, and call new Builder() with CSS-selector strings in ngAfterViewInit. BuilderJS is purely the in-browser editor you embed — it builds and exports the markup; you bring your own sending, hosting, and publishing. It ships under a one-time CodeCanyon license (Regular $52 / Extended $99) with full source you self-host: no SaaS, no monthly fee, no per-seat pricing.
Mount it
import { Component, AfterViewInit } from '@angular/core';
// The global /builderjs/builder.js script attaches window.Builder.
// There is no npm package and no named export to import.
declare global {
interface Window { Builder: any; }
}
@Component({
selector: 'app-builder',
template: `
<div id="bjs-widgets"></div>
<div id="bjs-canvas"></div>
<div id="bjs-settings"></div>
`,
})
export class BuilderComponent implements AfterViewInit {
private builder: any;
ngAfterViewInit(): void {
if (this.builder) return; // instantiate exactly once
this.builder = new window.Builder({
mainContainer: '#bjs-canvas', // required, a CSS selector string
widgetsContainer: '#bjs-widgets',
settingsContainer: '#bjs-settings',
});
this.builder.load(themeJson, themeTemplatesJson, themeConfigData, mediaUrl);
// save: const json = this.builder.getData(); POST json to your backend
// no destroy(): Angular discards the container DOM node on unmount
}
}
Load BuilderJS as a global script, not an npm import
BuilderJS ships as a compiled browser bundle, not an ES module. Add the stylesheet and script to your index.html (or the angular.json scripts/styles arrays): <link rel="stylesheet" href="/builderjs/builder.css"> and <script src="/builderjs/builder.js"></script>. Loading the script attaches a single global, window.Builder. There is no named export, so never write import { Builder } from 'builderjs' — that module does not exist and will fail to resolve. Inside your TypeScript component, tell the compiler the global exists by declaring it on the Window interface (declare global { interface Window { Builder: any } }) and reference it as window.Builder. The constructor signature is new window.Builder({ mainContainer, widgetsContainer, settingsContainer }) where every option is a CSS selector string (for example '#bjs-canvas'), not a DOM node and not an Angular ViewChild ElementRef. mainContainer is required; the other two are optional sidebars.
Mount client-side inside ngAfterViewInit
BuilderJS is a DOM-mount bundle: it queries the selectors you pass and renders the editor into those live elements. That means it can only run in the browser, after Angular has painted the component's template — never during server-side rendering. Instantiate it in ngAfterViewInit, the hook that fires once the view's DOM exists. Your component template must render the three container nodes the editor mounts into: <div id="bjs-widgets"></div>, <div id="bjs-canvas"></div>, and <div id="bjs-settings"></div>. Pass those same ids as selector strings to the constructor. If you use Angular Universal/SSR, guard the instantiation behind a platform check (isPlatformBrowser) so it only runs in the browser. The selectors must resolve to elements that are already in the DOM by the time ngAfterViewInit runs.
Load a theme and persist with getData() / load()
After construction, populate the canvas by calling builder.load(themeJson, themeTemplatesJson, themeConfigData, mediaUrl) — exactly four positional arguments, in that order. themeJson is the page tree, themeTemplatesJson maps template names to HTML, themeConfigData holds fonts/colors/sizes, and mediaUrl is the base URL for relative asset paths. To save the user's work, call const json = builder.getData() and POST that JSON to your own backend route. To restore a saved design later, feed it straight back through builder.load(...) as the first argument. BuilderJS itself does no sending, hosting, or publishing — getData() hands you the editor state and the exported markup, and your application owns storage and delivery from there.
No destroy() — instantiate exactly once
BuilderJS has no destroy(), teardown(), or dispose() method, so never call builder.destroy(). When Angular tears down the component, the framework removes the host container DOM node and the editor goes with it — there is nothing to dispose manually. The only thing to manage is not constructing it twice. In plain Angular this is straightforward because ngAfterViewInit runs once per component instance, but if you share the React-style double-invoke concern (or hot-reload during development), guard instantiation with a boolean flag on the component so new window.Builder() runs exactly once. Hold the instance in a class field if you need to call getData() or load() again later.
Frequently asked questions
-
Is there an npm package or an import for BuilderJS in Angular?
No. BuilderJS is a global browser script, not an npm module. You add builder.js and builder.css to your page (via index.html or angular.json), which attaches window.Builder. There is no named export, so import { Builder } from '...' is wrong. In TypeScript, declare the global on the Window interface and reference it as window.Builder.
-
Where should I instantiate the builder in an Angular component?
In ngAfterViewInit, which fires after the template's DOM exists. BuilderJS is a client-side DOM-mount bundle that queries your selector strings, so the three container divs must be rendered first. It cannot run during server-side rendering; under SSR, guard it with isPlatformBrowser.
-
How do I save and reload a design?
Call const json = builder.getData() and POST that JSON to your backend. To restore it, pass it back as the first argument of builder.load(themeJson, themeTemplatesJson, themeConfigData, mediaUrl) — four positional arguments in that order. Your app owns storage; BuilderJS only produces the editor state and markup.
-
Should I call builder.destroy() when the component unmounts?
No — there is no destroy() method. When Angular destroys the component it discards the container DOM node and the editor with it. The only thing to manage is constructing the builder exactly once; guard with a flag if hot-reload or double-invoke could re-run your mount code.
-
Does BuilderJS send emails or host pages, and how is it licensed?
No. BuilderJS is only the embeddable editor — it builds and exports HTML for email and pages; you bring your own sending, hosting, and publishing. It is sold under a one-time CodeCanyon license (Regular $52 / Extended $99) with full source you self-host: no SaaS, no monthly fee, no per-seat charges.