sap/fundamental-ngx

build-table

Build a @fundamental-ngx/platform data table with FdpTableDataSource, sorting, filtering, pagination, and row selection

First seen May 21, 2026

Installation

$ npx skills add sap/fundamental-ngx --skill build-table

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from sap/fundamental-ngx · top by installs.

npx skills add sap/fundamental-ngx

Browse all from sap/fundamental-ngx

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 294
License LICENSES
Default branch main
Open issues 113
Status Active

Skill metadata

Parsed from SKILL.md frontmatter.

Allowed toolsRead, Grep, Glob, Bash(nx *), Bash(ng build*), Write, Edit

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 10,829 B
  • docs SUMMARY.md 138 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 24 installs

SKILL.md

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 headers - filter — per-column or global search filter - paginate — page size picker + page navigation - select — 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. getusageguide('table') — DataSource patterns, variant decision tree, pitfalls
  2. getcomponentapi('fdp-table') — all inputs/outputs, selection mode options, page size inputs
  3. If filter requested: getcomponentapi('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 selected

Stop 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,
    TableViewSettingsDialogComponent
} 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, TableViewSettingsDialogComponent,
              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-view-settings-dialog></fdp-table-view-settings-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-helpers and add it to the component's imports array. Its selector matches fdp-table and it initializes state.columns from the column definitions before the first render. Without it, state.columns stays [] and the table shows "Right now, there are no visible columns." even though the fdp-column elements are correctly declared.
  • Import individual components, not PlatformTableModulePlatformTableModule is deprecated and cannot be statically resolved in a standalone component's imports array. Always import TableComponent, TableColumnComponent, TableToolbarComponent, TableToolbarActionsComponent, and TableP13DialogComponent directly from @fundamental-ngx/platform/table.
  • FdpTableDataSource is a type alias, not a class — it lives in @fundamental-ngx/platform/table-helpers and is exported under export type. Use ArrayTableDataSource for static arrays or ObservableTableDataSource for 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 each fdp-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-view-settings-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-columnname is the unique identifier (camelCase), key maps 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/platform increases the initial bundle to ~4.6 MB. In a standalone app raise the budget in angular.json to maximumWarning: "5MB", maximumError: "8MB".
  • Custom cell templates use fdpTableCell structural directive<ng-template fdpTableCell let-row>{{ row.date | date }}</ng-template> inside the fdp-column
  • Do NOT add standalone: true — default since Angular 19
  • Do NOT use ngIf / ngFor in templates — use @if / @for

Phase 5: Validate

# NX monorepo
nx run <project>:build

# Standalone Angular CLI app
ng build   # or: npm run build

Replace 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