
Build Table
- 14 installs
- 293 repo stars
- Updated August 4, 2026
- sap/fundamental-ngx
Helps with ai & agent building tasks.
About
build-table is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- build-table
- AI & Agent Building
- AI-coding skill
Build Table by the numbers
- 14 all-time installs (skills.sh)
- Ranked #11,296 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/sap/fundamental-ngx --skill build-tableAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 14 |
|---|---|
| repo stars | ★ 293 |
| Last updated | August 4, 2026 |
| Repository | sap/fundamental-ngx ↗ |
What it does
Helps with ai & agent building tasks.
Files
Build Table: $ARGUMENTS
If $ARGUMENTS is empty, ask: (1) what data the table displays, (2) which features are needed.
Phase 1: Determine Scope
Parse from $ARGUMENTS or ask:
- Table name (PascalCase, e.g.,
Users,Orders) - Data model: field names + TypeScript types (used for column definitions and the data interface). If not provided in
$ARGUMENTS, ask explicitly: "What columns should the table have? Please list field name and type, e.g.:id:number, customerName:string, status:string" - Base component:
fdp-table(platform, feature-rich — default) |fd-table(core, markup-level, use only for purely presentational tables) - Features (check all that apply):
sort— sortable column headersfilter— per-column or global search filterpaginate— page size picker + page navigationselect— row selection (single|multiple)toolbar— title bar with action buttons- Data source: static array | observable | HTTP service (lazy)
Default to fdp-table with sort + paginate unless the user specifies otherwise.
Phase 2: Gather Component Context
Call the @fundamental-ngx/mcp MCP server:
1. get_usage_guide('table') — DataSource patterns, variant decision tree, pitfalls 2. get_component_api('fdp-table') — all inputs/outputs, selection mode options, page size inputs 3. If filter requested: get_component_api('fdp-table-toolbar') for filter toolbar wiring 4. If custom cell rendering needed: look for fdpTableCell template directive API
If MCP is unavailable, read libs/mcp-server/src/data/usage-guides.ts.
Phase 3: Present Plan
Output this summary before writing any code:
## Table Plan: [TableName]
**Component:** fdp-table
**DataSource type:** FdpTableDataSource (wraps observable)
**Features:** sort ✓ | filter ✓ | paginate ✓ | select(multiple) ✓
| Column key | Label | Type | Sortable | Filterable | Width |
|------------|-------|------|----------|------------|-------|
| name | Name | string | yes | yes | auto |
| status | Status | string | yes | yes | 120px |
| createdAt | Created | date | yes | no | 160px |
**Toolbar actions:** Add, Delete selectedStop here and wait for approval before generating code.
Phase 4: Generate Component
Create three files in the target path (ask the user if not already known).
TypeScript (.component.ts)
import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import {
TableComponent,
TableColumnComponent,
TableToolbarComponent,
TableToolbarActionsComponent,
TableP13DialogComponent
} from '@fundamental-ngx/platform/table';
// FdpTableDataSource is a type alias only — use the concrete class from table-helpers:
import {
ArrayTableDataSource, // for static arrays
ObservableTableDataSource, // for observables
TableInitialStateDirective, // REQUIRED — initializes state.columns from column definitions
TableRowSelectionChangeEvent
} from '@fundamental-ngx/platform/table-helpers';
// NOTE: PlatformTableModule is deprecated — always import individual components above.
export interface [Name]Row {
// map data model fields here
id: number;
}
@Component({
selector: 'app-[kebab-name]-table',
templateUrl: './[kebab-name]-table.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [TableComponent, TableColumnComponent, TableToolbarComponent, TableToolbarActionsComponent, TableP13DialogComponent,
TableInitialStateDirective]
})
export class [Name]TableComponent {
readonly dataSource = new ArrayTableDataSource<[Name]Row>(this._getData());
readonly selectedRows = signal<[Name]Row[]>([]);
onRowSelectionChange(event: TableRowSelectionChangeEvent<[Name]Row>): void {
this.selectedRows.set(event.selection);
}
add(): void {
// TODO: open a dialog or navigate to an add form
}
deleteSelected(): void {
// TODO: call your service to delete this.selectedRows()
this.selectedRows.set([]);
}
private _getData(): [Name]Row[] {
// Replace with your observable or HTTP call:
// return this._service.getItems();
return [];
}
}HTML Template (.component.html)
<fdp-table
[dataSource]="dataSource"
selectionMode="multiple"
[pageSize]="25"
(rowSelectionChange)="onRowSelectionChange($event)"
>
<fdp-table-toolbar title="[TableName]" [hideItemCount]="false">
<fdp-table-toolbar-actions>
<button fd-button fdType="emphasized" (click)="add()">Add</button>
@if (selectedRows().length > 0) {
<button fd-button fdType="negative" (click)="deleteSelected()">Delete ({{ selectedRows().length }})</button>
}
</fdp-table-toolbar-actions>
</fdp-table-toolbar>
<fdp-column name="name" key="name" label="Name" [sortable]="true" [filterable]="true"> </fdp-column>
<!-- repeat fdp-column for each field -->
<fdp-table-p13-dialog></fdp-table-p13-dialog>
</fdp-table>SCSS (.component.scss)
Leave empty — table layout is handled by fundamental-styles. Add rules only for host-level sizing (e.g., height: 100%).
DataSource Patterns
Choose based on data origin:
| Source | Pattern |
|---|---|
| Static array | new ArrayTableDataSource(myArray) — from @fundamental-ngx/platform/table-helpers |
| Observable | new ObservableTableDataSource(myObservable$) — from @fundamental-ngx/platform/table-helpers |
| HTTP (lazy, server-side sort/filter) | Implement TableDataSource<T> interface — override fetch(tableState) |
For server-side sorting/filtering, implement TableDataSource<T>:
export class [Name]DataSource extends TableDataSource<[Name]Row> {
fetch(tableState?: TableState): Observable<[Name]Row[]> {
const { sortBy, filterBy, page } = tableState ?? {};
return this._service.query({ sortBy, filterBy, page });
}
}Critical Rules
- `TableInitialStateDirective` is required — import it from
@fundamental-ngx/platform/table-helpersand add it to the component'simportsarray. Its selector matchesfdp-tableand it initializesstate.columnsfrom the column definitions before the first render. Without it,state.columnsstays[]and the table shows "Right now, there are no visible columns." even though thefdp-columnelements are correctly declared. - Import individual components, not `PlatformTableModule` —
PlatformTableModuleis deprecated and cannot be statically resolved in a standalone component'simportsarray. Always importTableComponent,TableColumnComponent,TableToolbarComponent,TableToolbarActionsComponent, andTableP13DialogComponentdirectly from@fundamental-ngx/platform/table. - `FdpTableDataSource` is a type alias, not a class — it lives in
@fundamental-ngx/platform/table-helpersand is exported underexport type. UseArrayTableDataSourcefor static arrays orObservableTableDataSourcefor observables; both are in@fundamental-ngx/platform/table-helpers. - `TableRowSelectionChangeEvent` is from `table-helpers` — import it from
@fundamental-ngx/platform/table-helpers, not@fundamental-ngx/platform/table. - There are no `fdpTableSortable` / `fdpTableFilterable` directives — sort and filter are activated solely by
[sortable]="true"and[filterable]="true"on eachfdp-column. No extra directive goes on<fdp-table>. - `[pageSizeOptions]` does not exist —
[pageSize]is the only pagination input on<fdp-table>. There is no per-page picker input. - `fdp-table-p13-dialog` is required — without it, the column personalization panel and the sort/filter apply buttons do not render; include it inside
<fdp-table>even when not explicitly requested - `name` and `key` are both required on `fdp-column` —
nameis the unique identifier (camelCase),keymaps to the data row's property path; they can be identical - Do NOT pass a `BehaviorSubject` directly — wrap it:
new ObservableTableDataSource(subject.asObservable()); passing a subject directly causes double-subscription issues - `selectionMode` is a string input — values:
'single'|'multiple'|'none'; do not use[selectionMode]="SelectionMode.Multiple"enum binding unless you import the enum - Bundle budget — adding
@fundamental-ngx/platformincreases the initial bundle to ~4.6 MB. In a standalone app raise the budget inangular.jsontomaximumWarning: "5MB", maximumError: "8MB". - Custom cell templates use `fdpTableCell` structural directive —
<ng-template fdpTableCell let-row>{{ row.date | date }}</ng-template>inside thefdp-column - Do NOT add
standalone: true— default since Angular 19 - Do NOT use
*ngIf/*ngForin templates — use@if/@for
Phase 5: Validate
# NX monorepo
nx run <project>:build
# Standalone Angular CLI app
ng build # or: npm run buildReplace the empty _getData() return with at least a small static array and confirm the table renders with column headers before reporting done.
Output
## Build Table: [TableName]
**Files generated:**
- src/app/.../[kebab-name]-table.component.ts
- src/app/.../[kebab-name]-table.component.html
- src/app/.../[kebab-name]-table.component.scss
**Imports required in parent:**
- `import { [Name]TableComponent } from './[kebab-name]-table/[kebab-name]-table.component'`
- Note: `TableInitialStateDirective` is declared inside the generated component — no additional parent import needed
**Features implemented:** sort ✓ | filter ✓ | paginate(25/page) ✓ | select(multiple) ✓
**Next steps:**
- [ ] Replace static array in _getData() with your real service call
- [ ] Add custom cell templates (fdpTableCell) for date/currency/status columns
- [ ] For >10k rows: implement server-side TableDataSource with fetch() method
- [ ] Add row-level action column if inline edit/delete is needed