Skip to content

About

A visual form builder for ngx-formly that brings community efforts together. Build Angular forms with drag-and-drop editing, custom components, live previews, and Formly JSON export.

Resources

Contributing

Stars

3 stars

Watchers

0 watching

Forks

Repository files navigation

ngx-formly Builder

A visual form builder for ngx-formly that brings community efforts together. Build Angular forms with drag-and-drop editing, custom components, live previews, and Formly JSON export.

Live demo

Try the builder at builder.formly.dev.

Netlify automatically deploys successful builds of main, including the version commits used for new package releases. The demo can include changes ahead of the latest npm release. See the release checklist for deployment verification.

Project status

The repository is the shared foundation for an official ngx-formly builder. It currently provides the Studio application, reusable editor libraries, multiple UI profiles, local persistence, and authoring documentation.

The project is preparing its first embeddable package contract as @ngx-formly/builder, with companion packages under @ngx-formly/builder-*. No compatibility guarantee is made until the first public prerelease. See CONTRIBUTING.md before proposing public API changes.

The project originated from the community evaluation in ngx-formly discussion #4198. It uses Formly Studio as the initial authoring foundation and will incorporate the strongest engineering and schema workflows from the other community builders.

Name and canonical URLs

The application and documentation use ngx-formly Builder. Studio remains the reference application's source-folder name. The Material UI profile includes the standard controls and the builder's additional fields and layouts. The demo is hosted at builder.formly.dev. Canonical/social metadata and crawler files still reference formlystudio.com, while package homepages and documentation links use docs.formlystudio.com. The repository is ngx-formly/ngx-formly-builder.

When domains change, update both deployments, redirects, canonical/social URLs, sitemaps, crawler files, the docs build's site setting and header links together. Local browser storage is tied to an origin, so provide an export/import migration before a domain move. This branding change preserves all formly-studio-* storage keys and the project's author and provenance attribution.

Development

Use Node.js 24.15 or newer within the Node.js 24 release line and pnpm 10.25.0. The builder uses Angular 22 and Formly 11. PrimeNG 21 and PrimeUIX themes 2 retain their MIT licenses. Because PrimeNG 21 declares Angular 21 peers, Angular 22 consumers currently need the scoped pnpm overrides shown in the package-consumer fixture. Removing this compatibility requirement is a prerequisite for a stable public release.

pnpm install
pnpm dev

pnpm dev starts Studio at http://localhost:4200 and docs at http://localhost:4321. Use pnpm start for Studio alone or pnpm start:docs for docs alone. Studio watches the libraries through the source paths in tsconfig.json; no separate library watchers are needed.

Run pnpm dev:portless to start both apps through Portless, which assigns free ports and provides named URLs at https://builder-studio.ngx-formly.localhost and https://builder-docs.ngx-formly.localhost. On first use, Portless may request administrator access to start its HTTPS proxy and trust its local certificate. Follow the URLs printed in the terminal if you use a custom proxy configuration or a Git worktree. Studio stores forms per browser origin, so export forms from http://localhost:4200 before switching URLs, then import them at the new URL.

The pnpm workspace includes apps/*, libs/*, and libs/ui/*, with one root lockfile. The package-consumer fixture stays outside the workspace so it tests packed libraries in isolation.

Run pnpm test, pnpm run lint, pnpm run check:docs, and pnpm run build to validate changes. The build also verifies that every external library import is declared by its published package, packs the libraries, and builds a clean Angular consumer from those tarballs. After installing Playwright Chromium, run pnpm run check:packages:e2e to check the packaged editor in a browser.

Repository layout

  • apps/studio: hosted reference application.
  • apps/docs: author and integration documentation.
  • libs/state: headless document models, hierarchy operations, and persistence contracts.
  • libs/core: editor shell, UI orchestration, and extension contracts.
  • libs/ui/material: reusable Material runtime fields.
  • libs/ui/builder-material: editor-only adapters for Material composite fields.

Package names

Source Package
libs/core @ngx-formly/builder
libs/state @ngx-formly/builder-state
libs/ui/material @ngx-formly/builder-material-fields
libs/ui/builder-material @ngx-formly/builder-material

The builder name maps to the existing editor shell in libs/core; source directories, build targets, and package boundaries stay the same. It is separate from @ngx-formly/core, the Formly runtime dependency. The reusable Material fields use @ngx-formly/builder-material-fields to distinguish them from the existing @ngx-formly/material adapter. The private app workspaces use @ngx-formly/builder-studio and @ngx-formly/builder-docs. The isolated consumer fixture is @ngx-formly/builder-package-consumer.

Existing consumers must use the package names above in their dependencies and TypeScript imports, and import the stylesheet from @ngx-formly/builder/styles.css. Rebuild and install matching tarballs for all packages. Previous package names have no compatibility aliases. Exported symbols and saved forms are unchanged.

Embedding contract (prerelease)

The Studio route uses the same component and provider intended for embedding. The complete package-consumer fixture runs against npm tarballs without Studio or workspace source imports.

The editor's CSS requires Tailwind 4 and its PostCSS plugin. Install the build dependencies in the consuming application:

npm install tailwindcss tailwindcss-primeui
npm install --save-dev @tailwindcss/postcss postcss

Add .postcssrc.json at the Angular application's root:

{
  "plugins": {
    "@tailwindcss/postcss": {}
  }
}

Import the packaged stylesheet from the application's global CSS:

@layer theme, base, primeng;
@import '@ngx-formly/builder/styles.css';

html,
body,
app-root {
  display: block;
  height: 100%;
  margin: 0;
}

The CSS entry includes Tailwind's base styles, editor styles, PrimeUI utilities, and class scanning for the packaged editor, including its lazy dialogs. It also includes the layout utilities used by the editor's Styling panel. It is Tailwind source CSS, so it must go through PostCSS rather than a browser <link>. Give the builder's container an explicit height if it does not fill the page. UI profiles may need their own styles, such as an Angular Material theme.

Load the Material Symbols Outlined icon font in index.html, as Studio does, or self-host that font with its matching font-face and .material-symbols-outlined rules:

<link
  rel="stylesheet"
  href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0"
/>

Register the PrimeNG theme and any optional UI profiles, then render the builder component:

import { ApplicationConfig, ChangeDetectionStrategy, Component } from '@angular/core';
import { FormlyBuilder, primengPreset, provideFormlyBuilder } from '@ngx-formly/builder';
import { definePreset } from '@primeuix/themes';
import Aura from '@primeuix/themes/aura';
import { providePrimeNG } from 'primeng/config';

@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [FormlyBuilder],
  template: `<formly-builder class="block h-full" />`,
})
export class FormEditorPage {}

export const appConfig: ApplicationConfig = {
  providers: [
    providePrimeNG({
      theme: {
        preset: definePreset(Aura, primengPreset),
        options: {
          darkModeSelector: '.dark',
          cssLayer: { name: 'primeng', order: 'theme, base, primeng' },
        },
      },
    }),
    provideFormlyBuilder({ libraries: [myFormlyLibrary] }),
  ],
};

Use your own profile for myFormlyLibrary. If the host already configures PrimeNG, merge these theme settings into its existing provider. Toggle the .dark class on an ancestor to use dark mode. provideCoreTheme() remains available to hosts that also synchronize the code editor theme.

provideFormlyBuilder accepts an editor storage namespace, autosave settings, and a custom FormStoreService implementation. The API remains provisional until the first public prerelease.

Use provideFormlyBuilder() without profiles for native HTML controls. Leaving UI Library empty when creating or importing a form uses Vanilla: input, number, textarea, checkbox, select, and field groups. Pass shared FormTemplate[] through formTemplates to offer examples that use the selected library. Without this setting, the editor uses the templates configured in each profile.

Document models and persistence APIs can also be consumed without importing the editor UI:

import { createEmptyWorkspaceHierarchy, type FormStoreService } from '@ngx-formly/builder-state';

Custom stores may optionally implement getRecoveryIssues$ and resetCorruptedStorage$. These hooks let the builder show its backup and reset workflow when persisted data cannot be read. Stores that manage recovery outside the builder can omit them.

Recovery backups include each issue's original value and its optional relatedEntries, which hold any other stored values that reset will remove. The local store includes the workspace hierarchy when resetting corrupted forms also removes that hierarchy. Resetting only a corrupted hierarchy preserves the active form's unsaved edits.

Headless editing

@ngx-formly/builder-state provides Angular editing operations without PrimeNG, CDK or the shell. Register provideBuilderEngine in a route or environment injector, then inject BuilderEngineService. Use a different editorType for each independent storage namespace.

import { BuilderEngineService, provideBuilderEngine } from '@ngx-formly/builder-state';

const providers = [provideBuilderEngine({
  editorType: 'survey-designer',
  autoSave: true,
  libraries: [{
    id: 'survey',
    fieldTypes: [{ name: 'input', displayName: 'Input', defaultConfig: {} }],
  }],
})];
// In the configured Angular injection context:
// const engine = inject(BuilderEngineService);
// engine.addForm$('Survey', [], {}, 'survey').subscribe();
// engine.addField('input');
// engine.activePreviewFormFields() contains exported Formly fields.

Autosave defaults to true, with a 3000 ms delay; set autoSave: false for explicit saves. The provider accepts an optional formStore class and autoSaveDelay. It does not register Formly runtime components. Headless hosts render their own controls and register their chosen Formly runtime separately. BuilderFieldStateService holds transient per-field UI state without storage. The engine owns document edits, selection, hierarchy, autosave and recovery. Its formSelected$ event reports completed loads or unloads; the shell uses it to update library and panel selection.

Existing shell consumers keep provideFormlyBuilder and CoreFormService. That provider exposes the same engine and transient field-state instances through the state entry point. Do not also register provideBuilderEngine in the same injector. Storage keys and document formats are unchanged.

See Asynchronous stores and editor lifecycle for custom-store contracts, error handling, and saving before closing the editor.

About

A visual form builder for ngx-formly that brings community efforts together. Build Angular forms with drag-and-drop editing, custom components, live previews, and Formly JSON export.

Resources

Contributing

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages