diff --git a/.github/workflows/test_and_deploy.yml b/.github/workflows/test_and_deploy.yml
index 4e316a288..6e9da0e08 100644
--- a/.github/workflows/test_and_deploy.yml
+++ b/.github/workflows/test_and_deploy.yml
@@ -29,6 +29,9 @@ jobs:
- name: Install
run: npm ci
+ - name: Verify generated routes
+ run: npm run build:routes && git diff --exit-code
+
- name: Build and package library
run: npm run package
diff --git a/.prettierignore b/.prettierignore
index 7601ace55..98b7295fc 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -7,6 +7,10 @@ tmp
playwright/snapshots
CHANGELOG.md
+# Generated files
+src/app/app.routes.ts
+src/app/app.web-components.ts
+
# Skills managed by skills.sh
.agents/skills/playwright-cli
.agents/skills/gh-stack
diff --git a/angular.json b/angular.json
index d6bc284bd..28d175b04 100644
--- a/angular.json
+++ b/angular.json
@@ -19,6 +19,14 @@
"sourceRoot": "src",
"prefix": "app",
"architect": {
+ "build-routes": {
+ "builder": "@ngx-datatable/example-routes-builder:example-routes",
+ "options": {
+ "sourceRoot": "src/app",
+ "routesFile": "src/app/app.routes.ts",
+ "webComponentsFile": "src/app/app.web-components.ts"
+ }
+ },
"build": {
"builder": "@angular/build:application",
"options": {
@@ -99,6 +107,20 @@
}
}
},
+ "example-routes-builder": {
+ "projectType": "application",
+ "root": "tools/example-routes-builder",
+ "sourceRoot": "tools/example-routes-builder",
+ "architect": {
+ "lint": {
+ "builder": "@angular-eslint/builder:lint",
+ "options": {
+ "lintFilePatterns": ["tools/example-routes-builder/**/*.mts"],
+ "eslintConfig": "tools/example-routes-builder/eslint.config.mjs"
+ }
+ }
+ }
+ },
"ngx-datatable-lib": {
"projectType": "library",
"root": "projects/ngx-datatable",
diff --git a/docs/introduction/column-modes.md b/docs/introduction/column-modes.md
index 923e4f019..120fbe901 100644
--- a/docs/introduction/column-modes.md
+++ b/docs/introduction/column-modes.md
@@ -7,7 +7,7 @@ to the columns. The table comes with 3 modes; `standard`, `flex`, `force`.
Columns are distributed given the width's defined in the column options.
-{{ datatable_example('src/app/columns/fixed-column.component.ts', 'standard-column', '400px') }}
+{{ datatable_example('src/app/columns/fixed-column.component.ts', 'fixed-column', '400px') }}
## Flex
diff --git a/eslint.config.mjs b/eslint.config.mjs
index 5ad299437..e8da3433f 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -11,7 +11,7 @@ const __dirname = path.dirname(__filename);
export const tsConfig = typescriptEslint.config({
extends: [...angularTypescriptConfig],
- files: ['**/*.ts'],
+ files: ['**/*.{ts,mts}'],
languageOptions: {
parserOptions: {
project: ['tsconfig.app.json'],
diff --git a/package-lock.json b/package-lock.json
index 3ede9c736..8ee828e3f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7,6 +7,9 @@
"": {
"name": "ngx-datatable",
"version": "27.0.2",
+ "workspaces": [
+ "tools/example-routes-builder"
+ ],
"dependencies": {
"@angular/cdk": "22.0.6",
"@angular/common": "22.0.8",
@@ -3540,6 +3543,10 @@
"node": ">= 10"
}
},
+ "node_modules/@ngx-datatable/example-routes-builder": {
+ "resolved": "tools/example-routes-builder",
+ "link": true
+ },
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -17904,6 +17911,9 @@
"peerDependencies": {
"zod": "^3.25.28 || ^4"
}
+ },
+ "tools/example-routes-builder": {
+ "name": "@ngx-datatable/example-routes-builder"
}
}
}
diff --git a/package.json b/package.json
index e6e69eeb4..c2c8261f7 100644
--- a/package.json
+++ b/package.json
@@ -15,6 +15,7 @@
"start": "ng serve",
"start:prod": "http-server dist/ngx-datatable-examples -s -p 4200 -a 127.0.0.1",
"build": "ng build",
+ "build:routes": "tsc -p tools/example-routes-builder/tsconfig.json && ng run ngx-datatable:build-routes",
"build:prod": "ng build --configuration production",
"build:web-components": "ng build --configuration web-components",
"format": "prettier --write .",
@@ -37,6 +38,9 @@
"package": "npm run build:lib:prod && npm run copy-files && npm run build:css"
},
"private": true,
+ "workspaces": [
+ "tools/example-routes-builder"
+ ],
"overrides": {
"@microsoft/api-extractor": {
"typescript": "6.0.3"
diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
deleted file mode 100644
index 22d8fef7e..000000000
--- a/src/app/app-routing.module.ts
+++ /dev/null
@@ -1,378 +0,0 @@
-import { Routes } from '@angular/router';
-
-export const routes: Routes = [
- {
- path: '',
- data: { title: 'Fluid Row Height', sourcePath: 'basic/fluid-row-height.component.ts' },
- loadComponent: () =>
- import('./basic/fluid-row-height.component').then(c => c.FluidRowHeightComponent)
- },
- // Basic
- {
- path: 'large-data-set',
- data: { title: 'Large Data Set', sourcePath: 'basic/large-data-set.component.ts' },
- loadComponent: () =>
- import('./basic/large-data-set.component').then(c => c.LargeDataSetComponent)
- },
- {
- path: 'full-screen',
- data: { title: 'Full Screen', sourcePath: 'basic/full-screen.component.ts' },
- loadComponent: () => import('./basic/full-screen.component').then(c => c.FullScreenComponent)
- },
- {
- path: 'inline-editing',
- data: { title: 'Inline Editing', sourcePath: 'basic/inline-editing.component.ts' },
- loadComponent: () =>
- import('./basic/inline-editing.component').then(c => c.InlineEditingComponent)
- },
- {
- path: 'horz-vert-scrolling',
- data: { title: 'Horz/Vert Scrolling', sourcePath: 'basic/horz-vert-scrolling.component.ts' },
- loadComponent: () =>
- import('./basic/horz-vert-scrolling.component').then(c => c.HorzVertScrollingComponent)
- },
- {
- path: 'vert-dynamic-scrolling',
- data: {
- title: 'Vert Dynamic Scrolling',
- sourcePath: 'basic/vert-dynamic-scrolling.component.ts'
- },
- loadComponent: () =>
- import('./basic/vert-dynamic-scrolling.component').then(c => c.VertDynamicScrollingComponent)
- },
- {
- path: 'multiple-tables',
- data: { title: 'Multiple Tables', sourcePath: 'basic/multiple-tables.component.ts' },
- loadComponent: () =>
- import('./basic/multiple-tables.component').then(c => c.MultipleTablesComponent)
- },
- {
- path: 'filtering',
- data: { title: 'Filtering', sourcePath: 'basic/filtering.component.ts' },
- loadComponent: () => import('./basic/filtering.component').then(c => c.FilteringComponent)
- },
- {
- path: 'hidden-on-load',
- data: { title: 'Hidden On Load', sourcePath: 'basic/hidden-on-load.component.ts' },
- loadComponent: () =>
- import('./basic/hidden-on-load.component').then(c => c.HiddenOnLoadComponent)
- },
- {
- path: 'live-data',
- data: { title: 'Live Data', sourcePath: 'basic/live-data.component.ts' },
- loadComponent: () => import('./basic/live-data.component').then(c => c.LiveDataComponent)
- },
- {
- path: 'rxjs',
- data: { title: 'RxJS', sourcePath: 'basic/rxjs.component.ts' },
- loadComponent: () => import('./basic/rxjs.component').then(c => c.RxjsComponent)
- },
- {
- path: 'context-menu',
- data: { title: 'Context Menu', sourcePath: 'basic/context-menu.component.ts' },
- loadComponent: () => import('./basic/context-menu.component').then(c => c.ContextMenuComponent)
- },
- {
- path: 'css-classes',
- data: { title: 'CSS Classes', sourcePath: 'basic/css-classes.component.ts' },
- loadComponent: () => import('./basic/css-classes.component').then(c => c.CssClassesComponent)
- },
- {
- path: 'footer-template',
- data: { title: 'Footer Template', sourcePath: 'basic/footer-template.component.ts' },
- loadComponent: () =>
- import('./basic/footer-template.component').then(c => c.FooterTemplateComponent)
- },
- {
- path: 'empty-template',
- data: { title: 'Empty Template', sourcePath: 'basic/empty-template.component.ts' },
- loadComponent: () =>
- import('./basic/empty-template.component').then(c => c.EmptyTemplateComponent)
- },
- {
- path: 'drag-drop',
- data: { title: 'Drag Drop', sourcePath: 'drag-drop/drag-drop.component.ts' },
- loadComponent: () => import('./drag-drop/drag-drop.component').then(c => c.DragDropComponent)
- },
- // Themes
- {
- path: 'dark-theme',
- loadComponent: () => import('./basic/dark-theme.component').then(c => c.DarkThemeComponent),
- data: { dark: true, title: 'Dark Theme', sourcePath: 'basic/dark-theme.component.ts' }
- },
- {
- path: 'bootstrap-theme',
- data: { title: 'Bootstrap Theme', sourcePath: 'basic/bootstrap-theme.component.ts' },
- loadComponent: () =>
- import('./basic/bootstrap-theme.component').then(c => c.BootstrapThemeComponent)
- },
- // Tree
- {
- path: 'full-screen-tree',
- data: { title: 'Full Screen Tree', sourcePath: 'tree/full-screen-tree.component.ts' },
- loadComponent: () =>
- import('./tree/full-screen-tree.component').then(c => c.FullScreenTreeComponent)
- },
- {
- path: 'client-side-tree',
- data: { title: 'Client Side Tree', sourcePath: 'tree/client-side-tree.component.ts' },
- loadComponent: () =>
- import('./tree/client-side-tree.component').then(c => c.ClientSideTreeComponent)
- },
- // Rows
- {
- path: 'row-grouping',
- data: { title: 'Row Grouping', sourcePath: 'basic/row-grouping.component.ts' },
- loadComponent: () => import('./basic/row-grouping.component').then(c => c.RowGroupingComponent)
- },
- {
- path: 'fixed-row-height',
- data: { title: 'Fixed Row Height', sourcePath: 'basic/fixed-row-height.component.ts' },
- loadComponent: () =>
- import('./basic/fixed-row-height.component').then(c => c.FixedRowHeightComponent)
- },
- {
- path: 'dynamic-row-height',
- data: { title: 'Dynamic Row Height', sourcePath: 'basic/dynamic-row-height.component.ts' },
- loadComponent: () =>
- import('./basic/dynamic-row-height.component').then(c => c.DynamicRowHeightComponent)
- },
- {
- path: 'row-detail',
- data: { title: 'Row Detail', sourcePath: 'basic/row-detail.component.ts' },
- loadComponent: () => import('./basic/row-detail.component').then(c => c.RowDetailComponent)
- },
- {
- path: 'responsive',
- data: { title: 'Responsive', sourcePath: 'basic/responsive.component.ts' },
- loadComponent: () => import('./basic/responsive.component').then(c => c.ResponsiveComponent)
- },
- {
- path: 'disabled',
- data: { title: 'Disabled', sourcePath: 'basic/disabled.component.ts' },
- loadComponent: () => import('./basic/disabled.component').then(c => c.DisabledComponent)
- },
- // Paging
- {
- path: 'client-side-paging',
- data: { title: 'Client-side Paging', sourcePath: 'paging/client-side-paging.component.ts' },
- loadComponent: () =>
- import('./paging/client-side-paging.component').then(c => c.ClientSidePagingComponent)
- },
- {
- path: 'server-side-paging',
- data: { title: 'Server-side Paging', sourcePath: 'paging/server-side-paging.component.ts' },
- loadComponent: () =>
- import('./paging/server-side-paging.component').then(c => c.ServerSidePagingComponent)
- },
- {
- path: 'scrolling-no-virtual',
- data: { title: 'Scrolling no virtual', sourcePath: 'paging/scrolling-no-virtual.component.ts' },
- loadComponent: () =>
- import('./paging/scrolling-no-virtual.component').then(c => c.ScrollingNoVirtualComponent)
- },
- {
- path: 'scrolling-server-side',
- data: {
- title: 'Scrolling server-side',
- sourcePath: 'paging/scrolling-server-side.component.ts'
- },
- loadComponent: () =>
- import('./paging/scrolling-server-side.component').then(c => c.ScrollingServerSideComponent)
- },
- {
- path: 'virtual-server-side',
- data: { title: 'Virtual server-side', sourcePath: 'paging/virtual-server-side.component.ts' },
- loadComponent: () =>
- import('./paging/virtual-server-side.component').then(c => c.VirtualServerSideComponent)
- },
- // Sorting
- {
- path: 'client-side-sorting',
- data: { title: 'Client-side Sorting', sourcePath: 'sorting/client-side-sorting.component.ts' },
- loadComponent: () =>
- import('./sorting/client-side-sorting.component').then(c => c.ClientSideSortingComponent)
- },
- {
- path: 'default-sort',
- data: { title: 'Default Sort', sourcePath: 'sorting/default-sort.component.ts' },
- loadComponent: () =>
- import('./sorting/default-sort.component').then(c => c.DefaultSortComponent)
- },
- {
- path: 'server-side-sorting',
- data: { title: 'Server-side Sorting', sourcePath: 'sorting/server-side-sorting.component.ts' },
- loadComponent: () =>
- import('./sorting/server-side-sorting.component').then(c => c.ServerSideSortingComponent)
- },
- {
- path: 'comparator',
- data: { title: 'Comparator', sourcePath: 'sorting/comparator.component.ts' },
- loadComponent: () => import('./sorting/comparator.component').then(c => c.ComparatorComponent)
- },
- // Selection
- {
- path: 'cell-selection',
- data: { title: 'Cell Selection', sourcePath: 'selection/cell-selection.component.ts' },
- loadComponent: () =>
- import('./selection/cell-selection.component').then(c => c.CellSelectionComponent)
- },
- {
- path: 'single-row-selection',
- data: {
- title: 'Single Row Selection',
- sourcePath: 'selection/single-row-selection.component.ts'
- },
- loadComponent: () =>
- import('./selection/single-row-selection.component').then(c => c.SingleRowSelectionComponent)
- },
- {
- path: 'multi-row-selection',
- data: {
- title: 'Multi Row Selection',
- sourcePath: 'selection/multi-row-selection.component.ts'
- },
- loadComponent: () =>
- import('./selection/multi-row-selection.component').then(c => c.MultiRowSelectionComponent)
- },
- {
- path: 'multi-click-row-selection',
- data: {
- title: 'Multi Click Row Selection',
- sourcePath: 'selection/multi-click-row-selection.component.ts'
- },
- loadComponent: () =>
- import('./selection/multi-click-row-selection.component').then(
- c => c.MultiClickRowSelectionComponent
- )
- },
- {
- path: 'disable-selection-callback',
- data: {
- title: 'Disable Selection Callback',
- sourcePath: 'selection/disable-selection-callback.component.ts'
- },
- loadComponent: () =>
- import('./selection/disable-selection-callback.component').then(
- c => c.DisableSelectionCallbackComponent
- )
- },
- {
- path: 'checkbox-selection',
- data: { title: 'Checkbox Selection', sourcePath: 'selection/checkbox-selection.component.ts' },
- loadComponent: () =>
- import('./selection/checkbox-selection.component').then(c => c.CheckboxSelectionComponent)
- },
- {
- path: 'custom-checkbox-selection',
- data: {
- title: 'Custom Checkbox Selection',
- sourcePath: 'selection/custom-checkbox-selection.component.ts'
- },
- loadComponent: () =>
- import('./selection/custom-checkbox-selection.component').then(
- c => c.CustomCheckboxSelectionComponent
- )
- },
- {
- path: 'multi-click-and-checkbox-selection',
- data: {
- title: 'Multi Click and Checkbox Selection',
- sourcePath: 'selection/multi-click-and-checkbox-selection.component.ts'
- },
- loadComponent: () =>
- import('./selection/multi-click-and-checkbox-selection.component').then(
- c => c.MultiClickAndCheckboxSelectionComponent
- )
- },
- // Templates
- {
- path: 'inline-template',
- data: { title: 'Inline Template', sourcePath: 'templates/inline-template.component.ts' },
- loadComponent: () =>
- import('./templates/inline-template.component').then(c => c.InlineTemplateComponent)
- },
- {
- path: 'template-ref',
- data: { title: 'TemplateRef', sourcePath: 'templates/template-ref.component.ts' },
- loadComponent: () =>
- import('./templates/template-ref.component').then(c => c.TemplateRefComponent)
- },
- // Column
- {
- path: 'flex-column',
- data: { title: 'Flex Column', sourcePath: 'columns/flex-column.component.ts' },
- loadComponent: () => import('./columns/flex-column.component').then(c => c.FlexColumnComponent)
- },
- {
- path: 'column-toggling',
- data: { title: 'Column Toggling', sourcePath: 'columns/column-toggling.component.ts' },
- loadComponent: () =>
- import('./columns/column-toggling.component').then(c => c.ColumnTogglingComponent)
- },
- {
- path: 'fixed-column',
- data: { title: 'Fixed Column', sourcePath: 'columns/fixed-column.component.ts' },
- loadComponent: () =>
- import('./columns/fixed-column.component').then(c => c.FixedColumnComponent)
- },
- {
- path: 'force-column',
- data: { title: 'Force Column', sourcePath: 'columns/force-column.component.ts' },
- loadComponent: () =>
- import('./columns/force-column.component').then(c => c.ForceColumnComponent)
- },
- {
- path: 'column-pinning',
- data: { title: 'Column Pinning', sourcePath: 'columns/column-pinning.component.ts' },
- loadComponent: () =>
- import('./columns/column-pinning.component').then(c => c.ColumnPinningComponent)
- },
- {
- path: 'column-reorder',
- data: { title: 'Column Reorder', sourcePath: 'columns/column-reorder.component.ts' },
- loadComponent: () =>
- import('./columns/column-reorder.component').then(c => c.ColumnReorderComponent)
- },
- // Summary Row
- {
- path: 'simple-summary',
- data: { title: 'Simple Summary', sourcePath: 'summary/simple-summary.component.ts' },
- loadComponent: () =>
- import('./summary/simple-summary.component').then(c => c.SimpleSummaryComponent)
- },
- {
- path: 'custom-template-summary',
- data: {
- title: 'Custom Template Summary',
- sourcePath: 'summary/custom-template-summary.component.ts'
- },
- loadComponent: () =>
- import('./summary/custom-template-summary.component').then(
- c => c.CustomTemplateSummaryComponent
- )
- },
- {
- path: 'server-side-paging-summary',
- data: {
- title: 'Server-side Paging Summary',
- sourcePath: 'summary/server-side-paging-summary.component.ts'
- },
- loadComponent: () =>
- import('./summary/server-side-paging-summary.component').then(
- c => c.ServerSidePagingSummaryComponent
- )
- },
- {
- path: 'inline-html-summary',
- data: { title: 'Inline HTML Summary', sourcePath: 'summary/inline-html-summary.component.ts' },
- loadComponent: () =>
- import('./summary/inline-html-summary.component').then(c => c.InlineHtmlSummaryComponent)
- },
- {
- path: 'summary-row-actions',
- data: { title: 'Summary Row Actions', sourcePath: 'summary/summary-row-actions.component.ts' },
- loadComponent: () =>
- import('./summary/summary-row-actions.component').then(c => c.SummaryRowActionsComponent)
- }
-];
diff --git a/src/app/app.component.html b/src/app/app.component.html
index eba65a67a..ef2f996eb 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -244,6 +244,6 @@
Summary Row
@if (title()) {
}
-
+
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 938e1cfa4..a97b071f6 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -5,6 +5,11 @@ import { RouterLink, RouterOutlet } from '@angular/router';
import packageInfo from '../../projects/ngx-datatable/package.json';
import { ExampleTitleComponent } from './example-title.component';
+interface ExampleComponentConstructor {
+ dark?: boolean;
+ exampleTitle: string;
+}
+
@Component({
selector: 'app-root',
imports: [ExampleTitleComponent, RouterLink, RouterOutlet],
@@ -24,11 +29,12 @@ export class AppComponent {
readonly title = signal('');
readonly sourcePath = signal('');
- routeActivate(outlet: RouterOutlet): void {
- const { dark = false, sourcePath = '', title = '' } = outlet.activatedRoute.snapshot.data;
+ routeActivate(component: object, outlet: RouterOutlet): void {
+ const { sourcePath = '' } = outlet.activatedRoute.snapshot.data;
+ const example = component.constructor as unknown as ExampleComponentConstructor;
- this.dark.set(dark);
+ this.dark.set(example.dark ?? false);
this.sourcePath.set(sourcePath);
- this.title.set(title);
+ this.title.set(example.exampleTitle);
}
}
diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts
new file mode 100644
index 000000000..b1343227a
--- /dev/null
+++ b/src/app/app.routes.ts
@@ -0,0 +1,289 @@
+// This file is generated by the example-routes builder. Do not edit manually.
+import { Routes } from '@angular/router';
+export const routes: Routes = [
+ {
+ path: '',
+ redirectTo: 'fluid-row-height',
+ pathMatch: 'full'
+ },
+ {
+ path: 'bootstrap-theme',
+ data: { sourcePath: 'basic/bootstrap-theme.component.ts' },
+ loadComponent: () => import('./basic/bootstrap-theme.component').then(component => component.BootstrapThemeComponent)
+ },
+ {
+ path: 'cell-selection',
+ data: { sourcePath: 'selection/cell-selection.component.ts' },
+ loadComponent: () => import('./selection/cell-selection.component').then(component => component.CellSelectionComponent)
+ },
+ {
+ path: 'checkbox-selection',
+ data: { sourcePath: 'selection/checkbox-selection.component.ts' },
+ loadComponent: () => import('./selection/checkbox-selection.component').then(component => component.CheckboxSelectionComponent)
+ },
+ {
+ path: 'client-side-paging',
+ data: { sourcePath: 'paging/client-side-paging.component.ts' },
+ loadComponent: () => import('./paging/client-side-paging.component').then(component => component.ClientSidePagingComponent)
+ },
+ {
+ path: 'client-side-sorting',
+ data: { sourcePath: 'sorting/client-side-sorting.component.ts' },
+ loadComponent: () => import('./sorting/client-side-sorting.component').then(component => component.ClientSideSortingComponent)
+ },
+ {
+ path: 'client-side-tree',
+ data: { sourcePath: 'tree/client-side-tree.component.ts' },
+ loadComponent: () => import('./tree/client-side-tree.component').then(component => component.ClientSideTreeComponent)
+ },
+ {
+ path: 'column-pinning',
+ data: { sourcePath: 'columns/column-pinning.component.ts' },
+ loadComponent: () => import('./columns/column-pinning.component').then(component => component.ColumnPinningComponent)
+ },
+ {
+ path: 'column-reorder',
+ data: { sourcePath: 'columns/column-reorder.component.ts' },
+ loadComponent: () => import('./columns/column-reorder.component').then(component => component.ColumnReorderComponent)
+ },
+ {
+ path: 'column-toggling',
+ data: { sourcePath: 'columns/column-toggling.component.ts' },
+ loadComponent: () => import('./columns/column-toggling.component').then(component => component.ColumnTogglingComponent)
+ },
+ {
+ path: 'comparator',
+ data: { sourcePath: 'sorting/comparator.component.ts' },
+ loadComponent: () => import('./sorting/comparator.component').then(component => component.ComparatorComponent)
+ },
+ {
+ path: 'context-menu',
+ data: { sourcePath: 'basic/context-menu.component.ts' },
+ loadComponent: () => import('./basic/context-menu.component').then(component => component.ContextMenuComponent)
+ },
+ {
+ path: 'css-classes',
+ data: { sourcePath: 'basic/css-classes.component.ts' },
+ loadComponent: () => import('./basic/css-classes.component').then(component => component.CssClassesComponent)
+ },
+ {
+ path: 'custom-checkbox-selection',
+ data: { sourcePath: 'selection/custom-checkbox-selection.component.ts' },
+ loadComponent: () => import('./selection/custom-checkbox-selection.component').then(component => component.CustomCheckboxSelectionComponent)
+ },
+ {
+ path: 'custom-template-summary',
+ data: { sourcePath: 'summary/custom-template-summary.component.ts' },
+ loadComponent: () => import('./summary/custom-template-summary.component').then(component => component.CustomTemplateSummaryComponent)
+ },
+ {
+ path: 'dark-theme',
+ data: { sourcePath: 'basic/dark-theme.component.ts' },
+ loadComponent: () => import('./basic/dark-theme.component').then(component => component.DarkThemeComponent)
+ },
+ {
+ path: 'default-sort',
+ data: { sourcePath: 'sorting/default-sort.component.ts' },
+ loadComponent: () => import('./sorting/default-sort.component').then(component => component.DefaultSortComponent)
+ },
+ {
+ path: 'disable-selection-callback',
+ data: { sourcePath: 'selection/disable-selection-callback.component.ts' },
+ loadComponent: () => import('./selection/disable-selection-callback.component').then(component => component.DisableSelectionCallbackComponent)
+ },
+ {
+ path: 'disabled',
+ data: { sourcePath: 'basic/disabled.component.ts' },
+ loadComponent: () => import('./basic/disabled.component').then(component => component.DisabledComponent)
+ },
+ {
+ path: 'drag-drop',
+ data: { sourcePath: 'drag-drop/drag-drop.component.ts' },
+ loadComponent: () => import('./drag-drop/drag-drop.component').then(component => component.DragDropComponent)
+ },
+ {
+ path: 'dynamic-row-height',
+ data: { sourcePath: 'basic/dynamic-row-height.component.ts' },
+ loadComponent: () => import('./basic/dynamic-row-height.component').then(component => component.DynamicRowHeightComponent)
+ },
+ {
+ path: 'empty-template',
+ data: { sourcePath: 'basic/empty-template.component.ts' },
+ loadComponent: () => import('./basic/empty-template.component').then(component => component.EmptyTemplateComponent)
+ },
+ {
+ path: 'filtering',
+ data: { sourcePath: 'basic/filtering.component.ts' },
+ loadComponent: () => import('./basic/filtering.component').then(component => component.FilteringComponent)
+ },
+ {
+ path: 'fixed-column',
+ data: { sourcePath: 'columns/fixed-column.component.ts' },
+ loadComponent: () => import('./columns/fixed-column.component').then(component => component.FixedColumnComponent)
+ },
+ {
+ path: 'fixed-row-height',
+ data: { sourcePath: 'basic/fixed-row-height.component.ts' },
+ loadComponent: () => import('./basic/fixed-row-height.component').then(component => component.FixedRowHeightComponent)
+ },
+ {
+ path: 'flex-column',
+ data: { sourcePath: 'columns/flex-column.component.ts' },
+ loadComponent: () => import('./columns/flex-column.component').then(component => component.FlexColumnComponent)
+ },
+ {
+ path: 'fluid-row-height',
+ data: { sourcePath: 'basic/fluid-row-height.component.ts' },
+ loadComponent: () => import('./basic/fluid-row-height.component').then(component => component.FluidRowHeightComponent)
+ },
+ {
+ path: 'footer-template',
+ data: { sourcePath: 'basic/footer-template.component.ts' },
+ loadComponent: () => import('./basic/footer-template.component').then(component => component.FooterTemplateComponent)
+ },
+ {
+ path: 'force-column',
+ data: { sourcePath: 'columns/force-column.component.ts' },
+ loadComponent: () => import('./columns/force-column.component').then(component => component.ForceColumnComponent)
+ },
+ {
+ path: 'full-screen',
+ data: { sourcePath: 'basic/full-screen.component.ts' },
+ loadComponent: () => import('./basic/full-screen.component').then(component => component.FullScreenComponent)
+ },
+ {
+ path: 'full-screen-tree',
+ data: { sourcePath: 'tree/full-screen-tree.component.ts' },
+ loadComponent: () => import('./tree/full-screen-tree.component').then(component => component.FullScreenTreeComponent)
+ },
+ {
+ path: 'hidden-on-load',
+ data: { sourcePath: 'basic/hidden-on-load.component.ts' },
+ loadComponent: () => import('./basic/hidden-on-load.component').then(component => component.HiddenOnLoadComponent)
+ },
+ {
+ path: 'horz-vert-scrolling',
+ data: { sourcePath: 'basic/horz-vert-scrolling.component.ts' },
+ loadComponent: () => import('./basic/horz-vert-scrolling.component').then(component => component.HorzVertScrollingComponent)
+ },
+ {
+ path: 'inline-editing',
+ data: { sourcePath: 'basic/inline-editing.component.ts' },
+ loadComponent: () => import('./basic/inline-editing.component').then(component => component.InlineEditingComponent)
+ },
+ {
+ path: 'inline-html-summary',
+ data: { sourcePath: 'summary/inline-html-summary.component.ts' },
+ loadComponent: () => import('./summary/inline-html-summary.component').then(component => component.InlineHtmlSummaryComponent)
+ },
+ {
+ path: 'inline-template',
+ data: { sourcePath: 'templates/inline-template.component.ts' },
+ loadComponent: () => import('./templates/inline-template.component').then(component => component.InlineTemplateComponent)
+ },
+ {
+ path: 'large-data-set',
+ data: { sourcePath: 'basic/large-data-set.component.ts' },
+ loadComponent: () => import('./basic/large-data-set.component').then(component => component.LargeDataSetComponent)
+ },
+ {
+ path: 'live-data',
+ data: { sourcePath: 'basic/live-data.component.ts' },
+ loadComponent: () => import('./basic/live-data.component').then(component => component.LiveDataComponent)
+ },
+ {
+ path: 'multi-click-and-checkbox-selection',
+ data: { sourcePath: 'selection/multi-click-and-checkbox-selection.component.ts' },
+ loadComponent: () => import('./selection/multi-click-and-checkbox-selection.component').then(component => component.MultiClickAndCheckboxSelectionComponent)
+ },
+ {
+ path: 'multi-click-row-selection',
+ data: { sourcePath: 'selection/multi-click-row-selection.component.ts' },
+ loadComponent: () => import('./selection/multi-click-row-selection.component').then(component => component.MultiClickRowSelectionComponent)
+ },
+ {
+ path: 'multi-row-selection',
+ data: { sourcePath: 'selection/multi-row-selection.component.ts' },
+ loadComponent: () => import('./selection/multi-row-selection.component').then(component => component.MultiRowSelectionComponent)
+ },
+ {
+ path: 'multiple-tables',
+ data: { sourcePath: 'basic/multiple-tables.component.ts' },
+ loadComponent: () => import('./basic/multiple-tables.component').then(component => component.MultipleTablesComponent)
+ },
+ {
+ path: 'responsive',
+ data: { sourcePath: 'basic/responsive.component.ts' },
+ loadComponent: () => import('./basic/responsive.component').then(component => component.ResponsiveComponent)
+ },
+ {
+ path: 'row-detail',
+ data: { sourcePath: 'basic/row-detail.component.ts' },
+ loadComponent: () => import('./basic/row-detail.component').then(component => component.RowDetailComponent)
+ },
+ {
+ path: 'row-grouping',
+ data: { sourcePath: 'basic/row-grouping.component.ts' },
+ loadComponent: () => import('./basic/row-grouping.component').then(component => component.RowGroupingComponent)
+ },
+ {
+ path: 'rxjs',
+ data: { sourcePath: 'basic/rxjs.component.ts' },
+ loadComponent: () => import('./basic/rxjs.component').then(component => component.RxjsComponent)
+ },
+ {
+ path: 'scrolling-no-virtual',
+ data: { sourcePath: 'paging/scrolling-no-virtual.component.ts' },
+ loadComponent: () => import('./paging/scrolling-no-virtual.component').then(component => component.ScrollingNoVirtualComponent)
+ },
+ {
+ path: 'scrolling-server-side',
+ data: { sourcePath: 'paging/scrolling-server-side.component.ts' },
+ loadComponent: () => import('./paging/scrolling-server-side.component').then(component => component.ScrollingServerSideComponent)
+ },
+ {
+ path: 'server-side-paging',
+ data: { sourcePath: 'paging/server-side-paging.component.ts' },
+ loadComponent: () => import('./paging/server-side-paging.component').then(component => component.ServerSidePagingComponent)
+ },
+ {
+ path: 'server-side-paging-summary',
+ data: { sourcePath: 'summary/server-side-paging-summary.component.ts' },
+ loadComponent: () => import('./summary/server-side-paging-summary.component').then(component => component.ServerSidePagingSummaryComponent)
+ },
+ {
+ path: 'server-side-sorting',
+ data: { sourcePath: 'sorting/server-side-sorting.component.ts' },
+ loadComponent: () => import('./sorting/server-side-sorting.component').then(component => component.ServerSideSortingComponent)
+ },
+ {
+ path: 'simple-summary',
+ data: { sourcePath: 'summary/simple-summary.component.ts' },
+ loadComponent: () => import('./summary/simple-summary.component').then(component => component.SimpleSummaryComponent)
+ },
+ {
+ path: 'single-row-selection',
+ data: { sourcePath: 'selection/single-row-selection.component.ts' },
+ loadComponent: () => import('./selection/single-row-selection.component').then(component => component.SingleRowSelectionComponent)
+ },
+ {
+ path: 'summary-row-actions',
+ data: { sourcePath: 'summary/summary-row-actions.component.ts' },
+ loadComponent: () => import('./summary/summary-row-actions.component').then(component => component.SummaryRowActionsComponent)
+ },
+ {
+ path: 'template-ref',
+ data: { sourcePath: 'templates/template-ref.component.ts' },
+ loadComponent: () => import('./templates/template-ref.component').then(component => component.TemplateRefComponent)
+ },
+ {
+ path: 'vert-dynamic-scrolling',
+ data: { sourcePath: 'basic/vert-dynamic-scrolling.component.ts' },
+ loadComponent: () => import('./basic/vert-dynamic-scrolling.component').then(component => component.VertDynamicScrollingComponent)
+ },
+ {
+ path: 'virtual-server-side',
+ data: { sourcePath: 'paging/virtual-server-side.component.ts' },
+ loadComponent: () => import('./paging/virtual-server-side.component').then(component => component.VirtualServerSideComponent)
+ }
+];
diff --git a/src/app/app.web-components.ts b/src/app/app.web-components.ts
new file mode 100644
index 000000000..922e990cc
--- /dev/null
+++ b/src/app/app.web-components.ts
@@ -0,0 +1,60 @@
+// This file is generated by the example-routes builder. Do not edit manually.
+import { Type } from '@angular/core';
+export const exampleLoaders: ReadonlyMap Promise>> = new Map Promise>>([
+ ['bootstrap-theme', () => import('./basic/bootstrap-theme.component').then(component => component.BootstrapThemeComponent)],
+ ['cell-selection', () => import('./selection/cell-selection.component').then(component => component.CellSelectionComponent)],
+ ['checkbox-selection', () => import('./selection/checkbox-selection.component').then(component => component.CheckboxSelectionComponent)],
+ ['client-side-paging', () => import('./paging/client-side-paging.component').then(component => component.ClientSidePagingComponent)],
+ ['client-side-sorting', () => import('./sorting/client-side-sorting.component').then(component => component.ClientSideSortingComponent)],
+ ['client-side-tree', () => import('./tree/client-side-tree.component').then(component => component.ClientSideTreeComponent)],
+ ['column-pinning', () => import('./columns/column-pinning.component').then(component => component.ColumnPinningComponent)],
+ ['column-reorder', () => import('./columns/column-reorder.component').then(component => component.ColumnReorderComponent)],
+ ['column-toggling', () => import('./columns/column-toggling.component').then(component => component.ColumnTogglingComponent)],
+ ['comparator', () => import('./sorting/comparator.component').then(component => component.ComparatorComponent)],
+ ['context-menu', () => import('./basic/context-menu.component').then(component => component.ContextMenuComponent)],
+ ['css-classes', () => import('./basic/css-classes.component').then(component => component.CssClassesComponent)],
+ ['custom-checkbox-selection', () => import('./selection/custom-checkbox-selection.component').then(component => component.CustomCheckboxSelectionComponent)],
+ ['custom-template-summary', () => import('./summary/custom-template-summary.component').then(component => component.CustomTemplateSummaryComponent)],
+ ['dark-theme', () => import('./basic/dark-theme.component').then(component => component.DarkThemeComponent)],
+ ['default-sort', () => import('./sorting/default-sort.component').then(component => component.DefaultSortComponent)],
+ ['disable-selection-callback', () => import('./selection/disable-selection-callback.component').then(component => component.DisableSelectionCallbackComponent)],
+ ['disabled', () => import('./basic/disabled.component').then(component => component.DisabledComponent)],
+ ['drag-drop', () => import('./drag-drop/drag-drop.component').then(component => component.DragDropComponent)],
+ ['dynamic-row-height', () => import('./basic/dynamic-row-height.component').then(component => component.DynamicRowHeightComponent)],
+ ['empty-template', () => import('./basic/empty-template.component').then(component => component.EmptyTemplateComponent)],
+ ['filtering', () => import('./basic/filtering.component').then(component => component.FilteringComponent)],
+ ['fixed-column', () => import('./columns/fixed-column.component').then(component => component.FixedColumnComponent)],
+ ['fixed-row-height', () => import('./basic/fixed-row-height.component').then(component => component.FixedRowHeightComponent)],
+ ['flex-column', () => import('./columns/flex-column.component').then(component => component.FlexColumnComponent)],
+ ['fluid-row-height', () => import('./basic/fluid-row-height.component').then(component => component.FluidRowHeightComponent)],
+ ['footer-template', () => import('./basic/footer-template.component').then(component => component.FooterTemplateComponent)],
+ ['force-column', () => import('./columns/force-column.component').then(component => component.ForceColumnComponent)],
+ ['full-screen', () => import('./basic/full-screen.component').then(component => component.FullScreenComponent)],
+ ['full-screen-tree', () => import('./tree/full-screen-tree.component').then(component => component.FullScreenTreeComponent)],
+ ['hidden-on-load', () => import('./basic/hidden-on-load.component').then(component => component.HiddenOnLoadComponent)],
+ ['horz-vert-scrolling', () => import('./basic/horz-vert-scrolling.component').then(component => component.HorzVertScrollingComponent)],
+ ['inline-editing', () => import('./basic/inline-editing.component').then(component => component.InlineEditingComponent)],
+ ['inline-html-summary', () => import('./summary/inline-html-summary.component').then(component => component.InlineHtmlSummaryComponent)],
+ ['inline-template', () => import('./templates/inline-template.component').then(component => component.InlineTemplateComponent)],
+ ['large-data-set', () => import('./basic/large-data-set.component').then(component => component.LargeDataSetComponent)],
+ ['live-data', () => import('./basic/live-data.component').then(component => component.LiveDataComponent)],
+ ['multi-click-and-checkbox-selection', () => import('./selection/multi-click-and-checkbox-selection.component').then(component => component.MultiClickAndCheckboxSelectionComponent)],
+ ['multi-click-row-selection', () => import('./selection/multi-click-row-selection.component').then(component => component.MultiClickRowSelectionComponent)],
+ ['multi-row-selection', () => import('./selection/multi-row-selection.component').then(component => component.MultiRowSelectionComponent)],
+ ['multiple-tables', () => import('./basic/multiple-tables.component').then(component => component.MultipleTablesComponent)],
+ ['responsive', () => import('./basic/responsive.component').then(component => component.ResponsiveComponent)],
+ ['row-detail', () => import('./basic/row-detail.component').then(component => component.RowDetailComponent)],
+ ['row-grouping', () => import('./basic/row-grouping.component').then(component => component.RowGroupingComponent)],
+ ['rxjs', () => import('./basic/rxjs.component').then(component => component.RxjsComponent)],
+ ['scrolling-no-virtual', () => import('./paging/scrolling-no-virtual.component').then(component => component.ScrollingNoVirtualComponent)],
+ ['scrolling-server-side', () => import('./paging/scrolling-server-side.component').then(component => component.ScrollingServerSideComponent)],
+ ['server-side-paging', () => import('./paging/server-side-paging.component').then(component => component.ServerSidePagingComponent)],
+ ['server-side-paging-summary', () => import('./summary/server-side-paging-summary.component').then(component => component.ServerSidePagingSummaryComponent)],
+ ['server-side-sorting', () => import('./sorting/server-side-sorting.component').then(component => component.ServerSideSortingComponent)],
+ ['simple-summary', () => import('./summary/simple-summary.component').then(component => component.SimpleSummaryComponent)],
+ ['single-row-selection', () => import('./selection/single-row-selection.component').then(component => component.SingleRowSelectionComponent)],
+ ['summary-row-actions', () => import('./summary/summary-row-actions.component').then(component => component.SummaryRowActionsComponent)],
+ ['template-ref', () => import('./templates/template-ref.component').then(component => component.TemplateRefComponent)],
+ ['vert-dynamic-scrolling', () => import('./basic/vert-dynamic-scrolling.component').then(component => component.VertDynamicScrollingComponent)],
+ ['virtual-server-side', () => import('./paging/virtual-server-side.component').then(component => component.VirtualServerSideComponent)]
+]);
diff --git a/src/app/basic/bootstrap-theme.component.ts b/src/app/basic/bootstrap-theme.component.ts
index 93ed29bb9..a812e5e38 100644
--- a/src/app/basic/bootstrap-theme.component.ts
+++ b/src/app/basic/bootstrap-theme.component.ts
@@ -27,6 +27,7 @@ import { DataService } from '../data.service';
`
})
export class BootstrapThemeComponent {
+ static readonly exampleTitle = 'Bootstrap Theme';
private dataService = inject(DataService);
readonly rows = signal([]);
readonly loadingIndicator = signal(true);
diff --git a/src/app/basic/context-menu.component.ts b/src/app/basic/context-menu.component.ts
index abc07ae5f..66aa8d15d 100644
--- a/src/app/basic/context-menu.component.ts
+++ b/src/app/basic/context-menu.component.ts
@@ -44,6 +44,7 @@ import { DataService } from '../data.service';
`
})
export class ContextMenuComponent {
+ static readonly exampleTitle = 'Context Menu';
protected readonly rows = inject(DataService).load('company.json');
columns: TableColumn[] = [{ prop: 'name' }, { name: 'Gender' }, { name: 'Company' }];
diff --git a/src/app/basic/css-classes.component.ts b/src/app/basic/css-classes.component.ts
index 3cd2aa922..ca545fd7f 100644
--- a/src/app/basic/css-classes.component.ts
+++ b/src/app/basic/css-classes.component.ts
@@ -26,6 +26,7 @@ import { DataService } from '../data.service';
`
})
export class CssClassesComponent {
+ static readonly exampleTitle = 'CSS Classes';
protected readonly rows = inject(DataService)
.load('100k.json')
.pipe(map(data => data.slice(0, 50)));
diff --git a/src/app/basic/dark-theme.component.ts b/src/app/basic/dark-theme.component.ts
index b263e3ec5..e98f8e50b 100644
--- a/src/app/basic/dark-theme.component.ts
+++ b/src/app/basic/dark-theme.component.ts
@@ -26,6 +26,8 @@ import { DataService } from '../data.service';
`
})
export class DarkThemeComponent {
+ static readonly exampleTitle = 'Dark Theme';
+ static readonly dark = true;
private dataService = inject(DataService);
readonly rows = signal([]);
readonly loadingIndicator = signal(true);
diff --git a/src/app/basic/disabled.component.ts b/src/app/basic/disabled.component.ts
index 1f30ce9ec..a9551335f 100644
--- a/src/app/basic/disabled.component.ts
+++ b/src/app/basic/disabled.component.ts
@@ -83,6 +83,7 @@ import { DataService } from '../data.service';
`
})
export class DisabledComponent {
+ static readonly exampleTitle = 'Disabled';
private dataService = inject(DataService);
readonly rows = signal<(FullEmployee & { isDisabled?: boolean })[]>([]);
diff --git a/src/app/basic/dynamic-row-height.component.ts b/src/app/basic/dynamic-row-height.component.ts
index 8765ef58f..5482c2ac2 100644
--- a/src/app/basic/dynamic-row-height.component.ts
+++ b/src/app/basic/dynamic-row-height.component.ts
@@ -26,6 +26,7 @@ import { DataService } from '../data.service';
`
})
export class DynamicRowHeightComponent {
+ static readonly exampleTitle = 'Dynamic Row Height';
protected readonly rows = inject(DataService)
.load('100k.json')
.pipe(
diff --git a/src/app/basic/empty-template.component.ts b/src/app/basic/empty-template.component.ts
index 42b7b2be5..2de4828ee 100644
--- a/src/app/basic/empty-template.component.ts
+++ b/src/app/basic/empty-template.component.ts
@@ -32,6 +32,7 @@ import { DatatableComponent, TableColumn } from '@siemens/ngx-datatable';
`
})
export class EmptyTemplateComponent {
+ static readonly exampleTitle = 'Empty Template';
columns: TableColumn[] = [
{ prop: 'name' },
{ name: 'Gender' },
diff --git a/src/app/basic/filtering.component.ts b/src/app/basic/filtering.component.ts
index 9e34d8f24..2608f72ef 100644
--- a/src/app/basic/filtering.component.ts
+++ b/src/app/basic/filtering.component.ts
@@ -28,6 +28,7 @@ import { DataService } from '../data.service';
`
})
export class FilteringComponent {
+ static readonly exampleTitle = 'Filtering';
private dataService = inject(DataService);
readonly rows = signal([]);
diff --git a/src/app/basic/fixed-row-height.component.ts b/src/app/basic/fixed-row-height.component.ts
index 62ef75bff..bc2e79c6f 100644
--- a/src/app/basic/fixed-row-height.component.ts
+++ b/src/app/basic/fixed-row-height.component.ts
@@ -20,6 +20,7 @@ import { DataService } from '../data.service';
`
})
export class FixedRowHeightComponent {
+ static readonly exampleTitle = 'Fixed Row Height';
protected readonly rows = inject(DataService).load('company.json');
columns: TableColumn[] = [{ prop: 'name' }, { name: 'Company' }, { name: 'Gender' }];
}
diff --git a/src/app/basic/fluid-row-height.component.ts b/src/app/basic/fluid-row-height.component.ts
index 84843076e..d49cdb068 100644
--- a/src/app/basic/fluid-row-height.component.ts
+++ b/src/app/basic/fluid-row-height.component.ts
@@ -26,6 +26,7 @@ import { DataService } from '../data.service';
host: { class: 'datatable-example' }
})
export class FluidRowHeightComponent {
+ static readonly exampleTitle = 'Fluid Row Height';
private dataService = inject(DataService);
readonly rows = signal([]);
readonly loadingIndicator = signal(true);
diff --git a/src/app/basic/footer-template.component.ts b/src/app/basic/footer-template.component.ts
index 00f1ead25..012354352 100644
--- a/src/app/basic/footer-template.component.ts
+++ b/src/app/basic/footer-template.component.ts
@@ -54,6 +54,7 @@ import { DataService } from '../data.service';
`
})
export class FooterTemplateComponent {
+ static readonly exampleTitle = 'Footer Template';
protected readonly rows = inject(DataService)
.load('company.json')
.pipe(map(data => data.slice(0, 5)));
diff --git a/src/app/basic/full-screen.component.ts b/src/app/basic/full-screen.component.ts
index 3e20430d5..ffb52d984 100644
--- a/src/app/basic/full-screen.component.ts
+++ b/src/app/basic/full-screen.component.ts
@@ -29,5 +29,6 @@ import { DataService } from '../data.service';
`
})
export class FullScreenComponent {
+ static readonly exampleTitle = 'Full Screen';
protected readonly rows = inject(DataService).load('100k.json');
}
diff --git a/src/app/basic/hidden-on-load.component.ts b/src/app/basic/hidden-on-load.component.ts
index e7835e34e..2d97eecca 100644
--- a/src/app/basic/hidden-on-load.component.ts
+++ b/src/app/basic/hidden-on-load.component.ts
@@ -59,6 +59,7 @@ import { DataService } from '../data.service';
`
})
export class HiddenOnLoadComponent {
+ static readonly exampleTitle = 'Hidden On Load';
protected readonly rows = inject(DataService).load('100k.json');
tab1 = true;
diff --git a/src/app/basic/horz-vert-scrolling.component.ts b/src/app/basic/horz-vert-scrolling.component.ts
index 41cb4f87a..7ac591a45 100644
--- a/src/app/basic/horz-vert-scrolling.component.ts
+++ b/src/app/basic/horz-vert-scrolling.component.ts
@@ -27,5 +27,6 @@ import { DataService } from '../data.service';
`
})
export class HorzVertScrollingComponent {
+ static readonly exampleTitle = 'Horz/Vert Scrolling';
protected readonly rows = inject(DataService).load('100k.json');
}
diff --git a/src/app/basic/inline-editing.component.ts b/src/app/basic/inline-editing.component.ts
index 079e0496c..ab09b71f6 100644
--- a/src/app/basic/inline-editing.component.ts
+++ b/src/app/basic/inline-editing.component.ts
@@ -70,6 +70,7 @@ import { DataService } from '../data.service';
`
})
export class InlineEditingComponent {
+ static readonly exampleTitle = 'Inline Editing';
private dataService = inject(DataService);
editing: Record = {};
rows: Employee[] = [];
diff --git a/src/app/basic/large-data-set.component.ts b/src/app/basic/large-data-set.component.ts
index 5434d2259..80cf86b60 100644
--- a/src/app/basic/large-data-set.component.ts
+++ b/src/app/basic/large-data-set.component.ts
@@ -63,6 +63,7 @@ import { DataService } from '../data.service';
`
})
export class LargeDataSetComponent {
+ static readonly exampleTitle = 'Large Data Set';
private dataService = inject(DataService);
readonly rows = signal<(FullEmployee & { height: number })[]>([]);
readonly scrollTarget = signal(0);
diff --git a/src/app/basic/live-data.component.ts b/src/app/basic/live-data.component.ts
index dea491e84..d5f36074b 100644
--- a/src/app/basic/live-data.component.ts
+++ b/src/app/basic/live-data.component.ts
@@ -33,6 +33,7 @@ import { DataService } from '../data.service';
`
})
export class LiveDataComponent {
+ static readonly exampleTitle = 'Live Data';
private dataService = inject(DataService);
@ViewChild('mydatatable') mydatatable!: DatatableComponent;
diff --git a/src/app/basic/multiple-tables.component.ts b/src/app/basic/multiple-tables.component.ts
index 8c60ef629..fb9e7c9af 100644
--- a/src/app/basic/multiple-tables.component.ts
+++ b/src/app/basic/multiple-tables.component.ts
@@ -26,6 +26,7 @@ import { DatatableComponent, TableColumn } from '@siemens/ngx-datatable';
`
})
export class MultipleTablesComponent {
+ static readonly exampleTitle = 'Multiple Tables';
columns1: TableColumn[] = [{ prop: 'name' }, { name: 'Gender' }, { name: 'Company' }];
columns2: TableColumn[] = [{ prop: 'name', name: 'Name' }, { name: 'Gender' }];
diff --git a/src/app/basic/responsive.component.ts b/src/app/basic/responsive.component.ts
index e16b831e3..817f016d3 100644
--- a/src/app/basic/responsive.component.ts
+++ b/src/app/basic/responsive.component.ts
@@ -121,6 +121,7 @@ import { DataService } from '../data.service';
encapsulation: ViewEncapsulation.None
})
export class ResponsiveComponent {
+ static readonly exampleTitle = 'Responsive';
readonly rows = inject(DataService).load('100k.json');
@ViewChild('myTable') table!: DatatableComponent;
diff --git a/src/app/basic/row-detail.component.ts b/src/app/basic/row-detail.component.ts
index f15f3343e..47317317b 100644
--- a/src/app/basic/row-detail.component.ts
+++ b/src/app/basic/row-detail.component.ts
@@ -100,6 +100,7 @@ import { DataService } from '../data.service';
encapsulation: ViewEncapsulation.None
})
export class RowDetailComponent {
+ static readonly exampleTitle = 'Row Detail';
readonly rows = inject(DataService).load('100k.json');
@ViewChild('myTable') table!: DatatableComponent;
diff --git a/src/app/basic/row-grouping.component.ts b/src/app/basic/row-grouping.component.ts
index a5e09b4e3..3971ee3c8 100644
--- a/src/app/basic/row-grouping.component.ts
+++ b/src/app/basic/row-grouping.component.ts
@@ -143,6 +143,7 @@ import { DataService } from '../data.service';
`
})
export class RowGroupingComponent {
+ static readonly exampleTitle = 'Row Grouping';
private dataService = inject(DataService);
@ViewChild('myTable') table!: DatatableComponent;
diff --git a/src/app/basic/rxjs.component.ts b/src/app/basic/rxjs.component.ts
index 1fa692669..698ba044f 100644
--- a/src/app/basic/rxjs.component.ts
+++ b/src/app/basic/rxjs.component.ts
@@ -22,6 +22,7 @@ import { DataService } from '../data.service';
`
})
export class RxjsComponent {
+ static readonly exampleTitle = 'RxJS';
private dataService = inject(DataService);
rows: Observable;
diff --git a/src/app/basic/vert-dynamic-scrolling.component.ts b/src/app/basic/vert-dynamic-scrolling.component.ts
index 1027ced5f..7c09b7413 100644
--- a/src/app/basic/vert-dynamic-scrolling.component.ts
+++ b/src/app/basic/vert-dynamic-scrolling.component.ts
@@ -73,6 +73,7 @@ import { DataService } from '../data.service';
`
})
export class VertDynamicScrollingComponent {
+ static readonly exampleTitle = 'Vert Dynamic Scrolling';
private dataService = inject(DataService);
editing: Record = {};
rows: Employee[] = [];
diff --git a/src/app/columns/column-pinning.component.ts b/src/app/columns/column-pinning.component.ts
index d251010f0..90797b94a 100644
--- a/src/app/columns/column-pinning.component.ts
+++ b/src/app/columns/column-pinning.component.ts
@@ -27,5 +27,6 @@ import { DataService } from '../data.service';
`
})
export class ColumnPinningComponent {
+ static readonly exampleTitle = 'Column Pinning';
protected readonly rows = inject(DataService).load('100k.json');
}
diff --git a/src/app/columns/column-reorder.component.ts b/src/app/columns/column-reorder.component.ts
index 297904618..33ad06371 100644
--- a/src/app/columns/column-reorder.component.ts
+++ b/src/app/columns/column-reorder.component.ts
@@ -46,6 +46,7 @@ import { DataService } from '../data.service';
`
})
export class ColumnReorderComponent {
+ static readonly exampleTitle = 'Column Reorder';
private dataService = inject(DataService);
readonly rows = signal([]);
readonly loadingIndicator = signal(true);
diff --git a/src/app/columns/column-toggling.component.ts b/src/app/columns/column-toggling.component.ts
index 48f7f2b51..b2b69bc9e 100644
--- a/src/app/columns/column-toggling.component.ts
+++ b/src/app/columns/column-toggling.component.ts
@@ -40,6 +40,7 @@ import { Employee } from '../data.model';
`
})
export class ColumnTogglingComponent {
+ static readonly exampleTitle = 'Column Toggling';
rows: Employee[] = [
{
name: 'Claudine Neal',
diff --git a/src/app/columns/fixed-column.component.ts b/src/app/columns/fixed-column.component.ts
index 06f729ab2..571ed1edd 100644
--- a/src/app/columns/fixed-column.component.ts
+++ b/src/app/columns/fixed-column.component.ts
@@ -41,6 +41,7 @@ import { DataService } from '../data.service';
host: { class: 'datatable-example' }
})
export class FixedColumnComponent {
+ static readonly exampleTitle = 'Fixed Column';
protected readonly rows = inject(DataService)
.load('company.json')
.pipe(map(data => data.slice(0, 5)));
diff --git a/src/app/columns/flex-column.component.ts b/src/app/columns/flex-column.component.ts
index f666db702..934f60529 100644
--- a/src/app/columns/flex-column.component.ts
+++ b/src/app/columns/flex-column.component.ts
@@ -41,6 +41,7 @@ import { DataService } from '../data.service';
host: { class: 'datatable-example' }
})
export class FlexColumnComponent {
+ static readonly exampleTitle = 'Flex Column';
protected readonly rows = inject(DataService)
.load('company.json')
.pipe(map(data => data.slice(0, 5)));
diff --git a/src/app/columns/force-column.component.ts b/src/app/columns/force-column.component.ts
index 706ca55c7..ed5bea161 100644
--- a/src/app/columns/force-column.component.ts
+++ b/src/app/columns/force-column.component.ts
@@ -41,6 +41,7 @@ import { DataService } from '../data.service';
host: { class: 'datatable-example' }
})
export class ForceColumnComponent {
+ static readonly exampleTitle = 'Force Column';
protected readonly rows = inject(DataService)
.load('company.json')
.pipe(map(data => data.slice(0, 5)));
diff --git a/src/app/drag-drop/drag-drop.component.ts b/src/app/drag-drop/drag-drop.component.ts
index 790a3cf7a..fd1a2e47e 100644
--- a/src/app/drag-drop/drag-drop.component.ts
+++ b/src/app/drag-drop/drag-drop.component.ts
@@ -43,6 +43,7 @@ import { DataService } from '../data.service';
`
})
export class DragDropComponent {
+ static readonly exampleTitle = 'Drag Drop';
private dataService = inject(DataService);
readonly rows = signal([]);
readonly loadingIndicator = signal(true);
diff --git a/src/app/paging/client-side-paging.component.ts b/src/app/paging/client-side-paging.component.ts
index 3d76a07c8..b2930f78c 100644
--- a/src/app/paging/client-side-paging.component.ts
+++ b/src/app/paging/client-side-paging.component.ts
@@ -21,5 +21,6 @@ import { DataService } from '../data.service';
`
})
export class ClientSidePagingComponent {
+ static readonly exampleTitle = 'Client-side Paging';
protected readonly rows = inject(DataService).load('company.json');
}
diff --git a/src/app/paging/scrolling-no-virtual.component.ts b/src/app/paging/scrolling-no-virtual.component.ts
index d3d95bac7..367894d5a 100644
--- a/src/app/paging/scrolling-no-virtual.component.ts
+++ b/src/app/paging/scrolling-no-virtual.component.ts
@@ -33,6 +33,7 @@ import { Page } from './model/page';
providers: [MockServerResultsService]
})
export class ScrollingNoVirtualComponent implements OnInit {
+ static readonly exampleTitle = 'Scrolling no virtual';
private serverResultsService = inject(MockServerResultsService);
readonly page = signal({
pageNumber: 0,
diff --git a/src/app/paging/scrolling-server-side.component.ts b/src/app/paging/scrolling-server-side.component.ts
index 33d0f0b64..01cf04d35 100644
--- a/src/app/paging/scrolling-server-side.component.ts
+++ b/src/app/paging/scrolling-server-side.component.ts
@@ -48,6 +48,7 @@ export class MockServerResultsService {
providers: [MockServerResultsService]
})
export class ScrollingServerSideComponent implements OnInit {
+ static readonly exampleTitle = 'Scrolling server-side';
private serverResultsService = inject(MockServerResultsService);
private el = inject(ElementRef);
readonly headerHeight = 50;
diff --git a/src/app/paging/server-side-paging.component.ts b/src/app/paging/server-side-paging.component.ts
index e6f40d816..db59b74cc 100644
--- a/src/app/paging/server-side-paging.component.ts
+++ b/src/app/paging/server-side-paging.component.ts
@@ -29,6 +29,7 @@ import { Page } from './model/page';
providers: [MockServerResultsService]
})
export class ServerSidePagingComponent implements OnInit {
+ static readonly exampleTitle = 'Server-side Paging';
private serverResultsService = inject(MockServerResultsService);
readonly page = signal({
pageNumber: 0,
diff --git a/src/app/paging/virtual-server-side.component.ts b/src/app/paging/virtual-server-side.component.ts
index 9ef393b3f..721c76694 100644
--- a/src/app/paging/virtual-server-side.component.ts
+++ b/src/app/paging/virtual-server-side.component.ts
@@ -40,6 +40,7 @@ import { Page } from './model/page';
providers: [MockServerResultsService]
})
export class VirtualServerSideComponent {
+ static readonly exampleTitle = 'Virtual server-side';
private serverResultsService = inject(MockServerResultsService);
readonly totalElements = signal(0);
pageNumber = 0;
diff --git a/src/app/selection/cell-selection.component.ts b/src/app/selection/cell-selection.component.ts
index 8276ae482..f53e2b207 100644
--- a/src/app/selection/cell-selection.component.ts
+++ b/src/app/selection/cell-selection.component.ts
@@ -25,6 +25,7 @@ import { DataService } from '../data.service';
`
})
export class CellSelectionComponent {
+ static readonly exampleTitle = 'Cell Selection';
readonly rows = inject(DataService).load('company.json');
selected: Employee[] = [];
columns: TableColumn[] = [{ prop: 'name' }, { name: 'Company' }, { name: 'Gender' }];
diff --git a/src/app/selection/checkbox-selection.component.ts b/src/app/selection/checkbox-selection.component.ts
index 3455c65bd..aa8b03570 100644
--- a/src/app/selection/checkbox-selection.component.ts
+++ b/src/app/selection/checkbox-selection.component.ts
@@ -67,6 +67,7 @@ import { DataService } from '../data.service';
`
})
export class CheckboxSelectionComponent {
+ static readonly exampleTitle = 'Checkbox Selection';
private dataService = inject(DataService);
readonly rows = signal([]);
selected: Employee[] = [];
diff --git a/src/app/selection/custom-checkbox-selection.component.ts b/src/app/selection/custom-checkbox-selection.component.ts
index cf85f5b86..116d9c8cd 100644
--- a/src/app/selection/custom-checkbox-selection.component.ts
+++ b/src/app/selection/custom-checkbox-selection.component.ts
@@ -86,6 +86,7 @@ import { DataService } from '../data.service';
`
})
export class CustomCheckboxSelectionComponent {
+ static readonly exampleTitle = 'Custom Checkbox Selection';
private dataService = inject(DataService);
readonly rows = signal([]);
selected: Employee[] = [];
diff --git a/src/app/selection/disable-selection-callback.component.ts b/src/app/selection/disable-selection-callback.component.ts
index 0e7297790..ded38be85 100644
--- a/src/app/selection/disable-selection-callback.component.ts
+++ b/src/app/selection/disable-selection-callback.component.ts
@@ -42,6 +42,7 @@ import { DataService } from '../data.service';
`
})
export class DisableSelectionCallbackComponent {
+ static readonly exampleTitle = 'Disable Selection Callback';
readonly rows = inject(DataService).load('company.json');
selected: Employee[] = [];
diff --git a/src/app/selection/multi-click-and-checkbox-selection.component.ts b/src/app/selection/multi-click-and-checkbox-selection.component.ts
index 417e17942..c1a301157 100644
--- a/src/app/selection/multi-click-and-checkbox-selection.component.ts
+++ b/src/app/selection/multi-click-and-checkbox-selection.component.ts
@@ -68,6 +68,7 @@ import { DataService } from '../data.service';
`
})
export class MultiClickAndCheckboxSelectionComponent {
+ static readonly exampleTitle = 'Multi Click and Checkbox Selection';
private dataService = inject(DataService);
readonly rows = signal([]);
selected: Employee[] = [];
diff --git a/src/app/selection/multi-click-row-selection.component.ts b/src/app/selection/multi-click-row-selection.component.ts
index b0615a440..78bbffe6d 100644
--- a/src/app/selection/multi-click-row-selection.component.ts
+++ b/src/app/selection/multi-click-row-selection.component.ts
@@ -45,6 +45,7 @@ import { DataService } from '../data.service';
`
})
export class MultiClickRowSelectionComponent {
+ static readonly exampleTitle = 'Multi Click Row Selection';
readonly rows = inject(DataService).load('company.json');
selected: Employee[] = [];
diff --git a/src/app/selection/multi-row-selection.component.ts b/src/app/selection/multi-row-selection.component.ts
index e2d2ccc3e..cccada7b5 100644
--- a/src/app/selection/multi-row-selection.component.ts
+++ b/src/app/selection/multi-row-selection.component.ts
@@ -47,6 +47,7 @@ import { DataService } from '../data.service';
`
})
export class MultiRowSelectionComponent {
+ static readonly exampleTitle = 'Multi Row Selection';
readonly rows = inject(DataService).load('company.json');
readonly selected = signal([]);
diff --git a/src/app/selection/single-row-selection.component.ts b/src/app/selection/single-row-selection.component.ts
index 2cfdd6d07..46924a208 100644
--- a/src/app/selection/single-row-selection.component.ts
+++ b/src/app/selection/single-row-selection.component.ts
@@ -48,6 +48,7 @@ import { DataService } from '../data.service';
`
})
export class SingleRowSelectionComponent {
+ static readonly exampleTitle = 'Single Row Selection';
private dataService = inject(DataService);
readonly rows = signal([]);
diff --git a/src/app/sorting/client-side-sorting.component.ts b/src/app/sorting/client-side-sorting.component.ts
index c2c38e871..cd7297eec 100644
--- a/src/app/sorting/client-side-sorting.component.ts
+++ b/src/app/sorting/client-side-sorting.component.ts
@@ -22,6 +22,7 @@ import { DataService } from '../data.service';
`
})
export class ClientSideSortingComponent {
+ static readonly exampleTitle = 'Client-side Sorting';
protected readonly rows = inject(DataService).load('company.json');
columns: TableColumn[] = [{ name: 'Company' }, { name: 'Name' }, { name: 'Gender' }];
diff --git a/src/app/sorting/comparator.component.ts b/src/app/sorting/comparator.component.ts
index 95b1fa701..915e7635d 100644
--- a/src/app/sorting/comparator.component.ts
+++ b/src/app/sorting/comparator.component.ts
@@ -21,6 +21,7 @@ import { DataService } from '../data.service';
`
})
export class ComparatorComponent {
+ static readonly exampleTitle = 'Comparator';
protected readonly rows = inject(DataService)
.load('company.json')
.pipe(map(data => data.slice(0, 20)));
diff --git a/src/app/sorting/default-sort.component.ts b/src/app/sorting/default-sort.component.ts
index 8c5ccd3cf..d6d666fa5 100644
--- a/src/app/sorting/default-sort.component.ts
+++ b/src/app/sorting/default-sort.component.ts
@@ -40,5 +40,6 @@ import { DataService } from '../data.service';
`
})
export class DefaultSortComponent {
+ static readonly exampleTitle = 'Default Sort';
protected readonly rows = inject(DataService).load('company.json');
}
diff --git a/src/app/sorting/server-side-sorting.component.ts b/src/app/sorting/server-side-sorting.component.ts
index f0ab2b56f..793f935bd 100644
--- a/src/app/sorting/server-side-sorting.component.ts
+++ b/src/app/sorting/server-side-sorting.component.ts
@@ -23,6 +23,7 @@ import { DataService } from '../data.service';
`
})
export class ServerSideSortingComponent {
+ static readonly exampleTitle = 'Server-side Sorting';
private dataService = inject(DataService);
readonly loading = signal(false);
diff --git a/src/app/summary/custom-template-summary.component.ts b/src/app/summary/custom-template-summary.component.ts
index e65044e73..a51395a28 100644
--- a/src/app/summary/custom-template-summary.component.ts
+++ b/src/app/summary/custom-template-summary.component.ts
@@ -31,6 +31,7 @@ import { DataService } from '../data.service';
styleUrl: './custom-template-summary.component.scss'
})
export class CustomTemplateSummaryComponent implements OnInit {
+ static readonly exampleTitle = 'Custom Template Summary';
private dataService = inject(DataService);
readonly rows = signal([]);
diff --git a/src/app/summary/inline-html-summary.component.ts b/src/app/summary/inline-html-summary.component.ts
index 902fda1ae..4e1bcbe6d 100644
--- a/src/app/summary/inline-html-summary.component.ts
+++ b/src/app/summary/inline-html-summary.component.ts
@@ -28,6 +28,7 @@ import { DataService } from '../data.service';
`
})
export class InlineHtmlSummaryComponent {
+ static readonly exampleTitle = 'Inline HTML Summary';
private dataService = inject(DataService);
readonly rows = signal([]);
diff --git a/src/app/summary/server-side-paging-summary.component.ts b/src/app/summary/server-side-paging-summary.component.ts
index ab0f77965..71d024e51 100644
--- a/src/app/summary/server-side-paging-summary.component.ts
+++ b/src/app/summary/server-side-paging-summary.component.ts
@@ -30,6 +30,7 @@ import { Page } from '../paging/model/page';
providers: [MockServerResultsService]
})
export class ServerSidePagingSummaryComponent implements OnInit {
+ static readonly exampleTitle = 'Server-side Paging Summary';
private serverResultsService = inject(MockServerResultsService);
readonly page = signal({
pageNumber: 0,
diff --git a/src/app/summary/simple-summary.component.ts b/src/app/summary/simple-summary.component.ts
index 8bef5d18a..1f193baa4 100644
--- a/src/app/summary/simple-summary.component.ts
+++ b/src/app/summary/simple-summary.component.ts
@@ -42,6 +42,7 @@ import { DataService } from '../data.service';
styleUrl: './simple-summary.component.scss'
})
export class SimpleSummaryComponent {
+ static readonly exampleTitle = 'Simple Summary';
protected readonly rows = inject(DataService)
.load('company.json')
.pipe(map(data => data.slice(0, 5)));
diff --git a/src/app/summary/summary-row-actions.component.ts b/src/app/summary/summary-row-actions.component.ts
index 4f125477d..95334121c 100644
--- a/src/app/summary/summary-row-actions.component.ts
+++ b/src/app/summary/summary-row-actions.component.ts
@@ -65,6 +65,7 @@ import { DataService } from '../data.service';
`
})
export class SummaryRowActionsComponent {
+ static readonly exampleTitle = 'Summary Row Actions';
private dataService = inject(DataService);
protected readonly rows = signal([]);
protected readonly selected = signal([]);
diff --git a/src/app/templates/inline-template.component.ts b/src/app/templates/inline-template.component.ts
index 811d4b480..2c8a24824 100644
--- a/src/app/templates/inline-template.component.ts
+++ b/src/app/templates/inline-template.component.ts
@@ -56,6 +56,7 @@ import { DataService } from '../data.service';
`
})
export class InlineTemplateComponent {
+ static readonly exampleTitle = 'Inline Template';
protected readonly rows = inject(DataService)
.load('company.json')
.pipe(map(data => data.slice(0, 5)));
diff --git a/src/app/templates/template-ref.component.ts b/src/app/templates/template-ref.component.ts
index c1993cb89..320bf6700 100644
--- a/src/app/templates/template-ref.component.ts
+++ b/src/app/templates/template-ref.component.ts
@@ -34,6 +34,7 @@ import { DataService } from '../data.service';
`
})
export class TemplateRefComponent implements OnInit {
+ static readonly exampleTitle = 'TemplateRef';
readonly rows = inject(DataService)
.load('company.json')
.pipe(map(data => data.slice(0, 5)));
diff --git a/src/app/tree/client-side-tree.component.ts b/src/app/tree/client-side-tree.component.ts
index 0c158f180..d432f1358 100644
--- a/src/app/tree/client-side-tree.component.ts
+++ b/src/app/tree/client-side-tree.component.ts
@@ -43,6 +43,7 @@ import { DataService } from '../data.service';
styles: ['.icon {height: 10px; width: 10px; }', '.disabled {opacity: 0.5; }']
})
export class ClientSideTreeComponent {
+ static readonly exampleTitle = 'Client Side Tree';
protected readonly rows = inject(DataService).load('company_tree.json');
onTreeAction(event: any) {
diff --git a/src/app/tree/full-screen-tree.component.ts b/src/app/tree/full-screen-tree.component.ts
index d7664ecb8..39016d32f 100644
--- a/src/app/tree/full-screen-tree.component.ts
+++ b/src/app/tree/full-screen-tree.component.ts
@@ -60,6 +60,7 @@ import { DataService } from '../data.service';
styles: ['.icon {height: 10px; width: 10px; }', '.disabled {opacity: 0.5; }']
})
export class FullScreenTreeComponent {
+ static readonly exampleTitle = 'Full Screen Tree';
private dataService = inject(DataService);
readonly rows = signal<(FullEmployee & { treeStatus: TreeStatus; parentId?: string })[]>([]);
lastIndex = 15;
diff --git a/src/main.ts b/src/main.ts
index 34e7a2eb6..e4b94c549 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -4,8 +4,8 @@ import { bootstrapApplication } from '@angular/platform-browser';
import { provideRouter, withHashLocation } from '@angular/router';
import { providedNgxDatatableConfig } from '@siemens/ngx-datatable';
-import { routes } from './app/app-routing.module';
import { AppComponent } from './app/app.component';
+import { routes } from './app/app.routes';
bootstrapApplication(AppComponent, {
providers: [
diff --git a/src/main.web-components.ts b/src/main.web-components.ts
index 7c18d221f..cfce6bf84 100644
--- a/src/main.web-components.ts
+++ b/src/main.web-components.ts
@@ -9,6 +9,7 @@ import { createCustomElement } from '@angular/elements';
import { createApplication } from '@angular/platform-browser';
import { providedNgxDatatableConfig } from '@siemens/ngx-datatable';
+import { exampleLoaders } from './app/app.web-components';
import { DATA_ASSETS_URL } from './app/data.service';
declare global {
@@ -27,44 +28,12 @@ createApplication({
})
.then(appRef => {
window.loadDatatableExample = async example => {
- switch (example) {
- case 'fluid-row-height': {
- registerExample(
- 'ngx-datatable-fluid-row-height',
- await import('./app/basic/fluid-row-height.component').then(
- c => c.FluidRowHeightComponent
- ),
- appRef
- );
- return;
- }
- case 'standard-column': {
- registerExample(
- 'ngx-datatable-standard-column',
- await import('./app/columns/fixed-column.component').then(c => c.FixedColumnComponent),
- appRef
- );
- return;
- }
- case 'flex-column': {
- registerExample(
- 'ngx-datatable-flex-column',
- await import('./app/columns/flex-column.component').then(c => c.FlexColumnComponent),
- appRef
- );
- return;
- }
- case 'force-column': {
- registerExample(
- 'ngx-datatable-force-column',
- await import('./app/columns/force-column.component').then(c => c.ForceColumnComponent),
- appRef
- );
- return;
- }
- default:
- throw new Error(`Unknown datatable example: ${example}`);
+ const loadComponent = exampleLoaders.get(example);
+ if (!loadComponent) {
+ throw new Error(`Unknown datatable example: ${example}`);
}
+
+ registerExample(`ngx-datatable-${example}`, await loadComponent(), appRef);
};
window.dispatchEvent(new Event('ngx-datatable-examples-ready'));
diff --git a/tools/example-routes-builder/builders.json b/tools/example-routes-builder/builders.json
new file mode 100644
index 000000000..62089bbd2
--- /dev/null
+++ b/tools/example-routes-builder/builders.json
@@ -0,0 +1,8 @@
+{
+ "builders": {
+ "example-routes": {
+ "implementation": "./dist/example-routes-builder.mjs",
+ "schema": "./example-routes-builder.schema.json"
+ }
+ }
+}
diff --git a/tools/example-routes-builder/eslint.config.mjs b/tools/example-routes-builder/eslint.config.mjs
new file mode 100644
index 000000000..1c1e67f56
--- /dev/null
+++ b/tools/example-routes-builder/eslint.config.mjs
@@ -0,0 +1,13 @@
+import { defineConfig } from 'eslint/config';
+
+import { tsConfig } from '../../eslint.config.mjs';
+
+export default defineConfig({
+ extends: [...tsConfig],
+ files: ['**/*.mts'],
+ languageOptions: {
+ parserOptions: {
+ project: ['tools/example-routes-builder/tsconfig.json']
+ }
+ }
+});
diff --git a/tools/example-routes-builder/example-routes-builder.mts b/tools/example-routes-builder/example-routes-builder.mts
new file mode 100644
index 000000000..906185e4f
--- /dev/null
+++ b/tools/example-routes-builder/example-routes-builder.mts
@@ -0,0 +1,325 @@
+import { createBuilder, type BuilderContext, type BuilderOutput } from '@angular-devkit/architect';
+import { readFile, readdir, writeFile } from 'node:fs/promises';
+import { join, relative, resolve, sep } from 'node:path';
+import ts from 'typescript';
+
+interface Options {
+ sourceRoot: string;
+ routesFile: string;
+ webComponentsFile: string;
+}
+
+interface Example {
+ componentName: string;
+ filePath: string;
+ importPath: string;
+ path: string;
+}
+
+export const generateRoutes = async (options: Options, workspaceRoot: string): Promise => {
+ const sourceRoot = resolve(workspaceRoot, options.sourceRoot);
+ const examples = await getExamples(sourceRoot);
+
+ if (!examples.length) {
+ throw new Error(`No example components found in ${options.sourceRoot}.`);
+ }
+
+ const defaultExample =
+ examples.find(example => example.path === 'fluid-row-height') ?? examples[0];
+ await Promise.all([
+ writeGeneratedFile(
+ resolve(workspaceRoot, options.routesFile),
+ generateAngularRoutes(examples, defaultExample)
+ ),
+ writeGeneratedFile(
+ resolve(workspaceRoot, options.webComponentsFile),
+ generateWebComponentRoutes(examples)
+ )
+ ]);
+
+ return examples.length;
+};
+
+const execute = async (options: Options, context: BuilderContext): Promise => {
+ const count = await generateRoutes(options, context.workspaceRoot);
+ context.logger.info(`Generated routes for ${count} examples.`);
+ return { success: true };
+};
+
+const getExamples = async (sourceRoot: string): Promise => {
+ const files = await getFiles(sourceRoot);
+ const examples = await Promise.all(
+ files.filter(file => file.endsWith('.component.ts')).map(file => getExample(sourceRoot, file))
+ );
+
+ return examples
+ .filter((example): example is Example => example !== undefined)
+ .sort((a, b) => a.path.localeCompare(b.path));
+};
+
+const getFiles = async (directory: string): Promise => {
+ const entries = await readdir(directory, { withFileTypes: true });
+ const files: string[] = [];
+
+ for (const entry of entries) {
+ const path = join(directory, entry.name);
+ if (entry.isDirectory()) {
+ files.push(...(await getFiles(path)));
+ } else {
+ files.push(path);
+ }
+ }
+
+ return files;
+};
+
+const getExample = async (sourceRoot: string, filePath: string): Promise => {
+ const source = ts.createSourceFile(
+ filePath,
+ await readFile(filePath, 'utf8'),
+ ts.ScriptTarget.Latest,
+ true
+ );
+
+ for (const statement of source.statements) {
+ if (!ts.isClassDeclaration(statement) || !statement.name) {
+ continue;
+ }
+
+ const selector = getComponentSelector(statement);
+ if (!selector) {
+ continue;
+ }
+ if (!getExampleTitle(statement)) {
+ throw new Error(
+ `Example component ${statement.name.text} in ${filePath} must declare a static string exampleTitle.`
+ );
+ }
+
+ const relativePath = relative(sourceRoot, filePath).split(sep).join('/');
+ return {
+ componentName: statement.name.text,
+ filePath: relativePath,
+ importPath: `./${relativePath.replace(/\.ts$/, '')}`,
+ path: selector.replace(/-demo$/, '')
+ };
+ }
+
+ return undefined;
+};
+
+const getExampleTitle = (declaration: ts.ClassDeclaration): string | undefined => {
+ for (const member of declaration.members) {
+ if (
+ ts.isPropertyDeclaration(member) &&
+ member.modifiers?.some(modifier => modifier.kind === ts.SyntaxKind.StaticKeyword) &&
+ ts.isIdentifier(member.name) &&
+ member.name.text === 'exampleTitle' &&
+ member.initializer &&
+ ts.isStringLiteral(member.initializer)
+ ) {
+ return member.initializer.text;
+ }
+ }
+
+ return undefined;
+};
+
+const getComponentSelector = (declaration: ts.ClassDeclaration): string | undefined => {
+ for (const decorator of ts.getDecorators(declaration) ?? []) {
+ if (
+ !ts.isCallExpression(decorator.expression) ||
+ !ts.isIdentifier(decorator.expression.expression)
+ ) {
+ continue;
+ }
+ if (decorator.expression.expression.text !== 'Component') {
+ continue;
+ }
+
+ const metadata = decorator.expression.arguments[0];
+ if (!metadata || !ts.isObjectLiteralExpression(metadata)) {
+ return undefined;
+ }
+ const selector = metadata.properties.find(
+ selectorProperty =>
+ ts.isPropertyAssignment(selectorProperty) &&
+ ts.isIdentifier(selectorProperty.name) &&
+ selectorProperty.name.text === 'selector' &&
+ ts.isStringLiteral(selectorProperty.initializer)
+ );
+ if (selector && ts.isPropertyAssignment(selector) && ts.isStringLiteral(selector.initializer)) {
+ return selector.initializer.text.endsWith('-demo') ? selector.initializer.text : undefined;
+ }
+ }
+
+ return undefined;
+};
+
+const generateAngularRoutes = (examples: Example[], defaultExample: Example): string => {
+ const factory = ts.factory;
+ const routes = [
+ factory.createObjectLiteralExpression(
+ [
+ property('path', ''),
+ property('redirectTo', defaultExample.path),
+ property('pathMatch', 'full')
+ ],
+ true
+ ),
+ ...examples.map(createRoute)
+ ];
+ return printSource([
+ createNamedImport('Routes', '@angular/router'),
+ factory.createVariableStatement(
+ [factory.createModifier(ts.SyntaxKind.ExportKeyword)],
+ factory.createVariableDeclarationList(
+ [
+ factory.createVariableDeclaration(
+ 'routes',
+ undefined,
+ factory.createTypeReferenceNode('Routes'),
+ factory.createArrayLiteralExpression(routes, true)
+ )
+ ],
+ ts.NodeFlags.Const
+ )
+ )
+ ]);
+};
+
+const generateWebComponentRoutes = (examples: Example[]): string => {
+ const factory = ts.factory;
+ const loaderType = createLoaderType();
+ return printSource([
+ createNamedImport('Type', '@angular/core'),
+ factory.createVariableStatement(
+ [factory.createModifier(ts.SyntaxKind.ExportKeyword)],
+ factory.createVariableDeclarationList(
+ [
+ factory.createVariableDeclaration(
+ 'exampleLoaders',
+ undefined,
+ factory.createTypeReferenceNode('ReadonlyMap', [
+ factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
+ loaderType
+ ]),
+ factory.createNewExpression(
+ factory.createIdentifier('Map'),
+ [factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword), loaderType],
+ [
+ factory.createArrayLiteralExpression(
+ examples.map(example =>
+ factory.createArrayLiteralExpression([
+ stringLiteral(example.path),
+ createComponentLoader(example)
+ ])
+ ),
+ true
+ )
+ ]
+ )
+ )
+ ],
+ ts.NodeFlags.Const
+ )
+ )
+ ]);
+};
+
+const createLoaderType = (): ts.FunctionTypeNode => {
+ const factory = ts.factory;
+ return factory.createFunctionTypeNode(
+ undefined,
+ [],
+ factory.createTypeReferenceNode('Promise', [
+ factory.createTypeReferenceNode('Type', [
+ factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword)
+ ])
+ ])
+ );
+};
+
+const createRoute = (example: Example): ts.ObjectLiteralExpression => {
+ const factory = ts.factory;
+ return factory.createObjectLiteralExpression(
+ [
+ property('path', example.path),
+ factory.createPropertyAssignment(
+ 'data',
+ factory.createObjectLiteralExpression([property('sourcePath', example.filePath)], false)
+ ),
+ factory.createPropertyAssignment('loadComponent', createComponentLoader(example))
+ ],
+ true
+ );
+};
+
+const createComponentLoader = (example: Example): ts.ArrowFunction => {
+ const factory = ts.factory;
+ return factory.createArrowFunction(
+ undefined,
+ undefined,
+ [],
+ undefined,
+ factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
+ factory.createCallExpression(
+ factory.createPropertyAccessExpression(
+ factory.createCallExpression(factory.createIdentifier('import'), undefined, [
+ stringLiteral(example.importPath)
+ ]),
+ 'then'
+ ),
+ undefined,
+ [
+ factory.createArrowFunction(
+ undefined,
+ undefined,
+ [factory.createParameterDeclaration(undefined, undefined, 'component')],
+ undefined,
+ factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
+ factory.createPropertyAccessExpression(
+ factory.createIdentifier('component'),
+ factory.createIdentifier(example.componentName)
+ )
+ )
+ ]
+ )
+ );
+};
+
+const createNamedImport = (name: string, moduleSpecifier: string): ts.ImportDeclaration => {
+ return ts.factory.createImportDeclaration(
+ undefined,
+ ts.factory.createImportClause(
+ undefined,
+ undefined,
+ ts.factory.createNamedImports([
+ ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier(name))
+ ])
+ ),
+ stringLiteral(moduleSpecifier)
+ );
+};
+
+const property = (name: string, value: string): ts.PropertyAssignment => {
+ return ts.factory.createPropertyAssignment(name, stringLiteral(value));
+};
+
+const stringLiteral = (value: string): ts.StringLiteral => {
+ return ts.factory.createStringLiteral(value, true);
+};
+
+const writeGeneratedFile = async (filePath: string, source: string): Promise => {
+ await writeFile(filePath, source);
+};
+
+const printSource = (statements: ts.Statement[]): string => {
+ const sourceFile = ts.factory.updateSourceFile(
+ ts.createSourceFile('generated.ts', '', ts.ScriptTarget.Latest, false),
+ statements
+ );
+ return `// This file is generated by the example-routes builder. Do not edit manually.\n${ts.createPrinter({ newLine: ts.NewLineKind.LineFeed }).printFile(sourceFile)}`;
+};
+
+export default createBuilder(execute);
diff --git a/tools/example-routes-builder/example-routes-builder.schema.json b/tools/example-routes-builder/example-routes-builder.schema.json
new file mode 100644
index 000000000..60242d69d
--- /dev/null
+++ b/tools/example-routes-builder/example-routes-builder.schema.json
@@ -0,0 +1,11 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sourceRoot": { "type": "string" },
+ "routesFile": { "type": "string" },
+ "webComponentsFile": { "type": "string" }
+ },
+ "required": ["sourceRoot", "routesFile", "webComponentsFile"]
+}
diff --git a/tools/example-routes-builder/package.json b/tools/example-routes-builder/package.json
new file mode 100644
index 000000000..275a23652
--- /dev/null
+++ b/tools/example-routes-builder/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "@ngx-datatable/example-routes-builder",
+ "private": true,
+ "type": "module",
+ "builders": "./builders.json"
+}
diff --git a/tools/example-routes-builder/tsconfig.json b/tools/example-routes-builder/tsconfig.json
new file mode 100644
index 000000000..101b1f45b
--- /dev/null
+++ b/tools/example-routes-builder/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "compilerOptions": {
+ "esModuleInterop": true,
+ "module": "NodeNext",
+ "moduleResolution": "NodeNext",
+ "outDir": "./dist",
+ "rootDir": ".",
+ "skipLibCheck": true,
+ "target": "ES2022",
+ "types": ["node"]
+ },
+ "files": ["example-routes-builder.mts"]
+}
diff --git a/tsconfig.json b/tsconfig.json
index 90cb97fa1..c7cc14286 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -34,6 +34,9 @@
},
{
"path": "./projects/ngx-datatable/tsconfig.spec.json"
+ },
+ {
+ "path": "./tools/example-routes-builder/tsconfig.json"
}
]
}