Skip to content
Skills Library
Programming · Building & coding

extend-angular-module-ui

/extend-angular-module-ui

Extend a shipped ABP Angular module's UI (Identity, etc.) through the extension system — add row/toolbar actions, columns, and create/edit form fields without forking. USE FOR: the five contributor buckets (entity/toolbar-action, entity-prop, create/edit-form-prop contributors) keyed by the module's component enum; the EntityAction/ToolbarAction/EntityProp/FormProp factories; ePropType; the LinkedList mutators addTail/addByIndex/addAfter/dropByIndex (there is no patch/remove/insertByIndex — patch is drop-plus-reconstruct); registering via createRoutes in a lazy loadChildren (or the deprecated

Repository
abp-skills ↗
Licence
MIT
Last repository change
05.10.2026

Assessment and security

100/ 100Class: good
Format25 / 25
Frontmatter with name and description, valid name, description up to 1,024 characters, name matching the folder.
Discoverability25 / 25
Description explains when to use the skill, has a reasonable length and uses third person.
Content35 / 35
At least 150 words and at most 500 lines, headings, step lists, examples or code.
Hygiene15 / 15
No placeholders such as TODO, no Windows paths, with a licence.
Riskno signals detected in the scan
Files in this package
1
Scripts
0
HTML comments
0
URLs in SKILL.md
0
Deprecation

No signals detected. Repository changed on 05.10.2026, without references to retired models or APIs.

Licence

MIT, open: use and modify while retaining author attribution.

What it does and when to use it

Extend a shipped ABP Angular module's UI (Identity, etc.) through the extension system — add row/toolbar actions, columns, and create/edit form fields without forking. USE FOR: the five contributor buckets (entity/toolbar-action, entity-prop, create/edit-form-prop contributors) keyed by the module's component enum; the EntityAction/ToolbarAction/EntityProp/FormProp factories; ePropType; the LinkedList mutators addTail/addByIndex/addAfter/dropByIndex (there is no patch/remove/insertByIndex — patch is drop-plus-reconstruct); registering via createRoutes in a lazy loadChildren (or the deprecated

Original author description

Extend a shipped ABP Angular module's UI (Identity, etc.) through the extension system — add row/toolbar actions, columns, and create/edit form fields without forking. USE FOR: the five contributor buckets (entity/toolbar-action, entity-prop, create/edit-form-prop contributors) keyed by the module's component enum; the EntityAction/ToolbarAction/EntityProp/FormProp factories; ePropType; the LinkedList mutators addTail/addByIndex/addAfter/dropByIndex (there is no patch/remove/insertByIndex — patch is drop-plus-reconstruct); registering via createRoutes in a lazy loadChildren (or the deprecated

How it works

  1. When to Use
  2. When Not to Use
  3. The five contributor buckets
  4. Building items and mutating the list
  5. Registering the contributors
  6. Validation
  7. Common Pitfalls
Original SKILL.md headings · 106 lines, 659 words
SKILL.md preview
---
name: extend-angular-module-ui
description: >
  Extend a shipped ABP Angular module's UI (Identity, etc.) through the extension system — add row/toolbar actions, columns, and create/edit form fields without forking.
  USE FOR: the five contributor buckets (entity/toolbar-action, entity-prop, create/edit-form-prop contributors) keyed by the module's component enum; the EntityAction/ToolbarAction/EntityProp/FormProp factories; ePropType; the LinkedList mutators addTail/addByIndex/addAfter/dropByIndex (there is no patch/remove/insertByIndex — patch is drop-plus-reconstruct); registering via createRoutes in a lazy loadChildren (or the deprecated Module.forLazy); EXTENSIONS_IDENTIFIER; the @abp/ng.components/extensible package.
  DO NOT USE FOR: building your own non-module list/form (build-angular-lists-and-forms); proxy consumption, menus, permission directives, replaceable components (angular-ui); adding server-side extra properties to the entity/DTO (extend-objects-with-extra-properties); component testing (test-angular-ui).
license: MIT
---

# Extend Angular Module UI (ABP)

ABP's shipped Angular modules (Identity, Tenant Management, …) expose their grids and create/edit forms to a **contributor** system so you can add actions, columns, and fields without forking the module. Models write these by hand or fork the component; the extension API is the supported path.

## When to Use

- Adding a row action, toolbar button, extra column, or extra create/edit field to a **shipped module's** page.
- Reordering or replacing an existing column/field on such a page.

## When Not to Use

- **Your own feature's list/form** (not a shipped module) — use **build-angular-lists-and-forms**.
- **Proxies, menus, permission directives, replaceable components** — use **angular-ui**.
- **Persisting the extra field on the backend** (the entity/DTO side) — use **extend-objects-with-extra-properties**; the UI contributor only renders it.
- **Testing** — use **test-angular-ui**.

## The five contributor buckets

Each module exposes a typed options object with five buckets, keyed by that module's **component enum**. Identity's, for example:

```ts
import { eIdentityComponents } from '@abp/ng.identity';
import { IdentityEntityActionContributors, IdentityEntityPropContributors } from '@abp/ng.identity';

export const identityEntityActionContributors: IdentityEntityActionContributors = {
  [eIdentityComponents.Users]: [ /* contributor callbacks */ ],
};
```

The buckets are `entityActionContributors` (row actions), `toolbarActionContributors` (page toolbar buttons), `entityPropContributors` (data-table columns), `createFormPropContributors` and `editFormPropContributors` (form fields — create and edit are separate). A contributor is a callback that receives the current list and mutates it.

## Building items and mutating the list

Items come from factories in `@abp/ng.components/extensible`: `EntityAction`, `ToolbarAction`, `EntityProp` (a column), `FormProp` (a field). Column/field types use the `ePropType` enum (`String`, `Boolean`, `Date`, `DateTime`, `Email`, `Enum`, `Number`, `Password`, `Text`, `Time`, `Typeahead`, …).

The list passed to a contributor is a **doubly-linked list**, so you position items explicitly:

```ts
import {
  EntityAction, EntityActionList,
  EntityProp, EntityPropList,
  FormProp, FormPropList, ePropType,
} from '@abp/ng.components/extensible';
import { IdentityUserDto } from '@abp/ng.identity/proxy';
import { Validators } from '@angular/forms';

// row action -> appended to the row dropdown
export function sayHi(actionList: EntityActionList<IdentityUserDto>) {
  actionList.addTail(new EntityAction<IdentityUserDto>({
    text: 'Say Hi',
    action: data => alert(data.record.userName),   // text + action are required
  }));
}

// custom column -> inserted right after userName
export function nameColumn(propList: EntityPropList<IdentityUserDto>) {
  propList.addAfter(
    new EntityProp<IdentityUserDto>({ type: ePropType.String, name: 'name', displayName: '::Name', sortable: true }),
    'userName',
    (value, name) => value.name === name,
  );
}

// create-form field -> inserted at index 4
export function birthday(propList: FormPropList<IdentityUserDto>) {
  propList.addByIndex(
    new FormProp<IdentityUserDto>({ type: ePropType.Date, name: 'birthday', displayName: '::Birthday', validators: () => [Validators.required] }),
    4,
  );
}
```

Mutators: `addTail` / `addHead` / `addByIndex(item, position)` / `addAfter(item, sibling, compareFn)` / `addBefore` / `add(item).byIndex(n)`, and the `dropByIndex` / `dropByValue` family. There is **no** `patch`, `remove`, or `insertByIndex` — to "patch" an existing column, `dropByIndex(i)` it, then re-add a `new EntityProp({ ...droppedNode.value, valueResolver })`.

## Registering the contributors

In the current standalone setup, pass the buckets to the module's `createRoutes(options)` in the lazy route:

```ts
{
  path: 'identity',
  loadChildren: () => import('@abp/ng.identity').then(c => c.createRoutes({
    entityActionContributors: identityEntityActionContributors,
    entityPropContributors: identityEntityPropContributors,
    createFormPropContributors: identityCreateFormPropContributors,
  })),
}
```

(The legacy NgModule path, `IdentityModule.forLazy(options)`, takes the same options object but is deprecated.) Each page binds its bucket via the `EXTENSIONS_IDENTIFIER` token it provides.

For `@volo/abp.ng.*` module UIs, follow that module's own documentation for its UI extension APIs.

## Validation

- Add a column and confirm it renders in the grid at the position you chose and sorts if `sortable`.
- Add a create-form field and confirm it appears in the modal, validates, and round-trips (with the backend extra-property wired separately).

## Common Pitfalls

- **Inventing `patch` / `remove` / `insertByIndex`.** They don't exist. Use `dropByIndex` + re-add for patch, the `drop*` family for remove, `addByIndex` / `add().byIndex()` for insert-at-index.
- **Wrong bucket for create vs edit.** Create and edit forms have separate buckets; adding to only one leaves the other unchanged.
- **Expecting the column to persist data.** The UI contributor renders a value; the entity/DTO extra property is a backend concern — see **extend-objects-with-extra-properties**.
- **Building your own feature's grid here.** That's **build-angular-lists-and-forms**; this skill is only for extending *shipped* modules' pages.

Versions

The database has no other skills named extend-angular-module-ui.

Database snapshot: 13.11.2026 · package version 6e30297cd576 (SHA-256 digest of the entire package)

Downloads in the last 30 days: 0 · ranking

Report a problem with this skill: harmful content, incorrect descriptions or an author’s removal request.

Similar skills

  • 100angular
    Show how to use custom elements in Angular, including required CUSTOM_ELEMENTS_SCHEMA configuration. Use when the user asks to "use in Angular", "Angular custom elements", "custom elements in Angular", "CUSTOM_ELEMENTS_SCHEMA", or mentions "Angular module", "standalone…
  • 100extend-application-shell
    Extend the ABP application shell/layout across MVC and Blazor with layout hooks, global/page toolbars, the page header, and branding — without copying the theme layout. USE FOR: injecting content into the layout via AbpLayoutHookOptions + LayoutHooks (MVC ViewComponent hooks;…
  • 100angular-architecture
    Standards for Angular project structure, feature modules, and lazy loading. Use when structuring Angular apps, defining feature modules, or configuring lazy loading.
  • 100abp-ui
    ABP Framework v10.x (10.4–10.6) UI: MVC/Razor Pages (AbpPageModel), Blazor (AbpComponentBase), Angular, React (--modern), theming (LeptonX), menu contributor, dynamic proxy. Use when developing frontend, UI, pages, or components in ABP.
  • 100abp-ui
    ABP Framework v10.x (10.4–10.6) UI: MVC/Razor Pages (AbpPageModel), Blazor (AbpComponentBase), Angular, React (--modern), theming (LeptonX), menu contributor, dynamic proxy. Use when developing frontend, UI, pages, or components in ABP.
  • 85{setup-skill-name}
    Sets up {module-name} module in a project. Use when the user requests to 'install {module-code} module', 'configure {module-name}', or 'setup {module-name}'.

Feedback and reports

Your message goes to Bartosz Sokoliński. An email address is needed only for a reply. See the privacy policy.