Skip to content

Extensions overview

All customisation funnels through a single config type, INgxViewBuilderExtensionsConfig, registered either at bootstrap or at runtime.

Registering

At bootstrap (recommended):

ts
import { provideNgxViewBuilderExtensions } from 'ngx-view-builder';

providers: [
  provideNgxViewBuilderExtensions({
    elements: [...],
    expressionFunctions: [...],
    svgIcons: {...},
  }),
]

The provider also accepts a factory (sync or async) — handy when config comes from an API:

ts
provideNgxViewBuilderExtensions(async () => {
  const cfg = await fetch('/api/builder-config').then((r) => r.json());
  return { runtimeVariableContext: cfg.context, svgIcons: cfg.icons };
}),

At runtime:

ts
api.registerExtensions(config);
await api.registerExtensionsAsync(config);   // resolves icon directories etc.

Multiple provideNgxViewBuilderExtensions(...) calls compose — plugins use the same mechanism.

What the config can contain

KeyRegistersDetails
elementscustom element typesCustom elements
elementGroupsnew sidebar groupsid, label, icon, order
expressionFunctionsJEXL functionsCustom functions
globalPropertiesproperties added to every elementCustom properties
elementPropertiesper-type property overrides/additionsCustom properties
svgIcons / svgIconDirectory / svgIconDirectoriesicons by name / from asset foldersIcons
builderTabsextra builder tabsBuilding a plugin
featurePacksbundles of tabs + capabilitiesBuilding a plugin
runtimeVariables / runtimeVariableContextvariables for expressionsRuntime variables
uiDictionariesbuilder UI translationsUI translations
triggers / rules / process / fragmentsautomation definitionsconsumed by the automation plugins

Example — a project preset

ts
provideNgxViewBuilderExtensions({
  elementGroups: [{ code: 'acme', label: 'ACME widgets', icon: 'acmeLogo', order: 10 }],
  elements: [acmeCardElement, acmeRatingElement],
  expressionFunctions: [
    { name: 'vatAmount', args: ['net'], description: 'Adds 21% VAT',
      example: 'vatAmount({netPrice})',
      handler: (net: unknown) => Number(net || 0) * 1.21 },
  ],
  globalProperties: {
    trackingId: { label: 'Tracking ID', type: 'text', category: 'general' },
  },
  svgIcons: { acmeLogo: '<svg ...>...</svg>' },
  runtimeVariableContext: { brand: 'acme' },
});

Everything a creator then sees — the ACME group, the elements, the vatAmount() function, the extra property — comes from this one object.