Empower your Angular applications with a flexible, scalable plugin ecosystem! 🚀
The most successful web platforms —like WordPress, Nextcloud, or Drupal— thrive because of their massive plugin ecosystems. They make it effortless to extend functionality without touching the core.
In the Angular & TypeScript world, achieving this level of modularity has always been a challenge. ng-xtend was built to bridge that gap. It allows you to build "extensible by design" applications where external teams can contribute features seamlessly.
ng-xtend is an Angular library that enables you to:
- 🧩 Define once, render anywhere: Focus on your data structures; let the plugins handle the UI.
- ⚡ Dynamic Loading: Load and install plugins at runtime—no rebuild required.
- 💾 Storage Agnostic: Save, load, and update data to any backend or storage.
- 🔌 Seamless Interop: Plugins work together intelligently, even without knowing each others.
A real-world example of an app handling complex data (lists, views, and editions) entirely through dynamic plugins.
To better understand the real-world usage of ng-xtend, we've developed a set of example projects, in the ng-xtend examples repository.
Here is a short description of each one:
| Example | Description |
|---|---|
| basic-example | Displays any object in various format in a generic way |
| typed-example | By describing the type handled, ng-xtend supports more use cases |
| plugin-example | Countries and Money fields looks nicer thanks to the newly added plugins. They are discovered and used transparently by the ng-xtend framework |
| inout-example | A full list / edit / view flow is setup thanks to inputs / outputs connecting unknown components together. |
| store-example | Edited elements are persisted between sessions thanks to the xt-store library included with the ng-xtend framework. |
| advanced-type-example | Showcase support for advanced types and models (like references) |
| dynamic-example | Loads all plugins dynamically from another website using Native-Federation |
Curious about how plugins are dynamically injected? Try the dedicated tester:
Currently, ng-xtend supports four major extension points:
| Type | Description |
|---|---|
| Simple Components | Turn regular Angular components into pluggable units for specific data types. |
| Complex Components | Components that provide their own extension points. Example: A "Money" plugin delegating "Currency" selection to another plugin. |
| List Components | Effortlessly display collections of objects by delegating item rendering to the right plugins. |
| Action Handlers ✨ | Add logic and actionable buttons to your UI dynamically. |
The host application doesn't need to know its plugins at compile time. It simply sets Render Points (xt-render):
- Configuration: A simple JSON file defines which plugins to load from which remote URLs.
- Registration: Upon loading, the plugin registers itself and declares which data types or actions it supports.
- Resolution: When ng-xtend encounters a specific type (e.g.,
Rating,Currency), it automatically finds and injects the correct component from the loaded plugins.
- Dynamic insertion of simple components
- Plugin registry system
- Support for complex components and lists
- Strong type support
- Remote dynamic loading
- Action components support
- v1.0 Release! 🏁
- Enhanced component selection (context-aware)
- v2.0 & beyond
We use a monorepo structure powered by Rush.
npm install -g @microsoft/rush
rush update
rush build- 2026-01-27: Added repository with multiple examples of ng-xtend usage. => ng-xtend-examples
- 2026-01-04: Version 0.5.5, supports for many to one references
- 2025-11-02: Added support for actions, allowing plugins to add features dynamically, and added the agenda plugin, with support for recurrent tasks
- 2025-09-06: Version 0.5, moved to Angular 20.2, added country selection plugin.
- 2025-08-24: Published of apps developed: Dashboard
- 2025-07-14: First release, with support for dynamic plugins (thanks to Angular architects!) and a few plugins for Financial, Web and International applications. As well, added a default plugin to edit any data.
Here are screenshots of an application automatically handling list, view and edition of complex data (evaluations of coffee beans) using ng-xtend, a dont-code application{target="_blank"}, and the default plugin and web plugin
You can see how the different plugins work together without knowing each other. Even the host application does not know them.
- Checkout the repository ng-xtend{target="_blank"}
- It's a monorepo using rush build system, so run
npm install -g @microsoft/rush
rush update
rush build-
Use a copy of libs/xt-plugin-sample to develop your own plugins and components.
-
Unit test your components using vitest
- ng-xtend provides pre-defined test pages for different cases (in a form or not) that will easily embed your component for testing
- See currency simple component test{target="_blank"}
- Or money complex component test{target="_blank"}
-
Test your components using plugin-tester
- More details in plugin-tester user documentation.
- Run your plugin tester application, for example
ng serve sample-testerfor the sample plugin - Run the xt-plugin-tester with
ng serve plugin-testerin xt-plugin-tester directory - In the Plugin Tester app, load your plugin by entering its url (http://localhost:4201 for sample plugin) in the Plugin url field.
- Once loaded, go to the test screen, select your component in the second screen, and play with it
- For easier debugging, you can statically add and register your plugin to xt-plugin-tester/package.json{target="_blank"}
To use ng-xtend plugins in your own Angular Application, xt-host project is a great example. It does:
- Install xt-components and the default plugin in your package.json
npm install xt-components xt-type xt-store
npm install xt-plugin-default- Configure your application to load your plugins.
protected resolverService = inject (XtResolverService);
this.resolverService.loadPlugin(url);The plugins will register themselves automatically.
- Describe the data type you want to manipulate
this.resolverService.registerTypes ({
money:{
amount:'number',
currency:'currency' /** Type provided by the finance plugin **/
},
book: {
name:'string',
publication:'date',
price:'money',
notation:'rating' /** Type provided by the web plugin **/
}
}); - Sets insertion point in your angular pages
- For example, to display a table of books
<h1>List of books</h1>
<xt-render [displayMode]="LIST_VIEW" [valueType]="book" [value]="listOfBooks" ></xt-render> - or allow editing a book information
<h1>Enter your book details</h1>
<div form="bookForm">
<xt-render [displayMode]="FULL_EDITABLE" [valueType]="book" [formGroup]="bookForm" subName="book"></xt-render>
</div> - To support more complex scenario, use
<xt-render-sub [context]="context()"></xt-render-sub>with `context ()` returning type information necessary to select the right component.
Please check my other project Dont-code{target="_blank"}, it will soon run using ng-xtend ! Email: contact@ng-xtend.dev or developer@dont-code.net




