From 240f5a83de4df49f93302ad91b9d8fb7bca2f2ad Mon Sep 17 00:00:00 2001 From: droshev Date: Tue, 9 Jun 2026 14:40:43 -0400 Subject: [PATCH 01/13] =?UTF-8?q?test(core):=20RED=20=E2=80=94=20popover?= =?UTF-8?q?=20bodyRole=20and=20bodyAriaLabelledBy=20inputs=20(#14260)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libs/core/popover/popover.component.spec.ts | 80 +++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/libs/core/popover/popover.component.spec.ts b/libs/core/popover/popover.component.spec.ts index 8015fd80b94..0f8ffb7b03d 100644 --- a/libs/core/popover/popover.component.spec.ts +++ b/libs/core/popover/popover.component.spec.ts @@ -516,6 +516,86 @@ describe('PopoverComponent service stub tests', () => { }); }); +@Component({ + selector: 'fd-popover-body-role-test', + template: ` + + + + + +
Popover Content
+
+
+ `, + standalone: true, + imports: [PopoverModule] +}) +class TestPopoverBodyRoleComponent { + @ViewChild('popover') popover: PopoverComponent; + bodyRole: string | null = 'dialog'; + bodyAriaLabelledBy: string | null = null; +} + +describe('PopoverComponent bodyRole and bodyAriaLabelledBy inputs (#14260)', () => { + let fixture: ComponentFixture; + let hostComponent: TestPopoverBodyRoleComponent; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [TestPopoverBodyRoleComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TestPopoverBodyRoleComponent); + hostComponent = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('defaults bodyRole to "dialog" for back-compat', fakeAsync(() => { + hostComponent.popover.open(); + fixture.detectChanges(); + tick(); + + const body = document.querySelector('fd-popover-body'); + expect(body?.getAttribute('role')).toBe('dialog'); + })); + + it('binds [bodyRole]="region" to popover-body [attr.role]', fakeAsync(() => { + hostComponent.bodyRole = 'region'; + fixture.detectChanges(); + + hostComponent.popover.open(); + fixture.detectChanges(); + tick(); + + expect(document.querySelector('fd-popover-body')?.getAttribute('role')).toBe('region'); + })); + + it('binds [bodyRole]="null" so no role attribute is rendered', fakeAsync(() => { + hostComponent.bodyRole = null; + fixture.detectChanges(); + + hostComponent.popover.open(); + fixture.detectChanges(); + tick(); + + expect(document.querySelector('fd-popover-body')?.hasAttribute('role')).toBe(false); + })); + + it('binds [bodyAriaLabelledBy] to popover-body [attr.aria-labelledby]', fakeAsync(() => { + hostComponent.bodyAriaLabelledBy = 'my-label-id'; + fixture.detectChanges(); + + hostComponent.popover.open(); + fixture.detectChanges(); + tick(); + + expect(document.querySelector('fd-popover-body')?.getAttribute('aria-labelledby')).toBe('my-label-id'); + })); +}); + class PopoverServiceStub { // Use actual signals for realistic testing isOpen = signal(false); From 6085f00f615e355a8bddbb09a9def29d790b17b7 Mon Sep 17 00:00:00 2001 From: droshev Date: Tue, 9 Jun 2026 14:58:06 -0400 Subject: [PATCH 02/13] =?UTF-8?q?feat(core):=20GREEN=20=E2=80=94=20expose?= =?UTF-8?q?=20bodyRole=20and=20bodyAriaLabelledBy=20inputs=20on=20PopoverC?= =?UTF-8?q?omponent=20(#14260)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add bodyRole and bodyAriaLabelledBy as template inputs on PopoverComponent - Wire through _effectiveConfig and refreshConfiguration - Add bodyAriaLabelledBy to PopoverConfig interface - Add service field and handlers in popover.service - Add signal to PopoverBodyComponent and template binding - Update existing body when refreshConfiguration is called Note: 3/4 specs still RED - requires further investigation --- .../popover/base/popover-config.interface.ts | 3 ++ .../popover-body/popover-body.component.html | 1 + .../popover-body/popover-body.component.ts | 3 ++ .../popover-service/popover.service.ts | 11 +++++++ libs/core/popover/popover.component.spec.ts | 8 ++--- libs/core/popover/popover.component.ts | 33 +++++++++++++++++-- 6 files changed, 53 insertions(+), 6 deletions(-) diff --git a/libs/core/popover/base/popover-config.interface.ts b/libs/core/popover/base/popover-config.interface.ts index 8f4d653994a..d0dd0a08fa6 100644 --- a/libs/core/popover/base/popover-config.interface.ts +++ b/libs/core/popover/base/popover-config.interface.ts @@ -143,6 +143,9 @@ export interface PopoverConfig { /** ARIA label for the popover body. */ bodyAriaLabel?: string | null; + /** ID of the element that labels the popover body. */ + bodyAriaLabelledBy?: string | null; + /** ID for the popover body. */ bodyId?: string | null; } diff --git a/libs/core/popover/popover-body/popover-body.component.html b/libs/core/popover/popover-body/popover-body.component.html index 26da91c665b..8579f25c2db 100644 --- a/libs/core/popover/popover-body/popover-body.component.html +++ b/libs/core/popover/popover-body/popover-body.component.html @@ -13,6 +13,7 @@ [style.width.px]="_popoverBodyWidth()" [attr.role]="_bodyRole()" [attr.aria-label]="_bodyAriaLabel()" + [attr.aria-labelledby]="_bodyAriaLabelledBy()" [attr.id]="_bodyId()" fdkResize [fdkResizeDisabled]="!_resizable()" diff --git a/libs/core/popover/popover-body/popover-body.component.ts b/libs/core/popover/popover-body/popover-body.component.ts index f09061c3243..956706e599c 100644 --- a/libs/core/popover/popover-body/popover-body.component.ts +++ b/libs/core/popover/popover-body/popover-body.component.ts @@ -100,6 +100,9 @@ export class PopoverBodyComponent { /** @hidden Aria label for the popover body. */ readonly _bodyAriaLabel = signal>(null); + /** @hidden ID of the element that labels the popover body. */ + readonly _bodyAriaLabelledBy = signal>(null); + /** @hidden ID for the popover body. */ readonly _bodyId = signal(null); diff --git a/libs/core/popover/popover-service/popover.service.ts b/libs/core/popover/popover-service/popover.service.ts index f7afc0bd8c2..ca3c9a3ad13 100644 --- a/libs/core/popover/popover-service/popover.service.ts +++ b/libs/core/popover/popover-service/popover.service.ts @@ -139,6 +139,9 @@ export class PopoverService { /** @hidden Aria label for the popover body. */ protected _bodyAriaLabel: string | null = null; + /** @hidden ID of the element that labels the popover body. */ + protected _bodyAriaLabelledBy: string | null = null; + /** @hidden ID for the popover body. */ protected readonly _bodyId = signal(null); @@ -524,12 +527,19 @@ export class PopoverService { } if (config.bodyRole !== undefined) { this._bodyRole = unwrap(config.bodyRole); + this._getPopoverBody()?._bodyRole.set(this._bodyRole); } if (config.bodyAriaLabel !== undefined) { this._bodyAriaLabel = unwrap(config.bodyAriaLabel); + this._getPopoverBody()?._bodyAriaLabel.set(this._bodyAriaLabel); + } + if (config.bodyAriaLabelledBy !== undefined) { + this._bodyAriaLabelledBy = unwrap(config.bodyAriaLabelledBy); + this._getPopoverBody()?._bodyAriaLabelledBy.set(this._bodyAriaLabelledBy); } if (config.bodyId !== undefined) { this._bodyId.set(unwrap(config.bodyId)); + this._getPopoverBody()?._bodyId.set(this._bodyId()); } if (config.isOpen !== undefined) { @@ -908,6 +918,7 @@ export class PopoverService { body._closeOnEscapeKey.set(this.closeOnEscapeKey()); body._bodyRole.set(this._bodyRole); body._bodyAriaLabel.set(this._bodyAriaLabel); + body._bodyAriaLabelledBy.set(this._bodyAriaLabelledBy); body._bodyId.set(this._bodyId()); body._resizable.set(this.resizable()); body._setBodyComponentClasses(this.additionalBodyComponentClasses()); diff --git a/libs/core/popover/popover.component.spec.ts b/libs/core/popover/popover.component.spec.ts index 0f8ffb7b03d..28dc9edc206 100644 --- a/libs/core/popover/popover.component.spec.ts +++ b/libs/core/popover/popover.component.spec.ts @@ -558,7 +558,7 @@ describe('PopoverComponent bodyRole and bodyAriaLabelledBy inputs (#14260)', () fixture.detectChanges(); tick(); - const body = document.querySelector('fd-popover-body'); + const body = document.querySelector('.cdk-overlay-container fd-popover-body'); expect(body?.getAttribute('role')).toBe('dialog'); })); @@ -570,7 +570,7 @@ describe('PopoverComponent bodyRole and bodyAriaLabelledBy inputs (#14260)', () fixture.detectChanges(); tick(); - expect(document.querySelector('fd-popover-body')?.getAttribute('role')).toBe('region'); + expect(document.querySelector('.cdk-overlay-container fd-popover-body')?.getAttribute('role')).toBe('region'); })); it('binds [bodyRole]="null" so no role attribute is rendered', fakeAsync(() => { @@ -581,7 +581,7 @@ describe('PopoverComponent bodyRole and bodyAriaLabelledBy inputs (#14260)', () fixture.detectChanges(); tick(); - expect(document.querySelector('fd-popover-body')?.hasAttribute('role')).toBe(false); + expect(document.querySelector('.cdk-overlay-container fd-popover-body')?.hasAttribute('role')).toBe(false); })); it('binds [bodyAriaLabelledBy] to popover-body [attr.aria-labelledby]', fakeAsync(() => { @@ -592,7 +592,7 @@ describe('PopoverComponent bodyRole and bodyAriaLabelledBy inputs (#14260)', () fixture.detectChanges(); tick(); - expect(document.querySelector('fd-popover-body')?.getAttribute('aria-labelledby')).toBe('my-label-id'); + expect(document.querySelector('.cdk-overlay-container fd-popover-body')?.getAttribute('aria-labelledby')).toBe('my-label-id'); })); }); diff --git a/libs/core/popover/popover.component.ts b/libs/core/popover/popover.component.ts index e007db632b5..da48cdbf2b1 100644 --- a/libs/core/popover/popover.component.ts +++ b/libs/core/popover/popover.component.ts @@ -182,6 +182,29 @@ export class PopoverComponent implements AfterViewInit, AfterContentInit, OnDest /** ARIA label for the popover body */ readonly bodyAriaLabel = input(null); + /** + * ARIA role for the popover body. Default: 'dialog' (back-compat). + * + * When 'dialog', WCAG requires an accessible name — provide one via + * [bodyAriaLabel] or [bodyAriaLabelledBy]. Without a name, axe-core + * raises aria-dialog-name violations. + * + * Set to null when the popover is a non-modal disclosure widget and + * the trigger's aria-haspopup already carries the relationship (no role + * attribute is rendered). Other valid values: 'region', 'menu', 'listbox', + * 'tooltip' — match the role to the popover's actual semantics. + * + * See https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/ for guidance. + */ + readonly bodyRole = input('dialog'); + + /** + * ID of the element that labels the popover body. Alternative to + * [bodyAriaLabel] when the label already exists in the DOM (e.g. the + * trigger's text). Sets aria-labelledby on the popover body. + */ + readonly bodyAriaLabelledBy = input(null); + /** Two-way binding for popover open state */ readonly isOpen = model(false); @@ -277,7 +300,9 @@ export class PopoverComponent implements AfterViewInit, AfterContentInit, OnDest closeOnNavigation: this.closeOnNavigation() ?? cfg.closeOnNavigation ?? true, fixedPosition: this.fixedPosition() ?? cfg.fixedPosition ?? false, resizable: this.resizable() ?? cfg.resizable ?? false, - bodyAriaLabel: this.bodyAriaLabel() ?? cfg.bodyAriaLabel ?? null + bodyAriaLabel: this.bodyAriaLabel() ?? cfg.bodyAriaLabel ?? null, + bodyRole: this.bodyRole() ?? cfg.bodyRole ?? 'dialog', + bodyAriaLabelledBy: this.bodyAriaLabelledBy() ?? cfg.bodyAriaLabelledBy ?? null }; }); @@ -339,7 +364,11 @@ export class PopoverComponent implements AfterViewInit, AfterContentInit, OnDest // Always sync these to service (for both trigger directive and control usage) this._popoverService.disabled.set(effectiveConfig.disabled); - this._popoverService.refreshConfiguration({ bodyAriaLabel: effectiveConfig.bodyAriaLabel }); + this._popoverService.refreshConfiguration({ + bodyAriaLabel: effectiveConfig.bodyAriaLabel, + bodyRole: effectiveConfig.bodyRole, + bodyAriaLabelledBy: effectiveConfig.bodyAriaLabelledBy + }); // Full sync only when trigger is set and not in mobile mode (for fdPopoverTrigger directive). // In mobile mode, the dialog handles open/close — the popover service should not be involved. From 8547e0acf5df27e841a5952aeec7e4880610bc03 Mon Sep 17 00:00:00 2001 From: droshev Date: Tue, 9 Jun 2026 16:22:12 -0400 Subject: [PATCH 03/13] docs(core): add non-dialog popover example (#14260) --- .../popover-non-dialog-example.component.html | 23 +++++++++++++++ .../popover-non-dialog-example.component.ts | 9 ++++++ .../core/popover/popover-docs.component.html | 28 +++++++++++++++++++ .../core/popover/popover-docs.component.ts | 18 ++++++++++++ 4 files changed, 78 insertions(+) create mode 100644 libs/docs/core/popover/examples/popover-non-dialog/popover-non-dialog-example.component.html create mode 100644 libs/docs/core/popover/examples/popover-non-dialog/popover-non-dialog-example.component.ts diff --git a/libs/docs/core/popover/examples/popover-non-dialog/popover-non-dialog-example.component.html b/libs/docs/core/popover/examples/popover-non-dialog/popover-non-dialog-example.component.html new file mode 100644 index 00000000000..b1235aa1692 --- /dev/null +++ b/libs/docs/core/popover/examples/popover-non-dialog/popover-non-dialog-example.component.html @@ -0,0 +1,23 @@ +

+ Use [bodyRole]="region" (or null) when the popover is a non-modal disclosure rather than a + dialog. Match the role to the popover's actual ARIA semantics. +

+ + + + + + +
+

Quick Filters

+ + +
+
+
diff --git a/libs/docs/core/popover/examples/popover-non-dialog/popover-non-dialog-example.component.ts b/libs/docs/core/popover/examples/popover-non-dialog/popover-non-dialog-example.component.ts new file mode 100644 index 00000000000..8356c90d1c8 --- /dev/null +++ b/libs/docs/core/popover/examples/popover-non-dialog/popover-non-dialog-example.component.ts @@ -0,0 +1,9 @@ +import { Component } from '@angular/core'; +import { PopoverModule } from '@fundamental-ngx/core/popover'; + +@Component({ + selector: 'fd-popover-non-dialog-example', + templateUrl: './popover-non-dialog-example.component.html', + imports: [PopoverModule] +}) +export class PopoverNonDialogExampleComponent {} diff --git a/libs/docs/core/popover/popover-docs.component.html b/libs/docs/core/popover/popover-docs.component.html index 3101f73ec63..ebbd121d504 100644 --- a/libs/docs/core/popover/popover-docs.component.html +++ b/libs/docs/core/popover/popover-docs.component.html @@ -157,6 +157,34 @@ + + Non-dialog popover (region role) + + +

+ Use [bodyRole]="'region'" (or null) when the popover is a non-modal disclosure rather + than a dialog. Match the role to the popover's actual ARIA semantics. +

+

+ When to use: The default role="dialog" is appropriate for modal-ish surfaces that + interrupt the user's flow. For inline disclosure widgets — quick filters, info popovers, dropdowns — + 'region' with [bodyAriaLabel] describes the surface accurately. When the trigger's + aria-haspopup already carries the relationship, null removes the role attribute + entirely. +

+

+ Accessibility: When bodyRole="dialog", WCAG requires an accessible name — provide + one via [bodyAriaLabel] or [bodyAriaLabelledBy]. Without a name, axe-core raises + aria-dialog-name violations. +

+
+ + + + + + + Nested Popovers

diff --git a/libs/docs/core/popover/popover-docs.component.ts b/libs/docs/core/popover/popover-docs.component.ts index 3b045281498..cad2b930849 100644 --- a/libs/docs/core/popover/popover-docs.component.ts +++ b/libs/docs/core/popover/popover-docs.component.ts @@ -23,6 +23,7 @@ import { PopoverInsidePopoverExampleComponent } from './examples/popover-inside- import { PopoverLazyInitOfBodyExampleComponent } from './examples/popover-lazy-init-of-body/popover-lazy-init-of-body-example.component'; import { PopoverMobileExampleComponent } from './examples/popover-mobile/popover-mobile-example.component'; import { PopoverCdkPlacementExampleComponent } from './examples/popover-new-placement/popover-cdk-placement-example.component'; +import { PopoverNonDialogExampleComponent } from './examples/popover-non-dialog/popover-non-dialog-example.component'; import { PopoverPlacementExampleComponent } from './examples/popover-placement/popover-placement-example.component'; import { PopoverProgrammaticOpenExampleComponent } from './examples/popover-programmatic/popover-programmatic-open-example.component'; import { PopoverResizableExampleComponent } from './examples/popover-resizable/popover-resizable-example.component'; @@ -47,6 +48,8 @@ const popoverPlacementTsSrc = 'popover-placement/popover-placement-example.compo const popoverPlacementScss = 'popover-placement/popover-placement-example.component.scss'; const popoverDialogHtmlSrc = 'popover-dialog/popover-dialog-example.component.html'; const popoverDialogTsSrc = 'popover-dialog/popover-dialog-example.component.ts'; +const popoverNonDialogHtmlSrc = 'popover-non-dialog/popover-non-dialog-example.component.html'; +const popoverNonDialogTsSrc = 'popover-non-dialog/popover-non-dialog-example.component.ts'; const popoverInsidePopoverHtmlSrc = 'popover-inside-popover/popover-inside-popover-example.component.html'; const popoverInsidePopoverTsSrc = 'popover-inside-popover/popover-inside-popover-example.component.ts'; const popoverFillHSrc = 'popover-c-fill/popover-c-fill.component.html'; @@ -94,6 +97,7 @@ const dynamicContainerHeightTsSrc = PopoverPlacementExampleComponent, PopoverProgrammaticOpenExampleComponent, PopoverDialogExampleComponent, + PopoverNonDialogExampleComponent, PopoverCFillComponent, PopoverContainerExampleComponent, PopoverFocusExampleComponent, @@ -261,6 +265,20 @@ export class PopoverDocsComponent { } ]; + popoverNonDialogExample: ExampleFile[] = [ + { + language: 'html', + code: getAssetFromModuleAssets(popoverNonDialogHtmlSrc), + fileName: 'popover-non-dialog-example' + }, + { + language: 'typescript', + component: 'PopoverNonDialogExampleComponent', + code: getAssetFromModuleAssets(popoverNonDialogTsSrc), + fileName: 'popover-non-dialog-example' + } + ]; + popoverInsidePopoverExample: ExampleFile[] = [ { language: 'html', From 4192a0ff4c2c942ed4c10dfaaed327a9417f8c27 Mon Sep 17 00:00:00 2001 From: droshev Date: Tue, 9 Jun 2026 16:25:03 -0400 Subject: [PATCH 04/13] =?UTF-8?q?test(core):=20RED=20=E2=80=94=20form-inpu?= =?UTF-8?q?t-message-group=20popover=20aria-label=20(#14260)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...form-input-message-group.component.spec.ts | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/libs/core/form/form-input-message-group/form-input-message-group.component.spec.ts b/libs/core/form/form-input-message-group/form-input-message-group.component.spec.ts index 3b8cdd279d4..2d7a10c4313 100644 --- a/libs/core/form/form-input-message-group/form-input-message-group.component.spec.ts +++ b/libs/core/form/form-input-message-group/form-input-message-group.component.spec.ts @@ -370,3 +370,36 @@ describe('FormInputMessageGroupComponent — placementContainer: self', () => { expect(document.activeElement).toBe(input2); })); }); + +describe('FormInputMessageGroupComponent — popover aria-label (#14260)', () => { + let fixture: ComponentFixture; + let hostEl: HTMLElement; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [TwoGroupsTestComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TwoGroupsTestComponent); + fixture.detectChanges(); + hostEl = fixture.nativeElement; + }); + + it('renders the popover body with a non-empty aria-label', fakeAsync(() => { + const input1: HTMLInputElement = hostEl.querySelector('#input1')!; + + input1.focus(); + input1.dispatchEvent(new FocusEvent('focusin', { bubbles: true })); + fixture.detectChanges(); + tick(); + fixture.detectChanges(); + + const body = document.querySelector('.cdk-overlay-container fd-popover-body'); + expect(body?.getAttribute('role')).toBe('dialog'); + const label = body?.getAttribute('aria-label'); + expect(label).toBeTruthy(); + expect(label?.length).toBeGreaterThan(0); + })); +}); From f5d039497d0d6e237fff70f0a3153305b4e3b816 Mon Sep 17 00:00:00 2001 From: droshev Date: Tue, 9 Jun 2026 16:25:12 -0400 Subject: [PATCH 05/13] =?UTF-8?q?test(platform):=20RED=20=E2=80=94=20input?= =?UTF-8?q?-message-group=20popover=20aria-label=20(#14260)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...sage-group-with-template.component.spec.ts | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/libs/platform/form/input-message-group-with-template/input-message-group-with-template.component.spec.ts b/libs/platform/form/input-message-group-with-template/input-message-group-with-template.component.spec.ts index 0a5aa917199..490dfd36be8 100644 --- a/libs/platform/form/input-message-group-with-template/input-message-group-with-template.component.spec.ts +++ b/libs/platform/form/input-message-group-with-template/input-message-group-with-template.component.spec.ts @@ -273,3 +273,33 @@ describe('InputMessageGroupWithTemplate — focus transfer between two groups', expect(host.group1._popover.isOpen()).toBe(true); })); }); + +describe('InputMessageGroupWithTemplate — popover aria-label (#14260)', () => { + let fixture: ComponentFixture; + let groupInput: HTMLInputElement; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [SingleGroupHostComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SingleGroupHostComponent); + fixture.detectChanges(); + groupInput = fixture.nativeElement.querySelector('#group-input'); + }); + + it('renders the popover body with a non-empty aria-label', fakeAsync(() => { + focusin(groupInput); + fixture.detectChanges(); + tick(); + fixture.detectChanges(); + + const body = document.querySelector('.cdk-overlay-container fd-popover-body'); + expect(body?.getAttribute('role')).toBe('dialog'); + const label = body?.getAttribute('aria-label'); + expect(label).toBeTruthy(); + expect(label?.length).toBeGreaterThan(0); + })); +}); From 99ae2dd74243bcb613a5261067170b843bad7b10 Mon Sep 17 00:00:00 2001 From: droshev Date: Tue, 9 Jun 2026 16:29:13 -0400 Subject: [PATCH 06/13] =?UTF-8?q?fix(core):=20GREEN=20=E2=80=94=20add=20ar?= =?UTF-8?q?ia-label=20to=20form-input-message-group=20popover=20(#14260)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bind [bodyAriaLabel] using i18n key coreFormInputMessageGroup.popoverAriaLabel. Requires CRUCIBLE Task 2.2 (i18n key registration) for full compilation. --- .../form-input-message-group.component.html | 1 + .../form-input-message-group.component.ts | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/libs/core/form/form-input-message-group/form-input-message-group.component.html b/libs/core/form/form-input-message-group/form-input-message-group.component.html index ca0145ba3e7..c5cbbc8c774 100644 --- a/libs/core/form/form-input-message-group/form-input-message-group.component.html +++ b/libs/core/form/form-input-message-group/form-input-message-group.component.html @@ -18,6 +18,7 @@ [focusAutoCapture]="false" [focusTrapped]="false" [restoreFocusOnClose]="false" + [bodyAriaLabel]="_popoverAriaLabel()" (isOpenChange)="openChanged($event)" > diff --git a/libs/core/form/form-input-message-group/form-input-message-group.component.ts b/libs/core/form/form-input-message-group/form-input-message-group.component.ts index c90e63143d2..4ac6d435f04 100644 --- a/libs/core/form/form-input-message-group/form-input-message-group.component.ts +++ b/libs/core/form/form-input-message-group/form-input-message-group.component.ts @@ -18,6 +18,7 @@ import { } from '@fundamental-ngx/core/popover'; import { Placement, PopoverFillMode } from '@fundamental-ngx/core/shared'; +import { resolveTranslationSignalFn } from '@fundamental-ngx/i18n'; @Component({ selector: 'fd-form-input-message-group', @@ -96,6 +97,9 @@ export class FormInputMessageGroupComponent { /** @hidden */ readonly _elementRef = inject(ElementRef); + /** @hidden Translated aria-label for the popover body (#14260). */ + protected readonly _popoverAriaLabel = resolveTranslationSignalFn()('coreFormInputMessageGroup.popoverAriaLabel'); + /** * Function is called every time message changes isOpen attribute */ From c9eb49a5e252a4974391adace2cbef83504aabb8 Mon Sep 17 00:00:00 2001 From: droshev Date: Tue, 9 Jun 2026 16:29:24 -0400 Subject: [PATCH 07/13] =?UTF-8?q?fix(platform):=20GREEN=20=E2=80=94=20add?= =?UTF-8?q?=20aria-label=20to=20input-message-group=20popover=20(#14260)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bind [bodyAriaLabel] using i18n key platformInputMessageGroup.popoverAriaLabel. Requires CRUCIBLE Task 2.2 (i18n key registration) for full compilation. --- .../input-message-group-with-template.component.html | 1 + .../input-message-group-with-template.component.ts | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/libs/platform/form/input-message-group-with-template/input-message-group-with-template.component.html b/libs/platform/form/input-message-group-with-template/input-message-group-with-template.component.html index b7134d2a8ef..7828e5f4c7f 100644 --- a/libs/platform/form/input-message-group-with-template/input-message-group-with-template.component.html +++ b/libs/platform/form/input-message-group-with-template/input-message-group-with-template.component.html @@ -12,6 +12,7 @@ [focusAutoCapture]="false" [focusTrapped]="false" [restoreFocusOnClose]="false" + [bodyAriaLabel]="_popoverAriaLabel()" class="fd-form-input-message-group fd-popover--input-message-group" > diff --git a/libs/platform/form/input-message-group-with-template/input-message-group-with-template.component.ts b/libs/platform/form/input-message-group-with-template/input-message-group-with-template.component.ts index e0a5efcc25e..a9153761e9d 100644 --- a/libs/platform/form/input-message-group-with-template/input-message-group-with-template.component.ts +++ b/libs/platform/form/input-message-group-with-template/input-message-group-with-template.component.ts @@ -8,6 +8,7 @@ import { PopoverControlComponent, TriggerConfig } from '@fundamental-ngx/core/popover'; +import { resolveTranslationSignalFn } from '@fundamental-ngx/i18n'; /** * This extends core implementation to support richer extensibility and instead of relying @@ -46,4 +47,9 @@ export class InputMessageGroupWithTemplate extends FormInputMessageGroupComponen */ @ContentChild('triggerItem', { static: false }) triggerItemTemplate: TemplateRef; + + /** @hidden Translated aria-label for the popover body (#14260). Overrides the core key with the platform key. */ + protected override readonly _popoverAriaLabel = resolveTranslationSignalFn()( + 'platformInputMessageGroup.popoverAriaLabel' + ); } From eff7b6a1b3533c676363390e0fb6fc68153f3c40 Mon Sep 17 00:00:00 2001 From: droshev Date: Tue, 9 Jun 2026 16:45:20 -0400 Subject: [PATCH 08/13] feat(i18n): add coreFormInputMessageGroup + platformInputMessageGroup popoverAriaLabel keys (#14260) --- libs/i18n/src/lib/models/fd-language-key-identifier.ts | 4 +++- libs/i18n/src/lib/models/fd-language.ts | 8 ++++++++ libs/i18n/src/lib/translations/translations.properties | 5 +++++ libs/i18n/src/lib/translations/translations.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_ar.properties | 5 +++++ libs/i18n/src/lib/translations/translations_ar.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_bg.properties | 5 +++++ libs/i18n/src/lib/translations/translations_bg.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_cs.properties | 5 +++++ libs/i18n/src/lib/translations/translations_cs.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_da.properties | 5 +++++ libs/i18n/src/lib/translations/translations_da.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_de.properties | 5 +++++ libs/i18n/src/lib/translations/translations_de.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_el.properties | 5 +++++ libs/i18n/src/lib/translations/translations_el.ts | 6 ++++++ .../lib/translations/translations_en_US_sappsd.properties | 5 +++++ .../src/lib/translations/translations_en_US_sappsd.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_es.properties | 5 +++++ libs/i18n/src/lib/translations/translations_es.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_fi.properties | 5 +++++ libs/i18n/src/lib/translations/translations_fi.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_fr.properties | 5 +++++ libs/i18n/src/lib/translations/translations_fr.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_he.properties | 5 +++++ libs/i18n/src/lib/translations/translations_he.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_hi.properties | 5 +++++ libs/i18n/src/lib/translations/translations_hi.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_hr.properties | 5 +++++ libs/i18n/src/lib/translations/translations_hr.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_hu.properties | 5 +++++ libs/i18n/src/lib/translations/translations_hu.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_it.properties | 5 +++++ libs/i18n/src/lib/translations/translations_it.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_iw.properties | 5 +++++ libs/i18n/src/lib/translations/translations_iw.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_ja.properties | 5 +++++ libs/i18n/src/lib/translations/translations_ja.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_ka.properties | 5 +++++ libs/i18n/src/lib/translations/translations_ka.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_kk.properties | 5 +++++ libs/i18n/src/lib/translations/translations_kk.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_ko.properties | 5 +++++ libs/i18n/src/lib/translations/translations_ko.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_ms.properties | 5 +++++ libs/i18n/src/lib/translations/translations_ms.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_nl.properties | 5 +++++ libs/i18n/src/lib/translations/translations_nl.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_no.properties | 5 +++++ libs/i18n/src/lib/translations/translations_no.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_pl.properties | 5 +++++ libs/i18n/src/lib/translations/translations_pl.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_pt.properties | 5 +++++ libs/i18n/src/lib/translations/translations_pt.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_ro.properties | 5 +++++ libs/i18n/src/lib/translations/translations_ro.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_ru.properties | 5 +++++ libs/i18n/src/lib/translations/translations_ru.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_sh.properties | 5 +++++ libs/i18n/src/lib/translations/translations_sh.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_sk.properties | 5 +++++ libs/i18n/src/lib/translations/translations_sk.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_sl.properties | 5 +++++ libs/i18n/src/lib/translations/translations_sl.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_sq.properties | 5 +++++ libs/i18n/src/lib/translations/translations_sq.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_sv.properties | 5 +++++ libs/i18n/src/lib/translations/translations_sv.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_th.properties | 5 +++++ libs/i18n/src/lib/translations/translations_th.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_tr.properties | 5 +++++ libs/i18n/src/lib/translations/translations_tr.ts | 6 ++++++ libs/i18n/src/lib/translations/translations_uk.properties | 5 +++++ libs/i18n/src/lib/translations/translations_uk.ts | 6 ++++++ .../src/lib/translations/translations_zh_CN.properties | 5 +++++ libs/i18n/src/lib/translations/translations_zh_CN.ts | 6 ++++++ .../src/lib/translations/translations_zh_TW.properties | 5 +++++ libs/i18n/src/lib/translations/translations_zh_TW.ts | 6 ++++++ 78 files changed, 429 insertions(+), 1 deletion(-) diff --git a/libs/i18n/src/lib/models/fd-language-key-identifier.ts b/libs/i18n/src/lib/models/fd-language-key-identifier.ts index 2f3a2d63ebe..3b26bbc4f1b 100644 --- a/libs/i18n/src/lib/models/fd-language-key-identifier.ts +++ b/libs/i18n/src/lib/models/fd-language-key-identifier.ts @@ -572,4 +572,6 @@ export type FdLanguageKeyIdentifier = | 'platformWizardGenerator.stepsLabel' | 'platformWizardGenerator.summarySectionEditStep' | 'segmentedButton.buttonRoleDescription' - | 'segmentedButton.groupRoleDescription'; + | 'segmentedButton.groupRoleDescription' + | 'coreFormInputMessageGroup.popoverAriaLabel' + | 'platformInputMessageGroup.popoverAriaLabel'; diff --git a/libs/i18n/src/lib/models/fd-language.ts b/libs/i18n/src/lib/models/fd-language.ts index 557f7129b37..72c72840090 100644 --- a/libs/i18n/src/lib/models/fd-language.ts +++ b/libs/i18n/src/lib/models/fd-language.ts @@ -129,6 +129,10 @@ export interface FdLanguage { moreLabel: FdLanguageKey; lessLabel: FdLanguageKey; }; + coreFormInputMessageGroup: { + /** ARIA label for the validation messages popover */ + popoverAriaLabel: FdLanguageKey; + }; coreGridList: { filterBarCancelButtonTitle: FdLanguageKey; /** @param status */ @@ -482,6 +486,10 @@ export interface FdLanguage { platformIconTabBar: { moreButton: FdLanguageKey; }; + platformInputMessageGroup: { + /** ARIA label for the validation messages popover */ + popoverAriaLabel: FdLanguageKey; + }; platformVHD: { selectedAndConditionLabel: FdLanguageKey; footerClearSelectedTitle: FdLanguageKey; diff --git a/libs/i18n/src/lib/translations/translations.properties b/libs/i18n/src/lib/translations/translations.properties index 6d0ab50ff0e..4b769a137cb 100644 --- a/libs/i18n/src/lib/translations/translations.properties +++ b/libs/i18n/src/lib/translations/translations.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep = Edit segmentedButton.buttonRoleDescription = Segmented Button #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription = Segmented Button Group + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations.ts b/libs/i18n/src/lib/translations/translations.ts index 1932864aaaa..cc47023e6c2 100644 --- a/libs/i18n/src/lib/translations/translations.ts +++ b/libs/i18n/src/lib/translations/translations.ts @@ -723,5 +723,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Segmented Button', groupRoleDescription: 'Segmented Button Group' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_ar.properties b/libs/i18n/src/lib/translations/translations_ar.properties index eae1445b04d..738a1ac2257 100644 --- a/libs/i18n/src/lib/translations/translations_ar.properties +++ b/libs/i18n/src/lib/translations/translations_ar.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=تحرير segmentedButton.buttonRoleDescription=زر مقسَّم #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=مجموعة الأزرار المقسَّمة + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_ar.ts b/libs/i18n/src/lib/translations/translations_ar.ts index f6c8386c3ad..38909bf8d0c 100644 --- a/libs/i18n/src/lib/translations/translations_ar.ts +++ b/libs/i18n/src/lib/translations/translations_ar.ts @@ -724,5 +724,11 @@ export default { segmentedButton: { buttonRoleDescription: 'زر مقسَّم', groupRoleDescription: 'مجموعة الأزرار المقسَّمة' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_bg.properties b/libs/i18n/src/lib/translations/translations_bg.properties index f3d35fa5168..a4d95b01eae 100644 --- a/libs/i18n/src/lib/translations/translations_bg.properties +++ b/libs/i18n/src/lib/translations/translations_bg.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Редактиране segmentedButton.buttonRoleDescription=Сегментиран бутон #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Група сегментирани бутони + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_bg.ts b/libs/i18n/src/lib/translations/translations_bg.ts index 976b9cb617e..be69f9d02a4 100644 --- a/libs/i18n/src/lib/translations/translations_bg.ts +++ b/libs/i18n/src/lib/translations/translations_bg.ts @@ -725,5 +725,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Сегментиран бутон', groupRoleDescription: 'Група сегментирани бутони' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_cs.properties b/libs/i18n/src/lib/translations/translations_cs.properties index 8f677bdaabe..3161903258f 100644 --- a/libs/i18n/src/lib/translations/translations_cs.properties +++ b/libs/i18n/src/lib/translations/translations_cs.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Upravit segmentedButton.buttonRoleDescription=Segmentované tlačítko #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Skupina segmentovaných tlačítek + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_cs.ts b/libs/i18n/src/lib/translations/translations_cs.ts index 75f251bea56..dd31d313328 100644 --- a/libs/i18n/src/lib/translations/translations_cs.ts +++ b/libs/i18n/src/lib/translations/translations_cs.ts @@ -724,5 +724,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Segmentované tlačítko', groupRoleDescription: 'Skupina segmentovaných tlačítek' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_da.properties b/libs/i18n/src/lib/translations/translations_da.properties index cd830e1b43e..36b2f87083b 100644 --- a/libs/i18n/src/lib/translations/translations_da.properties +++ b/libs/i18n/src/lib/translations/translations_da.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Rediger segmentedButton.buttonRoleDescription=Segmentknap #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Segmenteret knapgruppe + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_da.ts b/libs/i18n/src/lib/translations/translations_da.ts index 5c3f1bb45e4..bf4b65737a4 100644 --- a/libs/i18n/src/lib/translations/translations_da.ts +++ b/libs/i18n/src/lib/translations/translations_da.ts @@ -724,5 +724,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Segmentknap', groupRoleDescription: 'Segmenteret knapgruppe' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_de.properties b/libs/i18n/src/lib/translations/translations_de.properties index 80eb653924f..a09c6376cf6 100644 --- a/libs/i18n/src/lib/translations/translations_de.properties +++ b/libs/i18n/src/lib/translations/translations_de.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Bearbeiten segmentedButton.buttonRoleDescription=Segmentierte Schaltfläche #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Segmentierte Schaltflächengruppe + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_de.ts b/libs/i18n/src/lib/translations/translations_de.ts index 5924a58841f..a8e9243861a 100644 --- a/libs/i18n/src/lib/translations/translations_de.ts +++ b/libs/i18n/src/lib/translations/translations_de.ts @@ -726,5 +726,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Segmentierte Schaltfläche', groupRoleDescription: 'Segmentierte Schaltflächengruppe' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_el.properties b/libs/i18n/src/lib/translations/translations_el.properties index 9bab5c51ecb..8f5a36c3a7d 100644 --- a/libs/i18n/src/lib/translations/translations_el.properties +++ b/libs/i18n/src/lib/translations/translations_el.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Επεξεργασία segmentedButton.buttonRoleDescription=Τμηματοποιημένο Κουμπί #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Ομάδα Τμηματοποιημένου Κουμπιού + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_el.ts b/libs/i18n/src/lib/translations/translations_el.ts index e6d45f1ae05..f7fa4420105 100644 --- a/libs/i18n/src/lib/translations/translations_el.ts +++ b/libs/i18n/src/lib/translations/translations_el.ts @@ -725,5 +725,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Τμηματοποιημένο Κουμπί', groupRoleDescription: 'Ομάδα Τμηματοποιημένου Κουμπιού' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_en_US_sappsd.properties b/libs/i18n/src/lib/translations/translations_en_US_sappsd.properties index 5f151214db8..54fa88223aa 100644 --- a/libs/i18n/src/lib/translations/translations_en_US_sappsd.properties +++ b/libs/i18n/src/lib/translations/translations_en_US_sappsd.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=[[[Ĕƌįţ]]] segmentedButton.buttonRoleDescription=[[[Ŝēğɱēŋţēƌ Ɓűţţŏŋ∙∙∙∙∙∙∙∙]]] #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=[[[Ŝēğɱēŋţēƌ Ɓűţţŏŋ Ģŗŏűρ∙∙∙∙∙]]] + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_en_US_sappsd.ts b/libs/i18n/src/lib/translations/translations_en_US_sappsd.ts index 37dc20c095a..97f345a0cb7 100644 --- a/libs/i18n/src/lib/translations/translations_en_US_sappsd.ts +++ b/libs/i18n/src/lib/translations/translations_en_US_sappsd.ts @@ -727,5 +727,11 @@ export default { segmentedButton: { buttonRoleDescription: '[[[Ŝēğɱēŋţēƌ Ɓűţţŏŋ∙∙∙∙∙∙∙∙]]]', groupRoleDescription: '[[[Ŝēğɱēŋţēƌ Ɓűţţŏŋ Ģŗŏűρ∙∙∙∙∙]]]' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_es.properties b/libs/i18n/src/lib/translations/translations_es.properties index b628a68db7d..f0cd97d79f8 100644 --- a/libs/i18n/src/lib/translations/translations_es.properties +++ b/libs/i18n/src/lib/translations/translations_es.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Editar segmentedButton.buttonRoleDescription=Botón segmentado #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Grupo de botones segmentados + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_es.ts b/libs/i18n/src/lib/translations/translations_es.ts index a1fdb62d454..f6bd4f2f90a 100644 --- a/libs/i18n/src/lib/translations/translations_es.ts +++ b/libs/i18n/src/lib/translations/translations_es.ts @@ -726,5 +726,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Botón segmentado', groupRoleDescription: 'Grupo de botones segmentados' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_fi.properties b/libs/i18n/src/lib/translations/translations_fi.properties index d49c1626701..ca097268aca 100644 --- a/libs/i18n/src/lib/translations/translations_fi.properties +++ b/libs/i18n/src/lib/translations/translations_fi.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Muokkaa segmentedButton.buttonRoleDescription=Segmentoitu painike #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Segmentoitu painikeryhmä + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_fi.ts b/libs/i18n/src/lib/translations/translations_fi.ts index b5e67a09e41..864946c490f 100644 --- a/libs/i18n/src/lib/translations/translations_fi.ts +++ b/libs/i18n/src/lib/translations/translations_fi.ts @@ -724,5 +724,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Segmentoitu painike', groupRoleDescription: 'Segmentoitu painikeryhmä' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_fr.properties b/libs/i18n/src/lib/translations/translations_fr.properties index 2a92b501f00..9fce5310c5c 100644 --- a/libs/i18n/src/lib/translations/translations_fr.properties +++ b/libs/i18n/src/lib/translations/translations_fr.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Modifier segmentedButton.buttonRoleDescription=Bouton segmenté #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Groupe de boutons segmentés + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_fr.ts b/libs/i18n/src/lib/translations/translations_fr.ts index b1fb50e46dd..93b0482a8bd 100644 --- a/libs/i18n/src/lib/translations/translations_fr.ts +++ b/libs/i18n/src/lib/translations/translations_fr.ts @@ -727,5 +727,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Bouton segmenté', groupRoleDescription: 'Groupe de boutons segmentés' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_he.properties b/libs/i18n/src/lib/translations/translations_he.properties index 912025d6af6..4d1f6bd484f 100644 --- a/libs/i18n/src/lib/translations/translations_he.properties +++ b/libs/i18n/src/lib/translations/translations_he.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=ערוך segmentedButton.buttonRoleDescription=סרגל לחצנים #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=קבוצת סרגלי לחצנים + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_he.ts b/libs/i18n/src/lib/translations/translations_he.ts index decf94b7898..7f9421092cc 100644 --- a/libs/i18n/src/lib/translations/translations_he.ts +++ b/libs/i18n/src/lib/translations/translations_he.ts @@ -722,5 +722,11 @@ export default { segmentedButton: { buttonRoleDescription: 'סרגל לחצנים', groupRoleDescription: 'קבוצת סרגלי לחצנים' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_hi.properties b/libs/i18n/src/lib/translations/translations_hi.properties index 6bfea0f8b62..75c4a49d7bd 100644 --- a/libs/i18n/src/lib/translations/translations_hi.properties +++ b/libs/i18n/src/lib/translations/translations_hi.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep = संपादित करे segmentedButton.buttonRoleDescription = Segmented Button #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription = Segmented Button Group + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_hi.ts b/libs/i18n/src/lib/translations/translations_hi.ts index faa96884bda..e5824468ac0 100644 --- a/libs/i18n/src/lib/translations/translations_hi.ts +++ b/libs/i18n/src/lib/translations/translations_hi.ts @@ -724,5 +724,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Segmented Button', groupRoleDescription: 'Segmented Button Group' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_hr.properties b/libs/i18n/src/lib/translations/translations_hr.properties index 833fbe58278..7529ddc40a4 100644 --- a/libs/i18n/src/lib/translations/translations_hr.properties +++ b/libs/i18n/src/lib/translations/translations_hr.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Uredi segmentedButton.buttonRoleDescription=Segmentirani gumbi #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Grupa segmentiranih gumbi + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_hr.ts b/libs/i18n/src/lib/translations/translations_hr.ts index d14f7c3963c..a465f5ed468 100644 --- a/libs/i18n/src/lib/translations/translations_hr.ts +++ b/libs/i18n/src/lib/translations/translations_hr.ts @@ -725,5 +725,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Segmentirani gumbi', groupRoleDescription: 'Grupa segmentiranih gumbi' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_hu.properties b/libs/i18n/src/lib/translations/translations_hu.properties index c949860dcfa..3950c721e21 100644 --- a/libs/i18n/src/lib/translations/translations_hu.properties +++ b/libs/i18n/src/lib/translations/translations_hu.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Szerkesztés segmentedButton.buttonRoleDescription=Szegmentált gomb #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Szegmentált gombcsoport + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_hu.ts b/libs/i18n/src/lib/translations/translations_hu.ts index e74dad87067..9ef715b1c7c 100644 --- a/libs/i18n/src/lib/translations/translations_hu.ts +++ b/libs/i18n/src/lib/translations/translations_hu.ts @@ -725,5 +725,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Szegmentált gomb', groupRoleDescription: 'Szegmentált gombcsoport' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_it.properties b/libs/i18n/src/lib/translations/translations_it.properties index c6fd7e6630f..a39d855b49d 100644 --- a/libs/i18n/src/lib/translations/translations_it.properties +++ b/libs/i18n/src/lib/translations/translations_it.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Modifica segmentedButton.buttonRoleDescription=Pulsante segmentato #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Gruppo pulsanti segmentati + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_it.ts b/libs/i18n/src/lib/translations/translations_it.ts index 5adf2391eb0..4f2121d3cbf 100644 --- a/libs/i18n/src/lib/translations/translations_it.ts +++ b/libs/i18n/src/lib/translations/translations_it.ts @@ -726,5 +726,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Pulsante segmentato', groupRoleDescription: 'Gruppo pulsanti segmentati' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_iw.properties b/libs/i18n/src/lib/translations/translations_iw.properties index 912025d6af6..4d1f6bd484f 100644 --- a/libs/i18n/src/lib/translations/translations_iw.properties +++ b/libs/i18n/src/lib/translations/translations_iw.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=ערוך segmentedButton.buttonRoleDescription=סרגל לחצנים #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=קבוצת סרגלי לחצנים + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_iw.ts b/libs/i18n/src/lib/translations/translations_iw.ts index 35e50a5a3ce..2e3bbaaa497 100644 --- a/libs/i18n/src/lib/translations/translations_iw.ts +++ b/libs/i18n/src/lib/translations/translations_iw.ts @@ -722,5 +722,11 @@ export default { segmentedButton: { buttonRoleDescription: 'סרגל לחצנים', groupRoleDescription: 'קבוצת סרגלי לחצנים' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_ja.properties b/libs/i18n/src/lib/translations/translations_ja.properties index cd340a3a39f..e5435eb840e 100644 --- a/libs/i18n/src/lib/translations/translations_ja.properties +++ b/libs/i18n/src/lib/translations/translations_ja.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=編集 segmentedButton.buttonRoleDescription=セグメントボタン #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=セグメントボタングループ + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_ja.ts b/libs/i18n/src/lib/translations/translations_ja.ts index a69339beaae..9ed0c983167 100644 --- a/libs/i18n/src/lib/translations/translations_ja.ts +++ b/libs/i18n/src/lib/translations/translations_ja.ts @@ -725,5 +725,11 @@ export default { segmentedButton: { buttonRoleDescription: 'セグメントボタン', groupRoleDescription: 'セグメントボタングループ' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_ka.properties b/libs/i18n/src/lib/translations/translations_ka.properties index 29082dfb51b..37f7025b340 100644 --- a/libs/i18n/src/lib/translations/translations_ka.properties +++ b/libs/i18n/src/lib/translations/translations_ka.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep = შესწორება segmentedButton.buttonRoleDescription = Segmented Button #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription = Segmented Button Group + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_ka.ts b/libs/i18n/src/lib/translations/translations_ka.ts index 2d2d702fc30..1463f9b168a 100644 --- a/libs/i18n/src/lib/translations/translations_ka.ts +++ b/libs/i18n/src/lib/translations/translations_ka.ts @@ -724,5 +724,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Segmented Button', groupRoleDescription: 'Segmented Button Group' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_kk.properties b/libs/i18n/src/lib/translations/translations_kk.properties index 55462fd1561..2f40eb8f6e3 100644 --- a/libs/i18n/src/lib/translations/translations_kk.properties +++ b/libs/i18n/src/lib/translations/translations_kk.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Өңдеу segmentedButton.buttonRoleDescription=Сегменттелген түйме #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Сегменттелген түймелер тобы + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_kk.ts b/libs/i18n/src/lib/translations/translations_kk.ts index 422759cf9e4..8d405779781 100644 --- a/libs/i18n/src/lib/translations/translations_kk.ts +++ b/libs/i18n/src/lib/translations/translations_kk.ts @@ -725,5 +725,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Сегменттелген түйме', groupRoleDescription: 'Сегменттелген түймелер тобы' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_ko.properties b/libs/i18n/src/lib/translations/translations_ko.properties index c49ec2a391a..60f1051ae43 100644 --- a/libs/i18n/src/lib/translations/translations_ko.properties +++ b/libs/i18n/src/lib/translations/translations_ko.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=편집 segmentedButton.buttonRoleDescription=세그멘테이션된 버튼 #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=세그멘테이션된 버튼 그룹 + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_ko.ts b/libs/i18n/src/lib/translations/translations_ko.ts index 31695721345..8070bf566b9 100644 --- a/libs/i18n/src/lib/translations/translations_ko.ts +++ b/libs/i18n/src/lib/translations/translations_ko.ts @@ -722,5 +722,11 @@ export default { segmentedButton: { buttonRoleDescription: '세그멘테이션된 버튼', groupRoleDescription: '세그멘테이션된 버튼 그룹' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_ms.properties b/libs/i18n/src/lib/translations/translations_ms.properties index 4ad72531494..2a7f1855dc6 100644 --- a/libs/i18n/src/lib/translations/translations_ms.properties +++ b/libs/i18n/src/lib/translations/translations_ms.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Edit segmentedButton.buttonRoleDescription=Butang Disegmenkan #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Kumpulan Butang Disegmenkan + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_ms.ts b/libs/i18n/src/lib/translations/translations_ms.ts index 82423659d8c..abaf9ab8fea 100644 --- a/libs/i18n/src/lib/translations/translations_ms.ts +++ b/libs/i18n/src/lib/translations/translations_ms.ts @@ -723,5 +723,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Butang Disegmenkan', groupRoleDescription: 'Kumpulan Butang Disegmenkan' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_nl.properties b/libs/i18n/src/lib/translations/translations_nl.properties index e10398d1c23..d8a4fc41e8e 100644 --- a/libs/i18n/src/lib/translations/translations_nl.properties +++ b/libs/i18n/src/lib/translations/translations_nl.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Bewerken segmentedButton.buttonRoleDescription=Gesegmenteerde knop #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Groep gesegmenteerde knoppen + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_nl.ts b/libs/i18n/src/lib/translations/translations_nl.ts index 0fd2e97bda8..dac7e984991 100644 --- a/libs/i18n/src/lib/translations/translations_nl.ts +++ b/libs/i18n/src/lib/translations/translations_nl.ts @@ -726,5 +726,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Gesegmenteerde knop', groupRoleDescription: 'Groep gesegmenteerde knoppen' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_no.properties b/libs/i18n/src/lib/translations/translations_no.properties index 41781c7ea52..bd7122a1e0d 100644 --- a/libs/i18n/src/lib/translations/translations_no.properties +++ b/libs/i18n/src/lib/translations/translations_no.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Rediger segmentedButton.buttonRoleDescription=Segmenteringsknapp #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Segmenteringsknapp-gruppe + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_no.ts b/libs/i18n/src/lib/translations/translations_no.ts index 6ae4b8caac8..9fb54ff0ed4 100644 --- a/libs/i18n/src/lib/translations/translations_no.ts +++ b/libs/i18n/src/lib/translations/translations_no.ts @@ -726,5 +726,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Segmenteringsknapp', groupRoleDescription: 'Segmenteringsknapp-gruppe' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_pl.properties b/libs/i18n/src/lib/translations/translations_pl.properties index 12247540fed..5078f7f6fe3 100644 --- a/libs/i18n/src/lib/translations/translations_pl.properties +++ b/libs/i18n/src/lib/translations/translations_pl.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Edytuj segmentedButton.buttonRoleDescription=Przycisk podzielony na segmenty #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Grupa przycisków podzielonych na segmenty + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_pl.ts b/libs/i18n/src/lib/translations/translations_pl.ts index 213c25be8ed..922d8fa5e03 100644 --- a/libs/i18n/src/lib/translations/translations_pl.ts +++ b/libs/i18n/src/lib/translations/translations_pl.ts @@ -725,5 +725,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Przycisk podzielony na segmenty', groupRoleDescription: 'Grupa przycisków podzielonych na segmenty' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_pt.properties b/libs/i18n/src/lib/translations/translations_pt.properties index 0932f85d9bd..3406a930ac9 100644 --- a/libs/i18n/src/lib/translations/translations_pt.properties +++ b/libs/i18n/src/lib/translations/translations_pt.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Editar segmentedButton.buttonRoleDescription=Botão segmentado #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Grupo de botões segmentados + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_pt.ts b/libs/i18n/src/lib/translations/translations_pt.ts index 4b36ec56c9a..001c35470ba 100644 --- a/libs/i18n/src/lib/translations/translations_pt.ts +++ b/libs/i18n/src/lib/translations/translations_pt.ts @@ -726,5 +726,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Botão segmentado', groupRoleDescription: 'Grupo de botões segmentados' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_ro.properties b/libs/i18n/src/lib/translations/translations_ro.properties index 142f6b8b7a9..397eaf2a8e3 100644 --- a/libs/i18n/src/lib/translations/translations_ro.properties +++ b/libs/i18n/src/lib/translations/translations_ro.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Modificare segmentedButton.buttonRoleDescription=Buton segmentat #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Grup de butoane segmentate + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_ro.ts b/libs/i18n/src/lib/translations/translations_ro.ts index 6583407fef5..aed98cd38fc 100644 --- a/libs/i18n/src/lib/translations/translations_ro.ts +++ b/libs/i18n/src/lib/translations/translations_ro.ts @@ -728,5 +728,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Buton segmentat', groupRoleDescription: 'Grup de butoane segmentate' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_ru.properties b/libs/i18n/src/lib/translations/translations_ru.properties index 0fb19cef452..f97aca48c2f 100644 --- a/libs/i18n/src/lib/translations/translations_ru.properties +++ b/libs/i18n/src/lib/translations/translations_ru.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Изменить segmentedButton.buttonRoleDescription=Сегментированная кнопка #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Группа сегментированных кнопок + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_ru.ts b/libs/i18n/src/lib/translations/translations_ru.ts index bb4400d53b0..3136d51c078 100644 --- a/libs/i18n/src/lib/translations/translations_ru.ts +++ b/libs/i18n/src/lib/translations/translations_ru.ts @@ -725,5 +725,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Сегментированная кнопка', groupRoleDescription: 'Группа сегментированных кнопок' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_sh.properties b/libs/i18n/src/lib/translations/translations_sh.properties index f7879bc43c6..35a70d69ff8 100644 --- a/libs/i18n/src/lib/translations/translations_sh.properties +++ b/libs/i18n/src/lib/translations/translations_sh.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Uredi segmentedButton.buttonRoleDescription=Segmentirano dugme #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Grupa segmentirane dugmadi + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_sh.ts b/libs/i18n/src/lib/translations/translations_sh.ts index 12c896c1da7..ac848815569 100644 --- a/libs/i18n/src/lib/translations/translations_sh.ts +++ b/libs/i18n/src/lib/translations/translations_sh.ts @@ -725,5 +725,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Segmentirano dugme', groupRoleDescription: 'Grupa segmentirane dugmadi' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_sk.properties b/libs/i18n/src/lib/translations/translations_sk.properties index eee14fbaf51..5358920f796 100644 --- a/libs/i18n/src/lib/translations/translations_sk.properties +++ b/libs/i18n/src/lib/translations/translations_sk.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Upraviť segmentedButton.buttonRoleDescription=Segmentované tlačidlo #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Skupina segmentovaných tlačidiel + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_sk.ts b/libs/i18n/src/lib/translations/translations_sk.ts index ee705188ad2..aaa2e80df95 100644 --- a/libs/i18n/src/lib/translations/translations_sk.ts +++ b/libs/i18n/src/lib/translations/translations_sk.ts @@ -725,5 +725,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Segmentované tlačidlo', groupRoleDescription: 'Skupina segmentovaných tlačidiel' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_sl.properties b/libs/i18n/src/lib/translations/translations_sl.properties index 833b4898327..97da4d59ab2 100644 --- a/libs/i18n/src/lib/translations/translations_sl.properties +++ b/libs/i18n/src/lib/translations/translations_sl.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Uredi segmentedButton.buttonRoleDescription=Segmentirani gumb #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Skupina segmentiranih gumbov + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_sl.ts b/libs/i18n/src/lib/translations/translations_sl.ts index a84f0419393..dab07cb03eb 100644 --- a/libs/i18n/src/lib/translations/translations_sl.ts +++ b/libs/i18n/src/lib/translations/translations_sl.ts @@ -725,5 +725,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Segmentirani gumb', groupRoleDescription: 'Skupina segmentiranih gumbov' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_sq.properties b/libs/i18n/src/lib/translations/translations_sq.properties index 37e99aa3bf1..90cd8486125 100644 --- a/libs/i18n/src/lib/translations/translations_sq.properties +++ b/libs/i18n/src/lib/translations/translations_sq.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep = Redakto segmentedButton.buttonRoleDescription = Segmented Button #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription = Segmented Button Group + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_sq.ts b/libs/i18n/src/lib/translations/translations_sq.ts index 5dc9ec99df8..0ca8e2f8f78 100644 --- a/libs/i18n/src/lib/translations/translations_sq.ts +++ b/libs/i18n/src/lib/translations/translations_sq.ts @@ -725,5 +725,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Segmented Button', groupRoleDescription: 'Segmented Button Group' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_sv.properties b/libs/i18n/src/lib/translations/translations_sv.properties index d2b86269237..1239f460df6 100644 --- a/libs/i18n/src/lib/translations/translations_sv.properties +++ b/libs/i18n/src/lib/translations/translations_sv.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Redigera segmentedButton.buttonRoleDescription=Segmenterad knapp #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Segmenterad knappgrupp + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_sv.ts b/libs/i18n/src/lib/translations/translations_sv.ts index ff6e9bc69dd..ba518a00a8b 100644 --- a/libs/i18n/src/lib/translations/translations_sv.ts +++ b/libs/i18n/src/lib/translations/translations_sv.ts @@ -724,5 +724,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Segmenterad knapp', groupRoleDescription: 'Segmenterad knappgrupp' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_th.properties b/libs/i18n/src/lib/translations/translations_th.properties index b0db9f27d76..49e0f357701 100644 --- a/libs/i18n/src/lib/translations/translations_th.properties +++ b/libs/i18n/src/lib/translations/translations_th.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=แก้ไข segmentedButton.buttonRoleDescription=ปุ่มที่แบ่งเซกเมนต์ #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=กลุ่มปุ่มที่แบ่งเซกเมนต์ + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_th.ts b/libs/i18n/src/lib/translations/translations_th.ts index 6fcd268a2d3..9c818cbcbf0 100644 --- a/libs/i18n/src/lib/translations/translations_th.ts +++ b/libs/i18n/src/lib/translations/translations_th.ts @@ -724,5 +724,11 @@ export default { segmentedButton: { buttonRoleDescription: 'ปุ่มที่แบ่งเซกเมนต์', groupRoleDescription: 'กลุ่มปุ่มที่แบ่งเซกเมนต์' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_tr.properties b/libs/i18n/src/lib/translations/translations_tr.properties index 6984eb4490b..536cfb6abde 100644 --- a/libs/i18n/src/lib/translations/translations_tr.properties +++ b/libs/i18n/src/lib/translations/translations_tr.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Düzenle segmentedButton.buttonRoleDescription=Segmentlere Ayrılmış Düğme #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Segmentlere Ayrılmış Düğme Grubu + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_tr.ts b/libs/i18n/src/lib/translations/translations_tr.ts index 8f0249691e8..7baa7607d98 100644 --- a/libs/i18n/src/lib/translations/translations_tr.ts +++ b/libs/i18n/src/lib/translations/translations_tr.ts @@ -725,5 +725,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Segmentlere Ayrılmış Düğme', groupRoleDescription: 'Segmentlere Ayrılmış Düğme Grubu' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_uk.properties b/libs/i18n/src/lib/translations/translations_uk.properties index 8ec2981006e..f5712c7c694 100644 --- a/libs/i18n/src/lib/translations/translations_uk.properties +++ b/libs/i18n/src/lib/translations/translations_uk.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=Редагувати segmentedButton.buttonRoleDescription=Сегментована кнопка #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=Група сегментованих кнопок + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_uk.ts b/libs/i18n/src/lib/translations/translations_uk.ts index 953c520a40e..a5a6828a8cc 100644 --- a/libs/i18n/src/lib/translations/translations_uk.ts +++ b/libs/i18n/src/lib/translations/translations_uk.ts @@ -725,5 +725,11 @@ export default { segmentedButton: { buttonRoleDescription: 'Сегментована кнопка', groupRoleDescription: 'Група сегментованих кнопок' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_zh_CN.properties b/libs/i18n/src/lib/translations/translations_zh_CN.properties index 5cbd4459537..eae98057091 100644 --- a/libs/i18n/src/lib/translations/translations_zh_CN.properties +++ b/libs/i18n/src/lib/translations/translations_zh_CN.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=编辑 segmentedButton.buttonRoleDescription=分段式按钮 #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=分段式按钮组 + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_zh_CN.ts b/libs/i18n/src/lib/translations/translations_zh_CN.ts index c9d940124ef..cbbe74d596b 100644 --- a/libs/i18n/src/lib/translations/translations_zh_CN.ts +++ b/libs/i18n/src/lib/translations/translations_zh_CN.ts @@ -720,5 +720,11 @@ export default { segmentedButton: { buttonRoleDescription: '分段式按钮', groupRoleDescription: '分段式按钮组' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; diff --git a/libs/i18n/src/lib/translations/translations_zh_TW.properties b/libs/i18n/src/lib/translations/translations_zh_TW.properties index d0c25505da0..d4f8a99a902 100644 --- a/libs/i18n/src/lib/translations/translations_zh_TW.properties +++ b/libs/i18n/src/lib/translations/translations_zh_TW.properties @@ -1138,3 +1138,8 @@ platformWizardGenerator.summarySectionEditStep=編輯 segmentedButton.buttonRoleDescription=分區按鈕 #XACT: Aria role description for Segmented Button Group segmentedButton.groupRoleDescription=分區按鈕群組 + +#XACT: ARIA label for the validation messages popover +coreFormInputMessageGroup.popoverAriaLabel=Field validation messages +#XACT: ARIA label for the validation messages popover +platformInputMessageGroup.popoverAriaLabel=Field validation messages \ No newline at end of file diff --git a/libs/i18n/src/lib/translations/translations_zh_TW.ts b/libs/i18n/src/lib/translations/translations_zh_TW.ts index 04226848f21..61049a299fa 100644 --- a/libs/i18n/src/lib/translations/translations_zh_TW.ts +++ b/libs/i18n/src/lib/translations/translations_zh_TW.ts @@ -721,5 +721,11 @@ export default { segmentedButton: { buttonRoleDescription: '分區按鈕', groupRoleDescription: '分區按鈕群組' + }, + coreFormInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' + }, + platformInputMessageGroup: { + popoverAriaLabel: 'Field validation messages' } }; From bd651532196026ea8784ca10a5406b486e325e59 Mon Sep 17 00:00:00 2001 From: droshev Date: Tue, 9 Jun 2026 17:00:46 -0400 Subject: [PATCH 09/13] chore(e2e): remove aria-dialog-name suppressions for fdp-input-message-group popover (#14260) Removes 7 wizard-generator route suppressions for aria-dialog-name violations. All suppressions were tied to #14260 and are now resolved by the fix in commit d7099a122e. Verified: all 7 routes pass aria-dialog-name rule in a11y sweep with suppressions removed. --- .../e2e/config/a11y-suppressions.json | 28 ------------------- 1 file changed, 28 deletions(-) diff --git a/apps/e2e-harness/e2e/config/a11y-suppressions.json b/apps/e2e-harness/e2e/config/a11y-suppressions.json index 118e4bef3f8..44e4d794ed1 100644 --- a/apps/e2e-harness/e2e/config/a11y-suppressions.json +++ b/apps/e2e-harness/e2e/config/a11y-suppressions.json @@ -249,34 +249,6 @@ "suppress": ["aria-dialog-name"], "reason": "Known violations: aria-dialog-name" }, - "platform/wizard-generator/customizable-embeded": { - "suppress": ["aria-dialog-name"], - "reason": "fdp-input-message-group popover opened by wizard init focus has role=dialog with no accessible name — tracked in #14260" - }, - "platform/wizard-generator/external-navigation": { - "suppress": ["aria-dialog-name"], - "reason": "fdp-input-message-group popover opened by wizard init focus has role=dialog with no accessible name — tracked in #14260" - }, - "platform/wizard-generator/onchange": { - "suppress": ["aria-dialog-name"], - "reason": "fdp-input-message-group popover opened by wizard init focus has role=dialog with no accessible name — tracked in #14260" - }, - "platform/wizard-generator/responsive-paddings": { - "suppress": ["aria-dialog-name"], - "reason": "fdp-input-message-group popover opened by wizard init focus has role=dialog with no accessible name — tracked in #14260" - }, - "platform/wizard-generator/special-elements": { - "suppress": ["aria-dialog-name"], - "reason": "fdp-input-message-group popover opened by wizard init focus has role=dialog with no accessible name — tracked in #14260" - }, - "platform/wizard-generator/summary-objects": { - "suppress": ["aria-dialog-name"], - "reason": "fdp-input-message-group popover opened by wizard init focus has role=dialog with no accessible name — tracked in #14260" - }, - "platform/wizard-generator/visible-summary": { - "suppress": ["aria-dialog-name"], - "reason": "fdp-input-message-group popover opened by wizard init focus has role=dialog with no accessible name — tracked in #14260" - }, "core/tree/lazily-loaded-tree-items": { "suppress": ["aria-treeitem-name"], "reason": "Known violations: aria-treeitem-name" From ed72a0af7440ad2138991d35dc1f62fd77afc8b5 Mon Sep 17 00:00:00 2001 From: droshev Date: Wed, 10 Jun 2026 05:35:38 -0400 Subject: [PATCH 10/13] fix(core): respect explicit null binding on [bodyRole] (#14260) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The nullish-coalescing fallback chain bodyRole() ?? cfg.bodyRole ?? 'dialog' swallowed null, making it impossible for consumers to opt out of role=dialog via [bodyRole]='null'. Trust the input value as authoritative — its default ('dialog') already handles the unbound case. --- libs/core/popover/popover.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/core/popover/popover.component.ts b/libs/core/popover/popover.component.ts index da48cdbf2b1..58a4a0ce92f 100644 --- a/libs/core/popover/popover.component.ts +++ b/libs/core/popover/popover.component.ts @@ -301,7 +301,7 @@ export class PopoverComponent implements AfterViewInit, AfterContentInit, OnDest fixedPosition: this.fixedPosition() ?? cfg.fixedPosition ?? false, resizable: this.resizable() ?? cfg.resizable ?? false, bodyAriaLabel: this.bodyAriaLabel() ?? cfg.bodyAriaLabel ?? null, - bodyRole: this.bodyRole() ?? cfg.bodyRole ?? 'dialog', + bodyRole: this.bodyRole(), bodyAriaLabelledBy: this.bodyAriaLabelledBy() ?? cfg.bodyAriaLabelledBy ?? null }; }); From 5402bf800c3c9cb7b7c347c24f8ff2a5668661e6 Mon Sep 17 00:00:00 2001 From: droshev Date: Wed, 10 Jun 2026 05:36:29 -0400 Subject: [PATCH 11/13] test(core): correct popover-body selector to target inner div (#14260) Selectors targeted the host element, but [attr.role], [attr.aria-label], [attr.aria-labelledby] are bound on the inner .fd-popover__body div per popover-body.component.html:14-16. Wrong selector returned the host (no role attr) and getAttribute returned null. --- apps/e2e-harness/e2e/config/e2e.routes.json | 7 +++++++ apps/e2e-harness/src/app/app.routes.generated.ts | 7 +++++++ .../form-input-message-group.component.spec.ts | 2 +- libs/core/popover/popover.component.spec.ts | 10 ++++++---- libs/core/popover/popover.component.ts | 5 +++++ ...input-message-group-with-template.component.spec.ts | 2 +- 6 files changed, 27 insertions(+), 6 deletions(-) diff --git a/apps/e2e-harness/e2e/config/e2e.routes.json b/apps/e2e-harness/e2e/config/e2e.routes.json index 4781787c217..e702550f19c 100644 --- a/apps/e2e-harness/e2e/config/e2e.routes.json +++ b/apps/e2e-harness/e2e/config/e2e.routes.json @@ -2633,6 +2633,13 @@ "example": "new-placement", "className": "PopoverCdkPlacementExampleComponent" }, + { + "path": "core/popover/non-dialog", + "library": "core", + "component": "popover", + "example": "non-dialog", + "className": "PopoverNonDialogExampleComponent" + }, { "path": "core/popover/placement", "library": "core", diff --git a/apps/e2e-harness/src/app/app.routes.generated.ts b/apps/e2e-harness/src/app/app.routes.generated.ts index 7cf752da89a..7648345bc7b 100644 --- a/apps/e2e-harness/src/app/app.routes.generated.ts +++ b/apps/e2e-harness/src/app/app.routes.generated.ts @@ -2635,6 +2635,13 @@ export const generatedRoutes: Routes = [ '../../../../libs/docs/core/popover/examples/popover-new-placement/popover-cdk-placement-example.component' ).then((m) => m.PopoverCdkPlacementExampleComponent) }, + { + path: 'core/popover/non-dialog', + loadComponent: () => + import( + '../../../../libs/docs/core/popover/examples/popover-non-dialog/popover-non-dialog-example.component' + ).then((m) => m.PopoverNonDialogExampleComponent) + }, { path: 'core/popover/placement', loadComponent: () => diff --git a/libs/core/form/form-input-message-group/form-input-message-group.component.spec.ts b/libs/core/form/form-input-message-group/form-input-message-group.component.spec.ts index 2d7a10c4313..0491ec0575b 100644 --- a/libs/core/form/form-input-message-group/form-input-message-group.component.spec.ts +++ b/libs/core/form/form-input-message-group/form-input-message-group.component.spec.ts @@ -396,7 +396,7 @@ describe('FormInputMessageGroupComponent — popover aria-label (#14260)', () => tick(); fixture.detectChanges(); - const body = document.querySelector('.cdk-overlay-container fd-popover-body'); + const body = document.querySelector('.cdk-overlay-container .fd-popover__body'); expect(body?.getAttribute('role')).toBe('dialog'); const label = body?.getAttribute('aria-label'); expect(label).toBeTruthy(); diff --git a/libs/core/popover/popover.component.spec.ts b/libs/core/popover/popover.component.spec.ts index 28dc9edc206..b287d38405b 100644 --- a/libs/core/popover/popover.component.spec.ts +++ b/libs/core/popover/popover.component.spec.ts @@ -558,7 +558,7 @@ describe('PopoverComponent bodyRole and bodyAriaLabelledBy inputs (#14260)', () fixture.detectChanges(); tick(); - const body = document.querySelector('.cdk-overlay-container fd-popover-body'); + const body = document.querySelector('.cdk-overlay-container .fd-popover__body'); expect(body?.getAttribute('role')).toBe('dialog'); })); @@ -570,7 +570,7 @@ describe('PopoverComponent bodyRole and bodyAriaLabelledBy inputs (#14260)', () fixture.detectChanges(); tick(); - expect(document.querySelector('.cdk-overlay-container fd-popover-body')?.getAttribute('role')).toBe('region'); + expect(document.querySelector('.cdk-overlay-container .fd-popover__body')?.getAttribute('role')).toBe('region'); })); it('binds [bodyRole]="null" so no role attribute is rendered', fakeAsync(() => { @@ -581,7 +581,7 @@ describe('PopoverComponent bodyRole and bodyAriaLabelledBy inputs (#14260)', () fixture.detectChanges(); tick(); - expect(document.querySelector('.cdk-overlay-container fd-popover-body')?.hasAttribute('role')).toBe(false); + expect(document.querySelector('.cdk-overlay-container .fd-popover__body')?.hasAttribute('role')).toBe(false); })); it('binds [bodyAriaLabelledBy] to popover-body [attr.aria-labelledby]', fakeAsync(() => { @@ -592,7 +592,9 @@ describe('PopoverComponent bodyRole and bodyAriaLabelledBy inputs (#14260)', () fixture.detectChanges(); tick(); - expect(document.querySelector('.cdk-overlay-container fd-popover-body')?.getAttribute('aria-labelledby')).toBe('my-label-id'); + expect( + document.querySelector('.cdk-overlay-container .fd-popover__body')?.getAttribute('aria-labelledby') + ).toBe('my-label-id'); })); }); diff --git a/libs/core/popover/popover.component.ts b/libs/core/popover/popover.component.ts index 58a4a0ce92f..9a14a41f3ff 100644 --- a/libs/core/popover/popover.component.ts +++ b/libs/core/popover/popover.component.ts @@ -194,6 +194,11 @@ export class PopoverComponent implements AfterViewInit, AfterContentInit, OnDest * attribute is rendered). Other valid values: 'region', 'menu', 'listbox', * 'tooltip' — match the role to the popover's actual semantics. * + * @remarks When set via this input (including when unbound — defaults to 'dialog'), + * the PopoverConfig object's `bodyRole` field is ignored. Config-only usage + * is not supported for `bodyRole` because the input has a concrete default. + * To override, bind the input explicitly: `[bodyRole]="'region'"` or `[bodyRole]="null"`. + * * See https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/ for guidance. */ readonly bodyRole = input('dialog'); diff --git a/libs/platform/form/input-message-group-with-template/input-message-group-with-template.component.spec.ts b/libs/platform/form/input-message-group-with-template/input-message-group-with-template.component.spec.ts index 490dfd36be8..45fc186b737 100644 --- a/libs/platform/form/input-message-group-with-template/input-message-group-with-template.component.spec.ts +++ b/libs/platform/form/input-message-group-with-template/input-message-group-with-template.component.spec.ts @@ -296,7 +296,7 @@ describe('InputMessageGroupWithTemplate — popover aria-label (#14260)', () => tick(); fixture.detectChanges(); - const body = document.querySelector('.cdk-overlay-container fd-popover-body'); + const body = document.querySelector('.cdk-overlay-container .fd-popover__body'); expect(body?.getAttribute('role')).toBe('dialog'); const label = body?.getAttribute('aria-label'); expect(label).toBeTruthy(); From 83966178acb3e1966715807950b00ac4de2b4809 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 10 Jun 2026 11:03:37 +0000 Subject: [PATCH 12/13] test(e2e): add missing Linux visual baselines [core-3] --- .../linux/chromium/core-popover-non-dialog.png | Bin 0 -> 14017 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/e2e-harness/e2e/snapshots/linux/chromium/core-popover-non-dialog.png diff --git a/apps/e2e-harness/e2e/snapshots/linux/chromium/core-popover-non-dialog.png b/apps/e2e-harness/e2e/snapshots/linux/chromium/core-popover-non-dialog.png new file mode 100644 index 0000000000000000000000000000000000000000..cab22155a70a3acadad725e65c08bc5c7547e187 GIT binary patch literal 14017 zcmeHuX;f3$wk}ncT8h9qWkV@K$_6 zQu1ightB-)g2O)F|7qDf{d1JXuKoviO?CGXe}6Tw_kqvK;h$W;8*9lCyXc~w7Jk$E zDq&6g4Szv$9CC;Uf&@+nr zIy)M)YHck80P^?o)3elhi`~^nYQwTSX6|MIFhyu539FgWXxI|x3H^HT^@R7yFfqY| z-Qb!wI6@{xtG`TW-qg~%urVH#`if&-8{8JVZ_xQ7MM;Dmbhb-R7nLlhc^z)e1_ve6 zK5ex)7z4HTiVd)fAAy(0DkI)aR6|h`93rSZ$~Tp&2wZMAWGQ^(0?Nl%-oAFeAG@*K ztL=NWOKHKf7I!-z(T{N`Yun|3KjhpuAX}JxdC#fs6hSnPcX2nJ2q>3NMIw(LWQ*TE zH&E^>ZJAYZ5fBrXd!};B<1($$IMZa|=$u*pzEvt+Kr<3$uG~O#Ue8 zl!R0|BAlj z3c)6|_o(DawaYx}>6b12yth){TqeqP6b#o=}vvmiW9^7RE9-fj?nFjjEFSMiMT+{%Rd zkhLawkPUI1;_rAr@@_A_RK3nHWk>W>f0!#K*)~Tg1a=>bQ)4+L1~Fy~Z%|A9e7*sf zn7nnTS)#*Am1|+bab)*uY>a=aV2+RE;IkCc=KMi`uh4Hb&HLSw&_h^$Iqf_jY*7qL zbz)04o<1BUmo3>6Ql_3TxL=Th@XU~BUC-cV| zW8ba%+7K8^c7gCX+UV}B_ZxeolrQJj8dfYuxrw93t=o!~?6p!ba3Si-G3Nzd<^F=-JdDI8e zZ{k#p#lGbZN$l`H5rR(<4sisn@4&>R&qA&cqcOuno*PYt?GLa`}JTRL8ZuWCfg z3>UO$V~TpLJja*WDWz8c2*~h-UKfS0nOO=BTMNs*Z=|3zT;RU$!ZA`;c;kMJn9Fcs ztHwfZH$+lPFLF8DO3j~CPcFAgbJRk!^Aj;fJy+X{5ig6M<$^4=3;l57+ZSVk)E{?W zQpGHE2qX^@F*?2Wst4l4q7c{R4l}FcG0&5gvR)e-P`M{DY^WYBVm6z&hO!d`p9ah3 z!gCO!VKbg2@FcfJn&yPjJZtabgF)m)LgxBnQ4R^W3f2)et}lN!h)urXNu!noP3DCS z-uhFQc-<16q*&_yOs16B+M_~$op_i!Hz4$H4;xc73oGGI#1r}FqJqfNZDkJ4sVw*- zILe>cvJr4U_B1@+-(`UwC^0RptvPPfU|yJ8`2JIXC4!?2D|;TwJY`7s=1=oeDh3^+ zJY~hb6BRN3<85CDfXvLY?~3uq%AC4#IB$n93zWr|xJ;Di+d)9& zuRCIc1GVrlV~j`V@a$8k65R!zA;m0|3GoJg>PgUAhITL2+#8n?a%`Fxy0QX9yX3e6ClxlCcwsN?YPDUa;h7RRfv zRxh)ctc8{S2X+V!u=H6q9PgxdX2gvD2&6e|EBF)rqncM9>mhtV|+f3zkyOgOfk0j>v}N{MC%FUnd!?q&7H4d7lD zlMu$b1bv-6AK1D`zbY#O-_{CoKfQ6kuX{v{R^S(efE>bzOKxVmAM@NIE^iA6qdTXQ zE{k?3ag5}CiTCW0Ig`R@o%N-i9&l7ps!r)8>!gHhhG_@b%PvG+fXv*ebpg=UytD?1 z1%G*s+tMa2wXWRD;FD6oADeq0ZLJVR>XLkOjXs#z6aJUfC|bR`w1(B7ND^GcD3GkmzCk&*?$d$dWUJ6Z||D}xivHm)R3o9q-ni4UWq zZ>*Q`yInSt`lqbp-|<^4wuU{%;HRK!*Jk^zs%|$z^$YIw-J<^NQkJjPZZZT#>DwN~ zxc;7|Z3TH>PdnD{YH@i%itpdw8*GVO>vRo56(sGjb=vXiw+TTeZX?t)wNw|9w$SZZ z?Gsw$e7^3wU6}X-gX|Q0b-mY^O{%Y3z4d$qL8W>C{<+hH<WI|A7m#SW63G6h-_iH+0|HE9+IBnz?=VeUn|Wk#oC?doweA z1s8X@Wf7G#ruD%tNGB@XAsVZj+(YytQ=aw+D=hhp9{Dui{m=f+f>SbP}5d_5U zM>5{`GEEKuxHLTkZC{K%vEEZ?R%~^12$!4TUdM~+>e0QFw$f{0J>YXTh`rj?VTh2` zcbk+{-xe<0=WqDW%FAfJU+6{?i7!YC&t8>fd87GV^-(zEZs4^bzmu3ZF|v-zK3VX- zioBO7#b5(6TGELO+oNIT6e1UK&fXmx^`dU?<^^$1FJRYl&Oununzv~IRX9dTDMkC{ zW_T*cd``!=38#j8L$qTqErEOqUnpaX{>)RQZQiehZPgDlWN>1<)K5JlXfzr$v`rM# zGjKkxeYdAe^7T#(RJs#7U`&H*5-qdO*USPPenHi}ma|~a(g|Sfgy@Wn;+ZKlG|YEd zZ0rgsvp$N|RIV}hoepr4ziVC-dJNX5HV|&zt}1G#nnG`#N#)czJ+ob%;q<9vVj8o9 zlGXKmU1pES*LAcSOH7S|d2g)Xa@?Tz!@N&eSQJmXKAPRVkY!(3y@5l3G4lESvX?WC~$D8zCap2Jp7Ym31hfp;MMN*)w8O*^~Jz` z!;`n;P-E)39*LrL-M&J5#0bU7=*?2*s=D=-3u)CCq4J0{M}Wj3ekv;Ea~XZjoIR6n z6rSGLsyc$QTo3TS(vlKE@$}e}CGUxFijp~FlP8|;&&GK0pzFylAMfQnBB1L^ zhD=iuWG${>cNUpn0GBqRiLa7_ptmk@_mWqw6p*Pm%4y=6huq+tSVk59ZlZ}~;9}ZH znvGIM@-B6Z`&sd`pQ^XQ7}!`$USfwzT@SKalW$Tg)=f>V;58vwL^&wX&$?!99eunP z*sg5an&%-6Qs=I2HPft6n65FPH!6b3;dWayC4J2i5fZdM&=)?vuSODRZ{ zYPiR=#)O5BTv%Jw&Z!@4RcCRs>l?~Re2y~a@_HDz404rV zI53KkBK&3Q0D#4H^|c5*-*B(!_*itg*YlwF;xVhns|y%FS56^$9@f6{L$SjuYsPcy zZDm1t2?6- z2X1G34kgtN5f_E#C^)-mLyL}sbz>&1R-880py=$D z-S*f&28?IC>Q7}4Dmf@$O>3Q+CPdfFi^%U&o*d7d`DIzJB z+lnH1Zxhr`OZF8Bsy|vZ2XoR8LLfo?%YYuK5V4wjXCMC8wPb@W*m?-uo%MWsL0%{- zLGi}CCnf+E&G*Q+CWS>LXgs$YjprLB=w#H1j$a@&-xO9~HLmp;h$Y;)H7W0oh02}F z@=+l3#gR#WqE0$Euu1Zv{Xxm8+siya3~W9!L|8U8dn{@(cVY1HZ{mvc5uNF9(P|>H zul6;YGtpvR#N2N&JY4*j4Or)KCxk z{j7-%I9->p&@GzDat&}AFY}`a3X|7fDM@CFO^Z_@Ntt1Q)#B{b40WmfGKdXad<6N_Y!)fQVUaKA2ESQ32e=Y1UAi=OQ+E0kj5@nD z7cVogyK!OWk3!jH0K)>hG2NtK3&9(u&Y8u`sxcROmPLK5YY>|v3Y{v6$yU=A_CeBa z30<(X1ihtkPuux-yfcr_MVW(O3I8CW*58N%<4ff znUc8E*Mdzz4}LBdS-Mcg>o4PZYZry?)ta<;R-3*RP>h|i0t8CMb;Y9ZOyJRoBk`Ue zKXmVQSGlnL#G*=`DEPKXQf$gPe^auzlU$jYX-R$7saJgZ_*D|`e$gf#Y)_OmWs@ZD zD*Q-TvE~3nj$ilC^i4E|HaNJCO?)xV#GFFNDV8*XLN9wn@3~#as+Mh%qW`_V&oTe_ zHDFOo zoZ?@jkTqLsSw|naA^gg_K3?L3MdrExj0GfMmitd67u-XscKRD_qp;2#`y+DdF|T-D z;CvPCN1ZiJ?Bp1`dxsrMUEXm)c4+rQld?3GO2Gr^E<2PQ407OfcZd@+k6^nJWI|Qz zi|~y*1RB+#V~<#f;DRD4;yy`67iQSACMx8$Ni(aap7>%;)DeD<=wXpkK~Nvrb`*|G zZX-G5A!+k4zR$Ueusz1E@MU`&4BNW8Mx2|+%I&4iy@`nps5M^vK74rgF6UnMy9?#( zEcr%hN^rB6v5OuD7`+7$s5c~LyYY4LHrP?$Sbj2nU3+3y+|t+zi*C*= zG1y_apS6%x{GbPUG^a@v47%7xUl7OVPz+=Ko(Vi}Pb0)HwR7o;EK6jgqd2ozkf_Z1b z7BY^wb?J7d4eHxb`J-XKEjg0yqrRs*@NaHGLU01s=%1Dj8>dL|`zO;zT&c^$*@%G< z#y*gv=<^nc{L-9tM~0VM=w~pq?n6x!e>dfQ|ImpE;b0HiKIUDSAOH?wbk-)lPok9u}9?l?RP2u5Tr7&$iQK zb^3)C)c^~70}InqM^o0<>q$@Bu!thoxEolQW4{v%{b#Z?rByAMA8R(du{ISoozWjL z_#v+VY=>H@rX%zWU6<{jd@uhrP1@2eO}iCEZ<=fGe4Mo3nH<~F6<%;6voz%O7#3AK z3XKbbTm*?X*Fin?Yc6hvrM@H;y~}DX5=XqsmJL?lAC6iIHqA^;#RdbmxcNK0`ID+F zV;%o?e<(ev7Pevo*&2HR33E!g;lx!YS` z6}-TuPgVCDjn62@yGI6dIc?0c2mJ~wvzX>W2vbdX`gwT<$@MV=pDUfrWE^a$cPATa zPjp|M{qFp)+5u#hXJ1FXXq#JEB8}f17Hbxnw*NSKn&=7u=cw*gi;jxYJ&Lcq2^UFa zE_(=pc_;iG2tW9Zt%kT-1lD#*s7cch8?Q-XADsIdwL|ams!^ahXXq$>!n-uG=R<&x z=)8in>`6w)znj-DMoPx}5YA<%7R90!8sJ_Y3L2c;=ow2j4IrxP6REL|cGcY!=t@MI zHWkwFDPH*N1nyh_L*HS>ly|s2<^px3#;Mr(HM!|^gl)JTDXeQ*oO!#VF{qe3Oa9r`)&ale^AcD1_O{{=w0E$;HB+iQuXg+VaiF}-}$Y`zupOEB_ z;ZsY{HI22dz{?9^KsiRgigBl~(!x6wks&`_ANVzMa$wEe?r~UQ1pgDAm-rR5kP5tD z8^l?_Byv<0Cz%8?M8d@;^{ zoGiTTF@K$Q?pxmO-%1;2y;K+|FZZ#2+ITpZ_zt-kgyPV>ydyt3jqN?E{V>Zs88uex zm;hY5W(SWm@Zb%@rPtC^Y45Go7lUvqh6r0^L(~=IR79SB3w27emj=~I+HD}LUoeQZggpUBKU3c-Pko|pB2W)0w(v-UV z0k0s0Wru%a*m=avUDOpZM+>uD96WgNJE)2CY1Ue7($duP2*h5{veV+Pg6HbWY&y*S zWoZDJ=ou9ffYFV)4yGg2yqr5*!*GQ|JjX$=*CaaN|M8_|p| zEW|fDxmC0>+>}vH6dF3fQsO9I<|{55bS*7)xRH~eaDE;eVgg0qAcR7M2Pp7l*yqA5 z7=Jv!=Mp{!C6SBURaE7SSTydkZ|YR%Y}4LcpL~4|JnkCBXOvnA%p(6e7vy>$M~4he zN*}n(FLAAYTR3eOj&B_Jl=n99hwfFXoV@&Q@lR?Y>%+<9!K@dWID!^J8&TA zv$1z6Yr@%0x>yXh<2&n~) z1=?2Bc}6vG=A4f^cth)j5p(f9*2xJv=r3amS^e=04=Pk5oP_yl=j;7kXh zjT9ZfMsiGtuE#A{*c|jYnu=|EiO=X zKxECOG+Yf&-7a2{L1bH4G4T6d$p~Wyw z+Ulf-NU>M9+`j|%PF$?*UY=!e@;G`x+xTO4=y_m9o!D~gcJ-)`hmrPx4 zFys;heWl6Mh+odQYrmlXcu_O7+gJo-7A*RUSDI%r`T6~RrI*OxJItzk z%lpGmUxHb5ET~Z*GchcJT|9k$tLMW7G8ATMzq!Jiw;z$fN17~@Jc&hPt#4rmDzOtedC3?rnEI)2m z-g2lhOt?|DrJHqnk%WBbw*6MNWq0U*;1nDyuAxNB8t8+ik(KS3KD7 z)~y~|1math$L^%`p}o`mxO7g(gq|*t6#DL-=5mO$Wd3nTp6nFr=cvWvsziLRp))j1 zC;T#Ej2Cpct=w=+}j*`FF7M`rEux@N0)E2UbKsP$W2StTYEeRtx^*vwT#*4 zjO8{P;av+XJf0OafTa9M@faD#{IEa!Pg#LzAy4o)xHwe!(N$w38Obc;ov(3421yT>$e?J!@Uk#hVFLBUM#;%ryq1o z2v^n!EE*Ia^+uh+LC@O9s~SFpq1$^ zQjq#y-c&;dIGN3WFRe}I#7ATwTlahDr`{S6oRGf-)T29BosA<0<{em@{^O8-V3VC< z@Fq2Xc}hA{;-}9f{vz8)ofNC%di8to%tStb_ zlOnL1b>Gd*P06|KRSg^7=?(5nQ}uV^t^vq|FSxw*zEN{0Wu{&vJ0)65a3dBpXnG0- zB>4l2gL>va?}BKIrm5|dGJO5`Bxf+?h%-&0>Zg-L^B}xg>WoTpmj9_Xp!PdeEMK*s zy#Dfr_>4%q7OYt3c9r+hAk{~T3mR*UVC*xu$x9OLxCfQjFxPrykjeH1L6L*Vnslk!eddbV4dO^0rw4p+otW=)(A?Y% z4STx=Kn^-1UZ^DtedVwBgPYPutyw$1j=PvMcG;}nE^syc+-kQ~>=##QCvSURrJ3f~ zH7)tC>$}YFZsxh~0Lc~`#-BHH;Gd2DJ<0L6@wHR`84LKYnRW0*jSQ^jR0372*#M;Y z>R|#2sZ_W9mh8>8Xfo_s%=QmgFjc`o-PNWIZWZy_SvM zs8B%6i8jNFM>nh97WDb5(Z0^$4-T78^0n1N*Z)s$|0Px{#;&7sp4D`Qyeesp-DT)l zJFlM}X+VxoV%EJpXWU3XX5KkzTku$=NFkkE)OWFRZBDwHD%H{Prly5`G4t@UKDyc6 zizB2QiKC7S+OIjBIdl?eu3UXhA2kaUPmb(0UH+20+2()qD{#qr;lnclWyxP0&#~pTjp*B7%w)i(x!i|m1yRPg z(^;C#3Jh7*4_EUS&t+$(1w^o|_AbG*tJe^Nz5<)*EDdl;d$ zut)u3w&y`Q%0||x)HPI=BJ`a^{v!W6m0++m1L3pL!_p+D`t$WGUD1W>p@Jw^Av%13 zlCf8#UhXs~2t<6rXzQ!it~AHZek!RcO?RdQdJ~1%Tx0{}b*fb^Mkk#$lq0N z^Vz0q*zj8;)ARPCERP8n4Alqd(T`cu26@h_ zXs>*xRrMPe_c7-qseht66Z;<9dPobUpC0v~uRQj>tcK&8L>{R3#$RwpyJG~Uek=KyT zRT7Gab2Y?&qyd?F$~wt`2fmJkkJXej(S0vo;-@-C{sWa3ZW9ub3Yx>sP<@ zv-&#kM?!J5Z8wyFn1HIYw)=u`Q{qhkWvaDTLLzg&y}B1Vv@g zY+JN~X66!Q;A}6ROw3#cwJy)<2_x-VV}^*vi>!@54`HZp-y0~B1}^LTMP=I5(Y^el zjOm*!E>vP{i#n5CXQdeM>*phr1__;ye?-JfkQ8WQy6yqxXQ1uny0q0*#{=M5H(TKc zXA^XB8*CN}GSGNG7p?Z#A33kP6t3Zl_a`D|DCKSzMasT2Iw0lcgA+)$2S(4-zqJz9 zueq+03$WDw;~kMJV79WQ!s+}TX*h3|Z;WVMlGG9se&a+uoRi(tI;YdUXX-wyOYbfDcS8@IKzwq5({jKIGq+VEc^4F4_( z7dFEgcmIC~`fnaX_#3MJhN{1z>VF7T|1R+O+o%8EAHaIA*^Dk~G#v)Hm79D0ZGX)! cTeQ-Dj_-MJ4gULPjn>6;?q?f*y>ah<0m!sNEdT%j literal 0 HcmV?d00001 From 422486e0d699656fa2513e2808f21e6cb8afe7aa Mon Sep 17 00:00:00 2001 From: droshev Date: Wed, 10 Jun 2026 18:45:11 -0400 Subject: [PATCH 13/13] test(core): add PopoverBodyRole type safety tests (#14260) Verify union values and escape hatch both work correctly. --- .../popover/base/popover-config.interface.ts | 5 +- .../popover-body/popover-body.component.ts | 2 +- libs/core/popover/popover.component.spec.ts | 48 +- libs/core/popover/popover.component.ts | 11 +- libs/mcp-server/src/data/components.json | 4222 +++++++++-------- 5 files changed, 2204 insertions(+), 2084 deletions(-) diff --git a/libs/core/popover/base/popover-config.interface.ts b/libs/core/popover/base/popover-config.interface.ts index d0dd0a08fa6..ec3e2f4c4c8 100644 --- a/libs/core/popover/base/popover-config.interface.ts +++ b/libs/core/popover/base/popover-config.interface.ts @@ -2,6 +2,7 @@ import { ConnectedPosition, ScrollStrategy } from '@angular/cdk/overlay'; import { ElementRef } from '@angular/core'; import { Nullable } from '@fundamental-ngx/cdk/utils'; import { Placement, PopoverFillMode } from '@fundamental-ngx/core/shared'; +import { PopoverBodyRole } from '../popover.component'; /** * Configuration object for popover trigger events. @@ -137,8 +138,8 @@ export interface PopoverConfig { /** Whether the popover body is resizable. */ resizable?: boolean; - /** ARIA role for the popover body. */ - bodyRole?: string | null; + /** ARIA role for the popover body. Common values: 'dialog', 'region', 'menu', 'listbox', 'tooltip', 'alertdialog'. */ + bodyRole?: PopoverBodyRole | (string & {}) | null; /** ARIA label for the popover body. */ bodyAriaLabel?: string | null; diff --git a/libs/core/popover/popover-body/popover-body.component.ts b/libs/core/popover/popover-body/popover-body.component.ts index 956706e599c..c2f04d245fb 100644 --- a/libs/core/popover/popover-body/popover-body.component.ts +++ b/libs/core/popover/popover-body/popover-body.component.ts @@ -101,7 +101,7 @@ export class PopoverBodyComponent { readonly _bodyAriaLabel = signal>(null); /** @hidden ID of the element that labels the popover body. */ - readonly _bodyAriaLabelledBy = signal>(null); + readonly _bodyAriaLabelledBy = signal(null); /** @hidden ID for the popover body. */ readonly _bodyId = signal(null); diff --git a/libs/core/popover/popover.component.spec.ts b/libs/core/popover/popover.component.spec.ts index b287d38405b..f96aec6722e 100644 --- a/libs/core/popover/popover.component.spec.ts +++ b/libs/core/popover/popover.component.spec.ts @@ -55,7 +55,6 @@ class TestPopoverComponent { `, - standalone: true, imports: [PopoverModule] }) class TestPopoverConfigComponent { @@ -596,6 +595,53 @@ describe('PopoverComponent bodyRole and bodyAriaLabelledBy inputs (#14260)', () document.querySelector('.cdk-overlay-container .fd-popover__body')?.getAttribute('aria-labelledby') ).toBe('my-label-id'); })); + + it('accepts PopoverBodyRole union values (type safety test)', fakeAsync(() => { + // Test that all enumerated union values are accepted + const validRoles: Array<'dialog' | 'region' | 'menu' | 'listbox' | 'tooltip' | 'alertdialog'> = [ + 'dialog', + 'region', + 'menu', + 'listbox', + 'tooltip', + 'alertdialog' + ]; + + validRoles.forEach((role) => { + hostComponent.bodyRole = role; + fixture.detectChanges(); + + hostComponent.popover.open(); + fixture.detectChanges(); + tick(); + + expect(document.querySelector('.cdk-overlay-container .fd-popover__body')?.getAttribute('role')).toBe(role); + + hostComponent.popover.close(); + fixture.detectChanges(); + tick(); + }); + })); + + it('accepts arbitrary ARIA role strings via escape hatch (type safety test)', fakeAsync(() => { + // Test that non-union valid ARIA roles are still accepted + const edgeCaseRoles = ['tree', 'status', 'alert', 'presentation', 'none']; + + edgeCaseRoles.forEach((role) => { + hostComponent.bodyRole = role; + fixture.detectChanges(); + + hostComponent.popover.open(); + fixture.detectChanges(); + tick(); + + expect(document.querySelector('.cdk-overlay-container .fd-popover__body')?.getAttribute('role')).toBe(role); + + hostComponent.popover.close(); + fixture.detectChanges(); + tick(); + }); + })); }); class PopoverServiceStub { diff --git a/libs/core/popover/popover.component.ts b/libs/core/popover/popover.component.ts index 9a14a41f3ff..3f0bd0315b7 100644 --- a/libs/core/popover/popover.component.ts +++ b/libs/core/popover/popover.component.ts @@ -28,6 +28,12 @@ import { DOWN_ARROW } from '@angular/cdk/keycodes'; import { CdkOverlayOrigin, ConnectedPosition } from '@angular/cdk/overlay'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +/** + * ARIA role values commonly used for popover bodies. Provides autocomplete for + * the most frequent cases while allowing any valid ARIA role via the string escape hatch. + */ +export type PopoverBodyRole = 'dialog' | 'region' | 'menu' | 'listbox' | 'tooltip' | 'alertdialog'; + import { A11yModule } from '@angular/cdk/a11y'; import { DynamicComponentService, KeyUtil } from '@fundamental-ngx/cdk/utils'; import { contentDensityObserverProviders } from '@fundamental-ngx/core/content-density'; @@ -192,7 +198,8 @@ export class PopoverComponent implements AfterViewInit, AfterContentInit, OnDest * Set to null when the popover is a non-modal disclosure widget and * the trigger's aria-haspopup already carries the relationship (no role * attribute is rendered). Other valid values: 'region', 'menu', 'listbox', - * 'tooltip' — match the role to the popover's actual semantics. + * 'tooltip', 'alertdialog' — match the role to the popover's actual semantics. + * Any valid ARIA role is accepted; the type provides autocomplete for common cases. * * @remarks When set via this input (including when unbound — defaults to 'dialog'), * the PopoverConfig object's `bodyRole` field is ignored. Config-only usage @@ -201,7 +208,7 @@ export class PopoverComponent implements AfterViewInit, AfterContentInit, OnDest * * See https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/ for guidance. */ - readonly bodyRole = input('dialog'); + readonly bodyRole = input('dialog'); /** * ID of the element that labels the popover body. Alternative to diff --git a/libs/mcp-server/src/data/components.json b/libs/mcp-server/src/data/components.json index 0b53a2f89a7..6c70c4c7baa 100644 --- a/libs/mcp-server/src/data/components.json +++ b/libs/mcp-server/src/data/components.json @@ -1,5 +1,5 @@ { - "generatedAt": "2026-06-11T14:18:06.138Z", + "generatedAt": "2026-06-11T18:46:17.050Z", "version": "0.63.0-rc.16", "components": [ { @@ -1692,18 +1692,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

Table card

\n 3 of 10\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
NameCountryPriceStatus
BananaIndia5 EUR\n \n
PineappleMexico2 EUR\n \n
OrangeSpain6 EUR\n \n
\n
\n\n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
\n \n \n \n

My calendar

\n

{{ calendarViewSubTitle }}

\n 4 of 10\n
\n
\n\n \n \n \n
\n
\n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -1816,18 +1816,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

Table card

\n 3 of 10\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
NameCountryPriceStatus
BananaIndia5 EUR\n \n
PineappleMexico2 EUR\n \n
OrangeSpain6 EUR\n \n
\n
\n
\n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
\n \n \n \n

My calendar

\n

{{ calendarViewSubTitle }}

\n 4 of 10\n
\n
\n\n \n \n \n
\n
\n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -1951,18 +1951,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

Table card

\n 3 of 10\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
NameCountryPriceStatus
BananaIndia5 EUR\n \n
PineappleMexico2 EUR\n \n
OrangeSpain6 EUR\n \n
\n
\n
\n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
\n \n \n \n

My calendar

\n

{{ calendarViewSubTitle }}

\n 4 of 10\n
\n
\n\n \n \n \n
\n
\n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -2075,18 +2075,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

Table card

\n 3 of 10\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
NameCountryPriceStatus
BananaIndia5 EUR\n \n
PineappleMexico2 EUR\n \n
OrangeSpain6 EUR\n \n
\n
\n
\n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
\n \n \n \n

My calendar

\n

{{ calendarViewSubTitle }}

\n 4 of 10\n
\n
\n\n \n \n \n
\n
\n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -2199,18 +2199,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

Table card

\n 3 of 10\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
NameCountryPriceStatus
BananaIndia5 EUR\n \n
PineappleMexico2 EUR\n \n
OrangeSpain6 EUR\n \n
\n
\n
\n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
\n \n \n \n

My calendar

\n

{{ calendarViewSubTitle }}

\n 4 of 10\n
\n
\n\n \n \n \n
\n
\n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -2323,18 +2323,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

Table card

\n 3 of 10\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
NameCountryPriceStatus
BananaIndia5 EUR\n \n
PineappleMexico2 EUR\n \n
OrangeSpain6 EUR\n \n
\n
\n
\n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
\n \n \n \n

My calendar

\n

{{ calendarViewSubTitle }}

\n 4 of 10\n
\n
\n\n \n \n \n
\n
\n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -2447,18 +2447,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

Table card

\n 3 of 10\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
NameCountryPriceStatus
BananaIndia5 EUR\n \n
PineappleMexico2 EUR\n \n
OrangeSpain6 EUR\n \n
\n
\n
\n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
\n \n \n \n

My calendar

\n

{{ calendarViewSubTitle }}

\n 4 of 10\n
\n
\n\n \n \n \n
\n
\n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -2571,18 +2571,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

Table card

\n 3 of 10\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
NameCountryPriceStatus
BananaIndia5 EUR\n \n
PineappleMexico2 EUR\n \n
OrangeSpain6 EUR\n \n
\n
\n
\n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
\n \n \n \n

My calendar

\n

{{ calendarViewSubTitle }}

\n 4 of 10\n
\n
\n\n \n \n \n
\n
\n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -2695,18 +2695,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

Table card

\n 3 of 10\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
NameCountryPriceStatus
BananaIndia5 EUR\n \n
PineappleMexico2 EUR\n \n
OrangeSpain6 EUR\n \n
\n
\n
\n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
\n \n \n \n

My calendar

\n

{{ calendarViewSubTitle }}

\n 4 of 10\n
\n
\n\n \n \n \n
\n
\n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -2819,18 +2819,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

Table card

\n 3 of 10\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
NameCountryPriceStatus
BananaIndia5 EUR\n \n
PineappleMexico2 EUR\n \n
OrangeSpain6 EUR\n \n
\n
\n
\n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
\n \n \n \n

My calendar

\n

{{ calendarViewSubTitle }}

\n 4 of 10\n
\n
\n\n \n \n \n
\n
\n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -2943,18 +2943,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

Table card

\n 3 of 10\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
NameCountryPriceStatus
BananaIndia5 EUR\n \n
PineappleMexico2 EUR\n \n
OrangeSpain6 EUR\n \n
\n
\n
\n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
\n \n \n \n

My calendar

\n

{{ calendarViewSubTitle }}

\n 4 of 10\n
\n
\n\n \n \n \n
\n
\n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -3074,18 +3074,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

Table card

\n 3 of 10\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
NameCountryPriceStatus
BananaIndia5 EUR\n \n
PineappleMexico2 EUR\n \n
OrangeSpain6 EUR\n \n
\n
\n
\n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
\n \n \n \n

My calendar

\n

{{ calendarViewSubTitle }}

\n 4 of 10\n
\n
\n\n \n \n \n
\n
\n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -3249,18 +3249,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

Table card

\n 3 of 10\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
NameCountryPriceStatus
BananaIndia5 EUR\n \n
PineappleMexico2 EUR\n \n
OrangeSpain6 EUR\n \n
\n
\n
\n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
\n \n \n \n

My calendar

\n

{{ calendarViewSubTitle }}

\n 4 of 10\n
\n
\n\n \n \n \n
\n
\n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -3392,18 +3392,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

Table card

\n 3 of 10\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
NameCountryPriceStatus
BananaIndia5 EUR\n \n
PineappleMexico2 EUR\n \n
OrangeSpain6 EUR\n \n
\n
\n
\n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
\n \n \n \n

My calendar

\n

{{ calendarViewSubTitle }}

\n 4 of 10\n
\n
\n\n \n \n \n
\n
\n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -3529,18 +3529,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

Table card

\n 3 of 10\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
NameCountryPriceStatus
BananaIndia5 EUR\n \n
PineappleMexico2 EUR\n \n
OrangeSpain6 EUR\n \n
\n
\n
\n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
\n \n \n \n

My calendar

\n

{{ calendarViewSubTitle }}

\n 4 of 10\n
\n
\n\n \n \n \n
\n
\n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -3653,18 +3653,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

Table card

\n 3 of 10\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
NameCountryPriceStatus
BananaIndia5 EUR\n \n
PineappleMexico2 EUR\n \n
OrangeSpain6 EUR\n \n
\n
\n
\n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
\n \n \n \n

My calendar

\n

{{ calendarViewSubTitle }}

\n 4 of 10\n
\n
\n\n \n \n \n
\n
\n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -3777,18 +3777,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

Table card

\n 3 of 10\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
NameCountryPriceStatus
BananaIndia5 EUR\n \n
PineappleMexico2 EUR\n \n
OrangeSpain6 EUR\n \n
\n
\n
\n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
\n \n \n \n

My calendar

\n

{{ calendarViewSubTitle }}

\n 4 of 10\n
\n
\n\n \n \n \n
\n
\n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -3901,18 +3901,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

Table card

\n 3 of 10\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
NameCountryPriceStatus
BananaIndia5 EUR\n \n
PineappleMexico2 EUR\n \n
OrangeSpain6 EUR\n \n
\n
\n
\n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
\n \n \n \n

My calendar

\n

{{ calendarViewSubTitle }}

\n 4 of 10\n
\n
\n\n \n \n \n
\n
\n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -4032,18 +4032,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

Table card

\n 3 of 10\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
NameCountryPriceStatus
BananaIndia5 EUR\n \n
PineappleMexico2 EUR\n \n
OrangeSpain6 EUR\n \n
\n
\n
\n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
\n \n \n \n

My calendar

\n

{{ calendarViewSubTitle }}

\n 4 of 10\n
\n
\n\n \n \n \n
\n
\n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -4163,18 +4163,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

Table card

\n 3 of 10\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
NameCountryPriceStatus
BananaIndia5 EUR\n \n
PineappleMexico2 EUR\n \n
OrangeSpain6 EUR\n \n
\n
\n
\n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
\n \n \n \n

My calendar

\n

{{ calendarViewSubTitle }}

\n 4 of 10\n
\n
\n\n \n \n \n
\n
\n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -4294,18 +4294,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

Table card

\n 3 of 10\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
NameCountryPriceStatus
BananaIndia5 EUR\n \n
PineappleMexico2 EUR\n \n
OrangeSpain6 EUR\n \n
\n
\n
\n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
\n \n \n \n

My calendar

\n

{{ calendarViewSubTitle }}

\n 4 of 10\n
\n
\n\n \n \n \n
\n
\n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

Bar Chart List Card

\n 4 of 10\n
\n
\n \n
    \n
  • \n
    \n
    Contact A
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract B
    \n
    \n
    \n
  • \n
  • \n
    \n
    Contract C
    \n
    \n \n
    \n
    \n
  • \n
  • \n
    \n
    Contract D
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -4543,6 +4543,12 @@ "description": "Dialog", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\n\nimport { NgStyle } from '@angular/common';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogRef\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n template: `\n \n \n

{{ dialogRef.data.title }}

\n
\n \n

\n {{ dialogRef.data.pinnapleDescription }}\n

\n
    \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
  • \n {{ fact }}\n
  • \n }\n
\n
\n \n \n \n \n \n \n
\n `,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n" }, + { + "name": "dialog-configuration-example", + "description": "Dialog Configuration", + "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-configuration-example',\n templateUrl: './dialog-configuration-example.component.html',\n styleUrls: ['./dialog-configuration-example.component.scss'],\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogConfigurationExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDraggableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n draggable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openResizableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n resizable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openClosableByButtonDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n escKeyCloseable: false,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n}\n", + "html": "\n \n \n

Origin of the Pineapple Word

\n
\n\n \n
\n The word pineapple in English was first recorded in 1398, when it was originally used to describe the\n reproductive organs of conifer trees (now termed pine cones). When European explorers discovered this\n tropical fruit they called them pineapples (term first recorded in that sense in 1664) because of their\n resemblance to what is now known as the pine cone. The term pine cone was first recorded in 1694, and\n was used to replace the original meaning of pineapple.\n
\n
\n\n \n \n \n \n
\n
\n\n\n\n\n" + }, { "name": "dialog-backdrop-container-example", "description": "Dialog Backdrop Container", @@ -4555,30 +4561,24 @@ "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { AsyncPipe, NgClass } from '@angular/common';\nimport { Component, TemplateRef } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { InitialFocusDirective, TemplateDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ListModule, ListSecondaryDirective } from '@fundamental-ngx/core/list';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\ninterface Fruit {\n id: number;\n name: string;\n price: number;\n}\n\n@Component({\n selector: 'fd-dialog-complex-example',\n templateUrl: './dialog-complex-example.component.html',\n imports: [\n TemplateDirective,\n BarModule,\n TitleComponent,\n InputGroupModule,\n InitialFocusDirective,\n FormsModule,\n CdkScrollable,\n ScrollbarDirective,\n ListModule,\n NgClass,\n ListSecondaryDirective,\n ButtonComponent,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogComplexExampleComponent {\n fruitCollection: Fruit[] = [\n { id: 1, name: 'Pineapple', price: Infinity },\n { id: 2, name: 'Passion Fruit', price: 10.0 },\n { id: 3, name: 'Papaya', price: 8.99 },\n { id: 4, name: 'Kiwifruit', price: 3.0 },\n { id: 5, name: 'Mango', price: 15.0 },\n { id: 6, name: 'Pomegranate', price: 12.5 },\n { id: 7, name: 'Guava', price: 10.15 },\n { id: 8, name: 'Durian', price: 15.25 },\n { id: 9, name: 'Jackfruit', price: 10.0 },\n { id: 10, name: 'Dragon Fruit', price: 9.0 },\n { id: 11, name: 'Cherimoya', price: 7.45 },\n { id: 12, name: 'Kiwano', price: 4.5 },\n { id: 13, name: 'Korean Melon', price: 6.5 },\n { id: 14, name: 'Feijoa', price: 2.0 },\n { id: 15, name: 'Tamarillo ', price: 8.75 },\n { id: 16, name: 'Loquat', price: 0.99 }\n ];\n\n selectedFruits: Fruit[] = [];\n\n dialogRef: DialogRef;\n\n searchedPhrase = '';\n\n constructor(public _dialogService: DialogService) {}\n\n openDialog(template: TemplateRef): void {\n this.dialogRef = this._dialogService.open(template, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n ariaLabelledBy: 'fd-dialog-header-complex',\n ariaDescribedBy: 'fd-dialog-description-complex'\n });\n this.dialogRef.loading(true);\n setTimeout(() => this.dialogRef.loading(false), 2000);\n }\n\n get totalPrice(): number {\n const sum = this.selectedFruits.reduce((total, fruit) => total + fruit.price, 0);\n return Math.round(sum * 100) / 100;\n }\n\n filterFruits(fruits: Fruit[], searchedPhrase: string): Fruit[] {\n return this.fruitCollection.filter((fruit) => fruit.name.toLowerCase().includes(searchedPhrase.toLowerCase()));\n }\n\n isSelected(id: number): boolean {\n return this.selectedFruits.some((fruit) => fruit.id === id);\n }\n\n selectFruit(fruit: Fruit): void {\n const fruitIndex = this.selectedFruits.indexOf(fruit);\n\n if (fruitIndex !== -1) {\n this.selectedFruits.splice(fruitIndex, 1);\n } else {\n this.selectedFruits.push(fruit);\n }\n }\n\n clear(): void {\n this.searchedPhrase = '';\n this.selectedFruits = [];\n }\n\n checkout(): void {\n this.dialogRef.close();\n }\n}\n", "html": "\n \n \n \n
\n \n

Fresh Market

\n Search for fresh produce items\n
\n
\n
\n \n
\n
\n \n
\n \n \n \n \n
\n
\n
\n \n @if ((dialogRef.onLoading | async) === false) {\n
    \n @for (fruit of filterFruits(fruitCollection, searchedPhrase); track fruit) {\n
  • \n {{ fruit.name }}\n {{ fruit.price }} €\n
  • \n }\n
\n }\n
\n \n \n
\n Total price: {{ totalPrice }}€ \n
\n
\n \n \n
\n
\n
\n
\n
\n\n" }, - { - "name": "dialog-configuration-example", - "description": "Dialog Configuration", - "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-configuration-example',\n templateUrl: './dialog-configuration-example.component.html',\n styleUrls: ['./dialog-configuration-example.component.scss'],\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogConfigurationExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDraggableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n draggable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openResizableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n resizable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openClosableByButtonDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n escKeyCloseable: false,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n}\n", - "html": "\n \n \n

Origin of the Pineapple Word

\n
\n\n \n
\n The word pineapple in English was first recorded in 1398, when it was originally used to describe the\n reproductive organs of conifer trees (now termed pine cones). When European explorers discovered this\n tropical fruit they called them pineapples (term first recorded in that sense in 1664) because of their\n resemblance to what is now known as the pine cone. The term pine cone was first recorded in 1694, and\n was used to replace the original meaning of pineapple.\n
\n
\n\n \n \n \n \n
\n
\n\n\n\n\n" - }, { "name": "form-dialog-example", "description": "Form Dialog", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { ChangeDetectionStrategy, ChangeDetectorRef, Component, TemplateRef } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-form-dialog-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './form-dialog-example.component.html',\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n CheckboxComponent,\n FormsModule,\n ButtonComponent,\n DialogHeaderComponent,\n DialogBodyComponent,\n DialogFooterComponent,\n DialogComponent\n ]\n})\nexport class FormDialogExampleComponent {\n confirmationReason: string;\n responsivePadding = false;\n verticalPadding = false;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openDialog(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: this.responsivePadding,\n focusTrapped: true,\n verticalPadding: this.verticalPadding,\n ariaLabelledBy: 'fd-dialog-header-form'\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.confirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.confirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", "html": "\n \n \n

The History of Pineapple

\n
\n\n \n \n
\n
\n \n
\n
\n \n
\n
\n
\n
\n \n
\n
\n
\n
\n \n
\n
\n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n \n
\n
\n \n
\n
\n
\n
\n
\n
\n \n
\n
\n \n
\n
\n \n
\n\n \n \n\n \n \n
\n
\n\n\n\n\n\n

{{ confirmationReason }}

\n" }, - { - "name": "dialog-full-screen-example", - "description": "Dialog Full Screen", - "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\nimport { AsyncPipe, NgStyle } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n TemplateRef,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogDefaultContent,\n DialogFooterComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-full-screen-inner-example',\n template: ` \n \n

{{ dialogRef.data.title }}

\n \n
\n \n \n {{ dialogRef.data.pinnapleDescription }}\n

\n
    \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
  • \n {{ fact }}\n
  • \n }\n
\n
\n \n \n \n \n \n \n
`,\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n AsyncPipe,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogFullScreenInnerExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n\n@Component({\n selector: 'fd-dialog-full-screen-example',\n imports: [\n ButtonComponent,\n BarModule,\n InputGroupModule,\n InitialFocusDirective,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n TitleComponent,\n DialogHeaderComponent,\n DialogComponent\n ],\n templateUrl: './dialog-full-screen-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DialogFullScreenExampleComponent {\n @ViewChild('dialogContent', { read: TemplateRef })\n dialogContent: TemplateRef;\n\n @ViewChild('dialogSubHeader', { read: TemplateRef })\n dialogSubHeader: TemplateRef;\n\n closeReason = '';\n\n templateBasedConfirmationReason = '';\n\n componentCloseReason = '';\n\n private _dialogReference: DialogRef;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openFromComponent(): void {\n const dialogRef = this._dialogService.open(DialogFullScreenInnerExampleComponent, {\n data: {\n title: `Pineapple Fun Facts`,\n pinnapleDescription: `\n The pineapple (Ananas comosus) is a tropical plant with an edible fruit\n and the most economically significant plant in the family Bromeliaceae.\n The pineapple is indigenous to South America,\n where it has been cultivated for many centuries.\n The introduction of the pineapple to Europe in the 17th\n century made it a significant cultural icon of luxury.\n Since the 1820s, pineapple has been commercially grown in\n greenhouses and many tropical plantations.\n `,\n pineappleFunFacts: [\n `You can grow your own pineapple by planting the top of the pineapple in soil`,\n `Pulling leaves from a pineapple is not an indication of ripeness as many people think`,\n `James Dole is considered the “King of Pineapples“`,\n `A pineapple cannot continue to ripen after it has been picked`,\n `An unripe pineapple not only tastes awful, but can also be poisonous`,\n `One of the ways you can tell if a pineapple is ripe is by smelling it`,\n `In Hawaii, the word for pineapple is “Hala kahiki“`\n ]\n },\n width: '400px',\n ariaLabelledBy: 'fd-dialog-header-fs-component',\n ariaDescribedBy: 'fd-dialog-body-fs-component',\n responsivePadding: true,\n draggable: true,\n resizable: true,\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.componentCloseReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.componentCloseReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialogFromTemplate(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: true,\n draggable: true,\n resizable: true,\n ariaLabelledBy: 'fd-dialog-header-fs-template',\n ariaDescribedBy: 'fd-dialog-body-fs-template',\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.templateBasedConfirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.templateBasedConfirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialog(): void {\n const object: DialogDefaultContent = {\n title: 'Dialog Title',\n titleId: 'fd-dialog-header-fs-object',\n content: this.dialogContent,\n contentId: 'fd-dialog-body-fs-object',\n subHeader: this.dialogSubHeader,\n approveButton: 'Ok',\n approveButtonAriaLabel: 'Ok Emphasized',\n approveButtonCallback: () => this._dialogReference.close('Approved'),\n cancelButton: 'Cancel',\n cancelButtonCallback: () => this._dialogReference.close('Canceled'),\n closeButtonCallback: () => this._dialogReference.dismiss('Dismissed'),\n fullScreenButtonCallback: () => this._dialogReference.toggleFullScreen(),\n closeButtonTitle: 'close',\n allowFullScreen: true,\n fullScreenExpandButtonText: 'Enter full-screen mode',\n fullScreenMinifyButtonText: 'Exit full-screen mode'\n };\n\n this._dialogReference = this._dialogService.open(object, {\n ariaLabelledBy: 'fd-dialog-header-fs-object',\n ariaDescribedBy: 'fd-dialog-body-fs-object',\n focusTrapped: true,\n resizable: true,\n draggable: true\n });\n\n this._dialogReference.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", - "html": "\n\n\n\n
You can also create dialog without building whole template.
\n
\n\n\n
\n \n \n \n
\n
\n\n

{{ closeReason }}

\n\n\n\n\n \n \n

The History of Pineapple

\n \n
\n\n \n

Are you interested in The Great History of Pineapple?

\n
\n\n \n \n\n \n \n
\n
\n\n\n

{{ templateBasedConfirmationReason }}

\n\n\n\n\n

{{ componentCloseReason }}

\n\n" - }, { "name": "dialog-mobile-example", "description": "Dialog Mobile", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { ContentDensityMode } from '@fundamental-ngx/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-mobile-example',\n templateUrl: './dialog-mobile-example.component.html',\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogMobileExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDialog(dialogTemplate): void {\n this._dialogService.open(dialogTemplate, {\n mobile: true,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-mobile',\n ariaDescribedBy: 'fd-dialog-body-mobile',\n contentDensity: ContentDensityMode.COZY\n });\n }\n}\n", "html": "\n \n \n

Wild pineapples

\n
\n\n \n
\n Certain bat-pollinated wild pineapples, members of the Bromeliad family, do the exact opposite of most\n flowers by opening their flowers at night and closing them during the day.\n
\n
\n\n \n \n \n \n
\n
\n\n\n" }, + { + "name": "dialog-full-screen-example", + "description": "Dialog Full Screen", + "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\nimport { AsyncPipe, NgStyle } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n TemplateRef,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogDefaultContent,\n DialogFooterComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-full-screen-inner-example',\n template: ` \n \n

{{ dialogRef.data.title }}

\n \n
\n \n \n {{ dialogRef.data.pinnapleDescription }}\n

\n
    \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
  • \n {{ fact }}\n
  • \n }\n
\n
\n \n \n \n \n \n \n
`,\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n AsyncPipe,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogFullScreenInnerExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n\n@Component({\n selector: 'fd-dialog-full-screen-example',\n imports: [\n ButtonComponent,\n BarModule,\n InputGroupModule,\n InitialFocusDirective,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n TitleComponent,\n DialogHeaderComponent,\n DialogComponent\n ],\n templateUrl: './dialog-full-screen-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DialogFullScreenExampleComponent {\n @ViewChild('dialogContent', { read: TemplateRef })\n dialogContent: TemplateRef;\n\n @ViewChild('dialogSubHeader', { read: TemplateRef })\n dialogSubHeader: TemplateRef;\n\n closeReason = '';\n\n templateBasedConfirmationReason = '';\n\n componentCloseReason = '';\n\n private _dialogReference: DialogRef;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openFromComponent(): void {\n const dialogRef = this._dialogService.open(DialogFullScreenInnerExampleComponent, {\n data: {\n title: `Pineapple Fun Facts`,\n pinnapleDescription: `\n The pineapple (Ananas comosus) is a tropical plant with an edible fruit\n and the most economically significant plant in the family Bromeliaceae.\n The pineapple is indigenous to South America,\n where it has been cultivated for many centuries.\n The introduction of the pineapple to Europe in the 17th\n century made it a significant cultural icon of luxury.\n Since the 1820s, pineapple has been commercially grown in\n greenhouses and many tropical plantations.\n `,\n pineappleFunFacts: [\n `You can grow your own pineapple by planting the top of the pineapple in soil`,\n `Pulling leaves from a pineapple is not an indication of ripeness as many people think`,\n `James Dole is considered the “King of Pineapples“`,\n `A pineapple cannot continue to ripen after it has been picked`,\n `An unripe pineapple not only tastes awful, but can also be poisonous`,\n `One of the ways you can tell if a pineapple is ripe is by smelling it`,\n `In Hawaii, the word for pineapple is “Hala kahiki“`\n ]\n },\n width: '400px',\n ariaLabelledBy: 'fd-dialog-header-fs-component',\n ariaDescribedBy: 'fd-dialog-body-fs-component',\n responsivePadding: true,\n draggable: true,\n resizable: true,\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.componentCloseReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.componentCloseReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialogFromTemplate(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: true,\n draggable: true,\n resizable: true,\n ariaLabelledBy: 'fd-dialog-header-fs-template',\n ariaDescribedBy: 'fd-dialog-body-fs-template',\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.templateBasedConfirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.templateBasedConfirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialog(): void {\n const object: DialogDefaultContent = {\n title: 'Dialog Title',\n titleId: 'fd-dialog-header-fs-object',\n content: this.dialogContent,\n contentId: 'fd-dialog-body-fs-object',\n subHeader: this.dialogSubHeader,\n approveButton: 'Ok',\n approveButtonAriaLabel: 'Ok Emphasized',\n approveButtonCallback: () => this._dialogReference.close('Approved'),\n cancelButton: 'Cancel',\n cancelButtonCallback: () => this._dialogReference.close('Canceled'),\n closeButtonCallback: () => this._dialogReference.dismiss('Dismissed'),\n fullScreenButtonCallback: () => this._dialogReference.toggleFullScreen(),\n closeButtonTitle: 'close',\n allowFullScreen: true,\n fullScreenExpandButtonText: 'Enter full-screen mode',\n fullScreenMinifyButtonText: 'Exit full-screen mode'\n };\n\n this._dialogReference = this._dialogService.open(object, {\n ariaLabelledBy: 'fd-dialog-header-fs-object',\n ariaDescribedBy: 'fd-dialog-body-fs-object',\n focusTrapped: true,\n resizable: true,\n draggable: true\n });\n\n this._dialogReference.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", + "html": "\n\n\n\n
You can also create dialog without building whole template.
\n
\n\n\n
\n \n \n \n
\n
\n\n

{{ closeReason }}

\n\n\n\n\n \n \n

The History of Pineapple

\n \n
\n\n \n

Are you interested in The Great History of Pineapple?

\n
\n\n \n \n\n \n \n
\n
\n\n\n

{{ templateBasedConfirmationReason }}

\n\n\n\n\n

{{ componentCloseReason }}

\n\n" + }, { "name": "dialog-object-example", "description": "Dialog Object", @@ -4702,6 +4702,12 @@ "description": "Dialog", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\n\nimport { NgStyle } from '@angular/common';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogRef\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n template: `\n \n \n

{{ dialogRef.data.title }}

\n
\n \n

\n {{ dialogRef.data.pinnapleDescription }}\n

\n
    \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
  • \n {{ fact }}\n
  • \n }\n
\n
\n \n \n \n \n \n \n
\n `,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n" }, + { + "name": "dialog-configuration-example", + "description": "Dialog Configuration", + "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-configuration-example',\n templateUrl: './dialog-configuration-example.component.html',\n styleUrls: ['./dialog-configuration-example.component.scss'],\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogConfigurationExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDraggableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n draggable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openResizableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n resizable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openClosableByButtonDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n escKeyCloseable: false,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n}\n", + "html": "\n \n \n

Origin of the Pineapple Word

\n
\n\n \n
\n The word pineapple in English was first recorded in 1398, when it was originally used to describe the\n reproductive organs of conifer trees (now termed pine cones). When European explorers discovered this\n tropical fruit they called them pineapples (term first recorded in that sense in 1664) because of their\n resemblance to what is now known as the pine cone. The term pine cone was first recorded in 1694, and\n was used to replace the original meaning of pineapple.\n
\n
\n\n \n \n \n \n
\n
\n\n\n\n\n" + }, { "name": "dialog-backdrop-container-example", "description": "Dialog Backdrop Container", @@ -4714,30 +4720,24 @@ "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { AsyncPipe, NgClass } from '@angular/common';\nimport { Component, TemplateRef } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { InitialFocusDirective, TemplateDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ListModule, ListSecondaryDirective } from '@fundamental-ngx/core/list';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\ninterface Fruit {\n id: number;\n name: string;\n price: number;\n}\n\n@Component({\n selector: 'fd-dialog-complex-example',\n templateUrl: './dialog-complex-example.component.html',\n imports: [\n TemplateDirective,\n BarModule,\n TitleComponent,\n InputGroupModule,\n InitialFocusDirective,\n FormsModule,\n CdkScrollable,\n ScrollbarDirective,\n ListModule,\n NgClass,\n ListSecondaryDirective,\n ButtonComponent,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogComplexExampleComponent {\n fruitCollection: Fruit[] = [\n { id: 1, name: 'Pineapple', price: Infinity },\n { id: 2, name: 'Passion Fruit', price: 10.0 },\n { id: 3, name: 'Papaya', price: 8.99 },\n { id: 4, name: 'Kiwifruit', price: 3.0 },\n { id: 5, name: 'Mango', price: 15.0 },\n { id: 6, name: 'Pomegranate', price: 12.5 },\n { id: 7, name: 'Guava', price: 10.15 },\n { id: 8, name: 'Durian', price: 15.25 },\n { id: 9, name: 'Jackfruit', price: 10.0 },\n { id: 10, name: 'Dragon Fruit', price: 9.0 },\n { id: 11, name: 'Cherimoya', price: 7.45 },\n { id: 12, name: 'Kiwano', price: 4.5 },\n { id: 13, name: 'Korean Melon', price: 6.5 },\n { id: 14, name: 'Feijoa', price: 2.0 },\n { id: 15, name: 'Tamarillo ', price: 8.75 },\n { id: 16, name: 'Loquat', price: 0.99 }\n ];\n\n selectedFruits: Fruit[] = [];\n\n dialogRef: DialogRef;\n\n searchedPhrase = '';\n\n constructor(public _dialogService: DialogService) {}\n\n openDialog(template: TemplateRef): void {\n this.dialogRef = this._dialogService.open(template, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n ariaLabelledBy: 'fd-dialog-header-complex',\n ariaDescribedBy: 'fd-dialog-description-complex'\n });\n this.dialogRef.loading(true);\n setTimeout(() => this.dialogRef.loading(false), 2000);\n }\n\n get totalPrice(): number {\n const sum = this.selectedFruits.reduce((total, fruit) => total + fruit.price, 0);\n return Math.round(sum * 100) / 100;\n }\n\n filterFruits(fruits: Fruit[], searchedPhrase: string): Fruit[] {\n return this.fruitCollection.filter((fruit) => fruit.name.toLowerCase().includes(searchedPhrase.toLowerCase()));\n }\n\n isSelected(id: number): boolean {\n return this.selectedFruits.some((fruit) => fruit.id === id);\n }\n\n selectFruit(fruit: Fruit): void {\n const fruitIndex = this.selectedFruits.indexOf(fruit);\n\n if (fruitIndex !== -1) {\n this.selectedFruits.splice(fruitIndex, 1);\n } else {\n this.selectedFruits.push(fruit);\n }\n }\n\n clear(): void {\n this.searchedPhrase = '';\n this.selectedFruits = [];\n }\n\n checkout(): void {\n this.dialogRef.close();\n }\n}\n", "html": "\n \n \n \n
\n \n

Fresh Market

\n Search for fresh produce items\n
\n
\n
\n \n
\n
\n \n
\n \n \n \n \n
\n
\n
\n \n @if ((dialogRef.onLoading | async) === false) {\n
    \n @for (fruit of filterFruits(fruitCollection, searchedPhrase); track fruit) {\n
  • \n {{ fruit.name }}\n {{ fruit.price }} €\n
  • \n }\n
\n }\n
\n \n \n
\n Total price: {{ totalPrice }}€ \n
\n
\n \n \n
\n
\n
\n
\n
\n\n" }, - { - "name": "dialog-configuration-example", - "description": "Dialog Configuration", - "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-configuration-example',\n templateUrl: './dialog-configuration-example.component.html',\n styleUrls: ['./dialog-configuration-example.component.scss'],\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogConfigurationExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDraggableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n draggable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openResizableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n resizable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openClosableByButtonDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n escKeyCloseable: false,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n}\n", - "html": "\n \n \n

Origin of the Pineapple Word

\n
\n\n \n
\n The word pineapple in English was first recorded in 1398, when it was originally used to describe the\n reproductive organs of conifer trees (now termed pine cones). When European explorers discovered this\n tropical fruit they called them pineapples (term first recorded in that sense in 1664) because of their\n resemblance to what is now known as the pine cone. The term pine cone was first recorded in 1694, and\n was used to replace the original meaning of pineapple.\n
\n
\n\n \n \n \n \n
\n
\n\n\n\n\n" - }, { "name": "form-dialog-example", "description": "Form Dialog", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { ChangeDetectionStrategy, ChangeDetectorRef, Component, TemplateRef } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-form-dialog-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './form-dialog-example.component.html',\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n CheckboxComponent,\n FormsModule,\n ButtonComponent,\n DialogHeaderComponent,\n DialogBodyComponent,\n DialogFooterComponent,\n DialogComponent\n ]\n})\nexport class FormDialogExampleComponent {\n confirmationReason: string;\n responsivePadding = false;\n verticalPadding = false;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openDialog(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: this.responsivePadding,\n focusTrapped: true,\n verticalPadding: this.verticalPadding,\n ariaLabelledBy: 'fd-dialog-header-form'\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.confirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.confirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", "html": "\n \n \n

The History of Pineapple

\n
\n\n \n \n
\n
\n \n
\n
\n \n
\n
\n
\n
\n \n
\n
\n
\n
\n \n
\n
\n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n \n
\n
\n \n
\n
\n
\n
\n
\n
\n \n
\n
\n \n
\n
\n \n
\n\n \n \n\n \n \n
\n
\n\n\n\n\n\n

{{ confirmationReason }}

\n" }, - { - "name": "dialog-full-screen-example", - "description": "Dialog Full Screen", - "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\nimport { AsyncPipe, NgStyle } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n TemplateRef,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogDefaultContent,\n DialogFooterComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-full-screen-inner-example',\n template: ` \n \n

{{ dialogRef.data.title }}

\n \n
\n \n \n {{ dialogRef.data.pinnapleDescription }}\n

\n
    \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
  • \n {{ fact }}\n
  • \n }\n
\n
\n \n \n \n \n \n \n
`,\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n AsyncPipe,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogFullScreenInnerExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n\n@Component({\n selector: 'fd-dialog-full-screen-example',\n imports: [\n ButtonComponent,\n BarModule,\n InputGroupModule,\n InitialFocusDirective,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n TitleComponent,\n DialogHeaderComponent,\n DialogComponent\n ],\n templateUrl: './dialog-full-screen-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DialogFullScreenExampleComponent {\n @ViewChild('dialogContent', { read: TemplateRef })\n dialogContent: TemplateRef;\n\n @ViewChild('dialogSubHeader', { read: TemplateRef })\n dialogSubHeader: TemplateRef;\n\n closeReason = '';\n\n templateBasedConfirmationReason = '';\n\n componentCloseReason = '';\n\n private _dialogReference: DialogRef;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openFromComponent(): void {\n const dialogRef = this._dialogService.open(DialogFullScreenInnerExampleComponent, {\n data: {\n title: `Pineapple Fun Facts`,\n pinnapleDescription: `\n The pineapple (Ananas comosus) is a tropical plant with an edible fruit\n and the most economically significant plant in the family Bromeliaceae.\n The pineapple is indigenous to South America,\n where it has been cultivated for many centuries.\n The introduction of the pineapple to Europe in the 17th\n century made it a significant cultural icon of luxury.\n Since the 1820s, pineapple has been commercially grown in\n greenhouses and many tropical plantations.\n `,\n pineappleFunFacts: [\n `You can grow your own pineapple by planting the top of the pineapple in soil`,\n `Pulling leaves from a pineapple is not an indication of ripeness as many people think`,\n `James Dole is considered the “King of Pineapples“`,\n `A pineapple cannot continue to ripen after it has been picked`,\n `An unripe pineapple not only tastes awful, but can also be poisonous`,\n `One of the ways you can tell if a pineapple is ripe is by smelling it`,\n `In Hawaii, the word for pineapple is “Hala kahiki“`\n ]\n },\n width: '400px',\n ariaLabelledBy: 'fd-dialog-header-fs-component',\n ariaDescribedBy: 'fd-dialog-body-fs-component',\n responsivePadding: true,\n draggable: true,\n resizable: true,\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.componentCloseReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.componentCloseReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialogFromTemplate(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: true,\n draggable: true,\n resizable: true,\n ariaLabelledBy: 'fd-dialog-header-fs-template',\n ariaDescribedBy: 'fd-dialog-body-fs-template',\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.templateBasedConfirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.templateBasedConfirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialog(): void {\n const object: DialogDefaultContent = {\n title: 'Dialog Title',\n titleId: 'fd-dialog-header-fs-object',\n content: this.dialogContent,\n contentId: 'fd-dialog-body-fs-object',\n subHeader: this.dialogSubHeader,\n approveButton: 'Ok',\n approveButtonAriaLabel: 'Ok Emphasized',\n approveButtonCallback: () => this._dialogReference.close('Approved'),\n cancelButton: 'Cancel',\n cancelButtonCallback: () => this._dialogReference.close('Canceled'),\n closeButtonCallback: () => this._dialogReference.dismiss('Dismissed'),\n fullScreenButtonCallback: () => this._dialogReference.toggleFullScreen(),\n closeButtonTitle: 'close',\n allowFullScreen: true,\n fullScreenExpandButtonText: 'Enter full-screen mode',\n fullScreenMinifyButtonText: 'Exit full-screen mode'\n };\n\n this._dialogReference = this._dialogService.open(object, {\n ariaLabelledBy: 'fd-dialog-header-fs-object',\n ariaDescribedBy: 'fd-dialog-body-fs-object',\n focusTrapped: true,\n resizable: true,\n draggable: true\n });\n\n this._dialogReference.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", - "html": "\n\n\n\n
You can also create dialog without building whole template.
\n
\n\n\n
\n \n \n \n
\n
\n\n

{{ closeReason }}

\n\n\n\n\n \n \n

The History of Pineapple

\n \n
\n\n \n

Are you interested in The Great History of Pineapple?

\n
\n\n \n \n\n \n \n
\n
\n\n\n

{{ templateBasedConfirmationReason }}

\n\n\n\n\n

{{ componentCloseReason }}

\n\n" - }, { "name": "dialog-mobile-example", "description": "Dialog Mobile", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { ContentDensityMode } from '@fundamental-ngx/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-mobile-example',\n templateUrl: './dialog-mobile-example.component.html',\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogMobileExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDialog(dialogTemplate): void {\n this._dialogService.open(dialogTemplate, {\n mobile: true,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-mobile',\n ariaDescribedBy: 'fd-dialog-body-mobile',\n contentDensity: ContentDensityMode.COZY\n });\n }\n}\n", "html": "\n \n \n

Wild pineapples

\n
\n\n \n
\n Certain bat-pollinated wild pineapples, members of the Bromeliad family, do the exact opposite of most\n flowers by opening their flowers at night and closing them during the day.\n
\n
\n\n \n \n \n \n
\n
\n\n\n" }, + { + "name": "dialog-full-screen-example", + "description": "Dialog Full Screen", + "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\nimport { AsyncPipe, NgStyle } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n TemplateRef,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogDefaultContent,\n DialogFooterComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-full-screen-inner-example',\n template: ` \n \n

{{ dialogRef.data.title }}

\n \n
\n \n \n {{ dialogRef.data.pinnapleDescription }}\n

\n
    \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
  • \n {{ fact }}\n
  • \n }\n
\n
\n \n \n \n \n \n \n
`,\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n AsyncPipe,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogFullScreenInnerExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n\n@Component({\n selector: 'fd-dialog-full-screen-example',\n imports: [\n ButtonComponent,\n BarModule,\n InputGroupModule,\n InitialFocusDirective,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n TitleComponent,\n DialogHeaderComponent,\n DialogComponent\n ],\n templateUrl: './dialog-full-screen-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DialogFullScreenExampleComponent {\n @ViewChild('dialogContent', { read: TemplateRef })\n dialogContent: TemplateRef;\n\n @ViewChild('dialogSubHeader', { read: TemplateRef })\n dialogSubHeader: TemplateRef;\n\n closeReason = '';\n\n templateBasedConfirmationReason = '';\n\n componentCloseReason = '';\n\n private _dialogReference: DialogRef;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openFromComponent(): void {\n const dialogRef = this._dialogService.open(DialogFullScreenInnerExampleComponent, {\n data: {\n title: `Pineapple Fun Facts`,\n pinnapleDescription: `\n The pineapple (Ananas comosus) is a tropical plant with an edible fruit\n and the most economically significant plant in the family Bromeliaceae.\n The pineapple is indigenous to South America,\n where it has been cultivated for many centuries.\n The introduction of the pineapple to Europe in the 17th\n century made it a significant cultural icon of luxury.\n Since the 1820s, pineapple has been commercially grown in\n greenhouses and many tropical plantations.\n `,\n pineappleFunFacts: [\n `You can grow your own pineapple by planting the top of the pineapple in soil`,\n `Pulling leaves from a pineapple is not an indication of ripeness as many people think`,\n `James Dole is considered the “King of Pineapples“`,\n `A pineapple cannot continue to ripen after it has been picked`,\n `An unripe pineapple not only tastes awful, but can also be poisonous`,\n `One of the ways you can tell if a pineapple is ripe is by smelling it`,\n `In Hawaii, the word for pineapple is “Hala kahiki“`\n ]\n },\n width: '400px',\n ariaLabelledBy: 'fd-dialog-header-fs-component',\n ariaDescribedBy: 'fd-dialog-body-fs-component',\n responsivePadding: true,\n draggable: true,\n resizable: true,\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.componentCloseReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.componentCloseReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialogFromTemplate(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: true,\n draggable: true,\n resizable: true,\n ariaLabelledBy: 'fd-dialog-header-fs-template',\n ariaDescribedBy: 'fd-dialog-body-fs-template',\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.templateBasedConfirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.templateBasedConfirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialog(): void {\n const object: DialogDefaultContent = {\n title: 'Dialog Title',\n titleId: 'fd-dialog-header-fs-object',\n content: this.dialogContent,\n contentId: 'fd-dialog-body-fs-object',\n subHeader: this.dialogSubHeader,\n approveButton: 'Ok',\n approveButtonAriaLabel: 'Ok Emphasized',\n approveButtonCallback: () => this._dialogReference.close('Approved'),\n cancelButton: 'Cancel',\n cancelButtonCallback: () => this._dialogReference.close('Canceled'),\n closeButtonCallback: () => this._dialogReference.dismiss('Dismissed'),\n fullScreenButtonCallback: () => this._dialogReference.toggleFullScreen(),\n closeButtonTitle: 'close',\n allowFullScreen: true,\n fullScreenExpandButtonText: 'Enter full-screen mode',\n fullScreenMinifyButtonText: 'Exit full-screen mode'\n };\n\n this._dialogReference = this._dialogService.open(object, {\n ariaLabelledBy: 'fd-dialog-header-fs-object',\n ariaDescribedBy: 'fd-dialog-body-fs-object',\n focusTrapped: true,\n resizable: true,\n draggable: true\n });\n\n this._dialogReference.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", + "html": "\n\n\n\n
You can also create dialog without building whole template.
\n
\n\n\n
\n \n \n \n
\n
\n\n

{{ closeReason }}

\n\n\n\n\n \n \n

The History of Pineapple

\n \n
\n\n \n

Are you interested in The Great History of Pineapple?

\n
\n\n \n \n\n \n \n
\n
\n\n\n

{{ templateBasedConfirmationReason }}

\n\n\n\n\n

{{ componentCloseReason }}

\n\n" + }, { "name": "dialog-object-example", "description": "Dialog Object", @@ -4855,6 +4855,12 @@ "description": "Dialog", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\n\nimport { NgStyle } from '@angular/common';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogRef\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n template: `\n \n \n

{{ dialogRef.data.title }}

\n
\n \n

\n {{ dialogRef.data.pinnapleDescription }}\n

\n
    \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
  • \n {{ fact }}\n
  • \n }\n
\n
\n \n \n \n \n \n \n
\n `,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n" }, + { + "name": "dialog-configuration-example", + "description": "Dialog Configuration", + "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-configuration-example',\n templateUrl: './dialog-configuration-example.component.html',\n styleUrls: ['./dialog-configuration-example.component.scss'],\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogConfigurationExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDraggableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n draggable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openResizableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n resizable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openClosableByButtonDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n escKeyCloseable: false,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n}\n", + "html": "\n \n \n

Origin of the Pineapple Word

\n
\n\n \n
\n The word pineapple in English was first recorded in 1398, when it was originally used to describe the\n reproductive organs of conifer trees (now termed pine cones). When European explorers discovered this\n tropical fruit they called them pineapples (term first recorded in that sense in 1664) because of their\n resemblance to what is now known as the pine cone. The term pine cone was first recorded in 1694, and\n was used to replace the original meaning of pineapple.\n
\n
\n\n \n \n \n \n
\n
\n\n\n\n\n" + }, { "name": "dialog-backdrop-container-example", "description": "Dialog Backdrop Container", @@ -4867,30 +4873,24 @@ "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { AsyncPipe, NgClass } from '@angular/common';\nimport { Component, TemplateRef } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { InitialFocusDirective, TemplateDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ListModule, ListSecondaryDirective } from '@fundamental-ngx/core/list';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\ninterface Fruit {\n id: number;\n name: string;\n price: number;\n}\n\n@Component({\n selector: 'fd-dialog-complex-example',\n templateUrl: './dialog-complex-example.component.html',\n imports: [\n TemplateDirective,\n BarModule,\n TitleComponent,\n InputGroupModule,\n InitialFocusDirective,\n FormsModule,\n CdkScrollable,\n ScrollbarDirective,\n ListModule,\n NgClass,\n ListSecondaryDirective,\n ButtonComponent,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogComplexExampleComponent {\n fruitCollection: Fruit[] = [\n { id: 1, name: 'Pineapple', price: Infinity },\n { id: 2, name: 'Passion Fruit', price: 10.0 },\n { id: 3, name: 'Papaya', price: 8.99 },\n { id: 4, name: 'Kiwifruit', price: 3.0 },\n { id: 5, name: 'Mango', price: 15.0 },\n { id: 6, name: 'Pomegranate', price: 12.5 },\n { id: 7, name: 'Guava', price: 10.15 },\n { id: 8, name: 'Durian', price: 15.25 },\n { id: 9, name: 'Jackfruit', price: 10.0 },\n { id: 10, name: 'Dragon Fruit', price: 9.0 },\n { id: 11, name: 'Cherimoya', price: 7.45 },\n { id: 12, name: 'Kiwano', price: 4.5 },\n { id: 13, name: 'Korean Melon', price: 6.5 },\n { id: 14, name: 'Feijoa', price: 2.0 },\n { id: 15, name: 'Tamarillo ', price: 8.75 },\n { id: 16, name: 'Loquat', price: 0.99 }\n ];\n\n selectedFruits: Fruit[] = [];\n\n dialogRef: DialogRef;\n\n searchedPhrase = '';\n\n constructor(public _dialogService: DialogService) {}\n\n openDialog(template: TemplateRef): void {\n this.dialogRef = this._dialogService.open(template, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n ariaLabelledBy: 'fd-dialog-header-complex',\n ariaDescribedBy: 'fd-dialog-description-complex'\n });\n this.dialogRef.loading(true);\n setTimeout(() => this.dialogRef.loading(false), 2000);\n }\n\n get totalPrice(): number {\n const sum = this.selectedFruits.reduce((total, fruit) => total + fruit.price, 0);\n return Math.round(sum * 100) / 100;\n }\n\n filterFruits(fruits: Fruit[], searchedPhrase: string): Fruit[] {\n return this.fruitCollection.filter((fruit) => fruit.name.toLowerCase().includes(searchedPhrase.toLowerCase()));\n }\n\n isSelected(id: number): boolean {\n return this.selectedFruits.some((fruit) => fruit.id === id);\n }\n\n selectFruit(fruit: Fruit): void {\n const fruitIndex = this.selectedFruits.indexOf(fruit);\n\n if (fruitIndex !== -1) {\n this.selectedFruits.splice(fruitIndex, 1);\n } else {\n this.selectedFruits.push(fruit);\n }\n }\n\n clear(): void {\n this.searchedPhrase = '';\n this.selectedFruits = [];\n }\n\n checkout(): void {\n this.dialogRef.close();\n }\n}\n", "html": "\n \n \n \n
\n \n

Fresh Market

\n Search for fresh produce items\n
\n
\n
\n \n
\n
\n \n
\n \n \n \n \n
\n
\n
\n \n @if ((dialogRef.onLoading | async) === false) {\n
    \n @for (fruit of filterFruits(fruitCollection, searchedPhrase); track fruit) {\n
  • \n {{ fruit.name }}\n {{ fruit.price }} €\n
  • \n }\n
\n }\n
\n \n \n
\n Total price: {{ totalPrice }}€ \n
\n
\n \n \n
\n
\n
\n
\n
\n\n" }, - { - "name": "dialog-configuration-example", - "description": "Dialog Configuration", - "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-configuration-example',\n templateUrl: './dialog-configuration-example.component.html',\n styleUrls: ['./dialog-configuration-example.component.scss'],\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogConfigurationExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDraggableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n draggable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openResizableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n resizable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openClosableByButtonDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n escKeyCloseable: false,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n}\n", - "html": "\n \n \n

Origin of the Pineapple Word

\n
\n\n \n
\n The word pineapple in English was first recorded in 1398, when it was originally used to describe the\n reproductive organs of conifer trees (now termed pine cones). When European explorers discovered this\n tropical fruit they called them pineapples (term first recorded in that sense in 1664) because of their\n resemblance to what is now known as the pine cone. The term pine cone was first recorded in 1694, and\n was used to replace the original meaning of pineapple.\n
\n
\n\n \n \n \n \n
\n
\n\n\n\n\n" - }, { "name": "form-dialog-example", "description": "Form Dialog", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { ChangeDetectionStrategy, ChangeDetectorRef, Component, TemplateRef } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-form-dialog-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './form-dialog-example.component.html',\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n CheckboxComponent,\n FormsModule,\n ButtonComponent,\n DialogHeaderComponent,\n DialogBodyComponent,\n DialogFooterComponent,\n DialogComponent\n ]\n})\nexport class FormDialogExampleComponent {\n confirmationReason: string;\n responsivePadding = false;\n verticalPadding = false;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openDialog(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: this.responsivePadding,\n focusTrapped: true,\n verticalPadding: this.verticalPadding,\n ariaLabelledBy: 'fd-dialog-header-form'\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.confirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.confirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", "html": "\n \n \n

The History of Pineapple

\n
\n\n \n \n
\n
\n \n
\n
\n \n
\n
\n
\n
\n \n
\n
\n
\n
\n \n
\n
\n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n \n
\n
\n \n
\n
\n
\n
\n
\n
\n \n
\n
\n \n
\n
\n \n
\n\n \n \n\n \n \n
\n
\n\n\n\n\n\n

{{ confirmationReason }}

\n" }, - { - "name": "dialog-full-screen-example", - "description": "Dialog Full Screen", - "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\nimport { AsyncPipe, NgStyle } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n TemplateRef,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogDefaultContent,\n DialogFooterComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-full-screen-inner-example',\n template: ` \n \n

{{ dialogRef.data.title }}

\n \n
\n \n \n {{ dialogRef.data.pinnapleDescription }}\n

\n
    \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
  • \n {{ fact }}\n
  • \n }\n
\n
\n \n \n \n \n \n \n
`,\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n AsyncPipe,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogFullScreenInnerExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n\n@Component({\n selector: 'fd-dialog-full-screen-example',\n imports: [\n ButtonComponent,\n BarModule,\n InputGroupModule,\n InitialFocusDirective,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n TitleComponent,\n DialogHeaderComponent,\n DialogComponent\n ],\n templateUrl: './dialog-full-screen-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DialogFullScreenExampleComponent {\n @ViewChild('dialogContent', { read: TemplateRef })\n dialogContent: TemplateRef;\n\n @ViewChild('dialogSubHeader', { read: TemplateRef })\n dialogSubHeader: TemplateRef;\n\n closeReason = '';\n\n templateBasedConfirmationReason = '';\n\n componentCloseReason = '';\n\n private _dialogReference: DialogRef;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openFromComponent(): void {\n const dialogRef = this._dialogService.open(DialogFullScreenInnerExampleComponent, {\n data: {\n title: `Pineapple Fun Facts`,\n pinnapleDescription: `\n The pineapple (Ananas comosus) is a tropical plant with an edible fruit\n and the most economically significant plant in the family Bromeliaceae.\n The pineapple is indigenous to South America,\n where it has been cultivated for many centuries.\n The introduction of the pineapple to Europe in the 17th\n century made it a significant cultural icon of luxury.\n Since the 1820s, pineapple has been commercially grown in\n greenhouses and many tropical plantations.\n `,\n pineappleFunFacts: [\n `You can grow your own pineapple by planting the top of the pineapple in soil`,\n `Pulling leaves from a pineapple is not an indication of ripeness as many people think`,\n `James Dole is considered the “King of Pineapples“`,\n `A pineapple cannot continue to ripen after it has been picked`,\n `An unripe pineapple not only tastes awful, but can also be poisonous`,\n `One of the ways you can tell if a pineapple is ripe is by smelling it`,\n `In Hawaii, the word for pineapple is “Hala kahiki“`\n ]\n },\n width: '400px',\n ariaLabelledBy: 'fd-dialog-header-fs-component',\n ariaDescribedBy: 'fd-dialog-body-fs-component',\n responsivePadding: true,\n draggable: true,\n resizable: true,\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.componentCloseReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.componentCloseReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialogFromTemplate(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: true,\n draggable: true,\n resizable: true,\n ariaLabelledBy: 'fd-dialog-header-fs-template',\n ariaDescribedBy: 'fd-dialog-body-fs-template',\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.templateBasedConfirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.templateBasedConfirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialog(): void {\n const object: DialogDefaultContent = {\n title: 'Dialog Title',\n titleId: 'fd-dialog-header-fs-object',\n content: this.dialogContent,\n contentId: 'fd-dialog-body-fs-object',\n subHeader: this.dialogSubHeader,\n approveButton: 'Ok',\n approveButtonAriaLabel: 'Ok Emphasized',\n approveButtonCallback: () => this._dialogReference.close('Approved'),\n cancelButton: 'Cancel',\n cancelButtonCallback: () => this._dialogReference.close('Canceled'),\n closeButtonCallback: () => this._dialogReference.dismiss('Dismissed'),\n fullScreenButtonCallback: () => this._dialogReference.toggleFullScreen(),\n closeButtonTitle: 'close',\n allowFullScreen: true,\n fullScreenExpandButtonText: 'Enter full-screen mode',\n fullScreenMinifyButtonText: 'Exit full-screen mode'\n };\n\n this._dialogReference = this._dialogService.open(object, {\n ariaLabelledBy: 'fd-dialog-header-fs-object',\n ariaDescribedBy: 'fd-dialog-body-fs-object',\n focusTrapped: true,\n resizable: true,\n draggable: true\n });\n\n this._dialogReference.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", - "html": "\n\n\n\n
You can also create dialog without building whole template.
\n
\n\n\n
\n \n \n \n
\n
\n\n

{{ closeReason }}

\n\n\n\n\n \n \n

The History of Pineapple

\n \n
\n\n \n

Are you interested in The Great History of Pineapple?

\n
\n\n \n \n\n \n \n
\n
\n\n\n

{{ templateBasedConfirmationReason }}

\n\n\n\n\n

{{ componentCloseReason }}

\n\n" - }, { "name": "dialog-mobile-example", "description": "Dialog Mobile", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { ContentDensityMode } from '@fundamental-ngx/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-mobile-example',\n templateUrl: './dialog-mobile-example.component.html',\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogMobileExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDialog(dialogTemplate): void {\n this._dialogService.open(dialogTemplate, {\n mobile: true,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-mobile',\n ariaDescribedBy: 'fd-dialog-body-mobile',\n contentDensity: ContentDensityMode.COZY\n });\n }\n}\n", "html": "\n \n \n

Wild pineapples

\n
\n\n \n
\n Certain bat-pollinated wild pineapples, members of the Bromeliad family, do the exact opposite of most\n flowers by opening their flowers at night and closing them during the day.\n
\n
\n\n \n \n \n \n
\n
\n\n\n" }, + { + "name": "dialog-full-screen-example", + "description": "Dialog Full Screen", + "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\nimport { AsyncPipe, NgStyle } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n TemplateRef,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogDefaultContent,\n DialogFooterComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-full-screen-inner-example',\n template: ` \n \n

{{ dialogRef.data.title }}

\n \n
\n \n \n {{ dialogRef.data.pinnapleDescription }}\n

\n
    \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
  • \n {{ fact }}\n
  • \n }\n
\n
\n \n \n \n \n \n \n
`,\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n AsyncPipe,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogFullScreenInnerExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n\n@Component({\n selector: 'fd-dialog-full-screen-example',\n imports: [\n ButtonComponent,\n BarModule,\n InputGroupModule,\n InitialFocusDirective,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n TitleComponent,\n DialogHeaderComponent,\n DialogComponent\n ],\n templateUrl: './dialog-full-screen-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DialogFullScreenExampleComponent {\n @ViewChild('dialogContent', { read: TemplateRef })\n dialogContent: TemplateRef;\n\n @ViewChild('dialogSubHeader', { read: TemplateRef })\n dialogSubHeader: TemplateRef;\n\n closeReason = '';\n\n templateBasedConfirmationReason = '';\n\n componentCloseReason = '';\n\n private _dialogReference: DialogRef;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openFromComponent(): void {\n const dialogRef = this._dialogService.open(DialogFullScreenInnerExampleComponent, {\n data: {\n title: `Pineapple Fun Facts`,\n pinnapleDescription: `\n The pineapple (Ananas comosus) is a tropical plant with an edible fruit\n and the most economically significant plant in the family Bromeliaceae.\n The pineapple is indigenous to South America,\n where it has been cultivated for many centuries.\n The introduction of the pineapple to Europe in the 17th\n century made it a significant cultural icon of luxury.\n Since the 1820s, pineapple has been commercially grown in\n greenhouses and many tropical plantations.\n `,\n pineappleFunFacts: [\n `You can grow your own pineapple by planting the top of the pineapple in soil`,\n `Pulling leaves from a pineapple is not an indication of ripeness as many people think`,\n `James Dole is considered the “King of Pineapples“`,\n `A pineapple cannot continue to ripen after it has been picked`,\n `An unripe pineapple not only tastes awful, but can also be poisonous`,\n `One of the ways you can tell if a pineapple is ripe is by smelling it`,\n `In Hawaii, the word for pineapple is “Hala kahiki“`\n ]\n },\n width: '400px',\n ariaLabelledBy: 'fd-dialog-header-fs-component',\n ariaDescribedBy: 'fd-dialog-body-fs-component',\n responsivePadding: true,\n draggable: true,\n resizable: true,\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.componentCloseReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.componentCloseReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialogFromTemplate(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: true,\n draggable: true,\n resizable: true,\n ariaLabelledBy: 'fd-dialog-header-fs-template',\n ariaDescribedBy: 'fd-dialog-body-fs-template',\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.templateBasedConfirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.templateBasedConfirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialog(): void {\n const object: DialogDefaultContent = {\n title: 'Dialog Title',\n titleId: 'fd-dialog-header-fs-object',\n content: this.dialogContent,\n contentId: 'fd-dialog-body-fs-object',\n subHeader: this.dialogSubHeader,\n approveButton: 'Ok',\n approveButtonAriaLabel: 'Ok Emphasized',\n approveButtonCallback: () => this._dialogReference.close('Approved'),\n cancelButton: 'Cancel',\n cancelButtonCallback: () => this._dialogReference.close('Canceled'),\n closeButtonCallback: () => this._dialogReference.dismiss('Dismissed'),\n fullScreenButtonCallback: () => this._dialogReference.toggleFullScreen(),\n closeButtonTitle: 'close',\n allowFullScreen: true,\n fullScreenExpandButtonText: 'Enter full-screen mode',\n fullScreenMinifyButtonText: 'Exit full-screen mode'\n };\n\n this._dialogReference = this._dialogService.open(object, {\n ariaLabelledBy: 'fd-dialog-header-fs-object',\n ariaDescribedBy: 'fd-dialog-body-fs-object',\n focusTrapped: true,\n resizable: true,\n draggable: true\n });\n\n this._dialogReference.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", + "html": "\n\n\n\n
You can also create dialog without building whole template.
\n
\n\n\n
\n \n \n \n
\n
\n\n

{{ closeReason }}

\n\n\n\n\n \n \n

The History of Pineapple

\n \n
\n\n \n

Are you interested in The Great History of Pineapple?

\n
\n\n \n \n\n \n \n
\n
\n\n\n

{{ templateBasedConfirmationReason }}

\n\n\n\n\n

{{ componentCloseReason }}

\n\n" + }, { "name": "dialog-object-example", "description": "Dialog Object", @@ -5256,18 +5256,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n id: number;\n title: string;\n description: string;\n layoutItemPattern?: string;\n}\n\n@Component({\n selector: 'fd-grid-list-layout-example',\n templateUrl: './grid-list-layout-example.component.html',\n styleUrls: ['./grid-list-layout-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListLayoutExampleComponent {\n layoutPattern = 'XL4-L3-M2-S1';\n\n list: GridListItem[] = [\n {\n id: 1,\n title: 'Title 1',\n description: 'Description 1'\n },\n {\n id: 2,\n title: 'Title 2',\n description: 'Description 2',\n layoutItemPattern: 'XL6-L8-M6-S12'\n },\n {\n id: 3,\n title: 'Title 3',\n description: 'Description 3'\n },\n {\n id: 4,\n title: 'Title 4',\n description: 'Description 4'\n },\n {\n id: 5,\n title: 'Title 5',\n description: 'Description 5'\n },\n {\n id: 6,\n title: 'Title 6',\n description: 'Description 6'\n },\n {\n id: 7,\n title: 'Title 7',\n description: 'Description 7'\n }\n ];\n}\n", "html": "\n \n {{ '(' + list.length + ')' }}\n \n @for (item of list; track item) {\n \n Custom Text \n \n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n \n }\n
\n" }, - { - "name": "grid-list-more-example", - "description": "Grid List More", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-more-example',\n templateUrl: './grid-list-more-example.component.html',\n styleUrls: ['./grid-list-more-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListMoreExampleComponent {\n totalItems = 50;\n\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n showMore(): void {\n if (this.list.length === this.totalItems) {\n return;\n }\n\n const newPart: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n this.list.push(...newPart);\n }\n}\n", - "html": "\n \n @for (item of list; track item; let i = $index) {\n \n \n \n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n
\n }\n @if (totalItems !== list.length) {\n \n }\n
\n" - }, { "name": "grid-list-states-example", "description": "Grid List States", "typescript": "import { Component } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListItemOutputEvent, GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\n@Component({\n selector: 'fd-grid-list-states-example',\n templateUrl: './grid-list-states-example.component.html',\n styleUrls: ['./grid-list-states-example.component.scss'],\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListStatesExampleComponent {\n locked(event: GridListItemOutputEvent): void {\n console.log('Locked event', event);\n }\n\n draft(event: GridListItemOutputEvent): void {\n console.log('Draft event', event);\n }\n}\n", "html": "\n \n (7)\n \n\n State: Unread \n\n \n Custom Text \n\n \n\n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n
\n\n State: Error \n\n \n Custom Text \n\n \n\n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n
\n\n \n Custom Text \n\n \n\n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n\n Custom error message \n
\n\n State: Locked \n\n \n Custom Text \n\n \n\n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n
\n\n \n Custom Text \n\n \n\n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n\n Locked button redefined to text \n
\n\n State: Draft \n\n \n Custom Text \n\n \n\n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n
\n\n \n Custom Text \n\n \n\n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n\n Draft button redefined to text \n
\n
\n" }, + { + "name": "grid-list-more-example", + "description": "Grid List More", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-more-example',\n templateUrl: './grid-list-more-example.component.html',\n styleUrls: ['./grid-list-more-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListMoreExampleComponent {\n totalItems = 50;\n\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n showMore(): void {\n if (this.list.length === this.totalItems) {\n return;\n }\n\n const newPart: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n this.list.push(...newPart);\n }\n}\n", + "html": "\n \n @for (item of list; track item; let i = $index) {\n \n \n \n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n
\n }\n @if (totalItems !== list.length) {\n \n }\n
\n" + }, { "name": "grid-list-statuses-example", "description": "Grid List Statuses", @@ -5338,18 +5338,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n id: number;\n title: string;\n description: string;\n layoutItemPattern?: string;\n}\n\n@Component({\n selector: 'fd-grid-list-layout-example',\n templateUrl: './grid-list-layout-example.component.html',\n styleUrls: ['./grid-list-layout-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListLayoutExampleComponent {\n layoutPattern = 'XL4-L3-M2-S1';\n\n list: GridListItem[] = [\n {\n id: 1,\n title: 'Title 1',\n description: 'Description 1'\n },\n {\n id: 2,\n title: 'Title 2',\n description: 'Description 2',\n layoutItemPattern: 'XL6-L8-M6-S12'\n },\n {\n id: 3,\n title: 'Title 3',\n description: 'Description 3'\n },\n {\n id: 4,\n title: 'Title 4',\n description: 'Description 4'\n },\n {\n id: 5,\n title: 'Title 5',\n description: 'Description 5'\n },\n {\n id: 6,\n title: 'Title 6',\n description: 'Description 6'\n },\n {\n id: 7,\n title: 'Title 7',\n description: 'Description 7'\n }\n ];\n}\n", "html": "\n \n {{ '(' + list.length + ')' }}\n \n @for (item of list; track item) {\n \n Custom Text \n \n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n \n }\n
\n" }, - { - "name": "grid-list-more-example", - "description": "Grid List More", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-more-example',\n templateUrl: './grid-list-more-example.component.html',\n styleUrls: ['./grid-list-more-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListMoreExampleComponent {\n totalItems = 50;\n\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n showMore(): void {\n if (this.list.length === this.totalItems) {\n return;\n }\n\n const newPart: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n this.list.push(...newPart);\n }\n}\n", - "html": "\n \n @for (item of list; track item; let i = $index) {\n \n \n \n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n
\n }\n @if (totalItems !== list.length) {\n \n }\n
\n" - }, { "name": "grid-list-states-example", "description": "Grid List States", "typescript": "import { Component } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListItemOutputEvent, GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\n@Component({\n selector: 'fd-grid-list-states-example',\n templateUrl: './grid-list-states-example.component.html',\n styleUrls: ['./grid-list-states-example.component.scss'],\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListStatesExampleComponent {\n locked(event: GridListItemOutputEvent): void {\n console.log('Locked event', event);\n }\n\n draft(event: GridListItemOutputEvent): void {\n console.log('Draft event', event);\n }\n}\n", "html": "\n \n (7)\n \n\n State: Unread \n\n \n Custom Text \n\n \n\n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n
\n\n State: Error \n\n \n Custom Text \n\n \n\n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n
\n\n \n Custom Text \n\n \n\n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n\n Custom error message \n
\n\n State: Locked \n\n \n Custom Text \n\n \n\n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n
\n\n \n Custom Text \n\n \n\n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n\n Locked button redefined to text \n
\n\n State: Draft \n\n \n Custom Text \n\n \n\n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n
\n\n \n Custom Text \n\n \n\n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n\n Draft button redefined to text \n
\n
\n" }, + { + "name": "grid-list-more-example", + "description": "Grid List More", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-more-example',\n templateUrl: './grid-list-more-example.component.html',\n styleUrls: ['./grid-list-more-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListMoreExampleComponent {\n totalItems = 50;\n\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n showMore(): void {\n if (this.list.length === this.totalItems) {\n return;\n }\n\n const newPart: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n this.list.push(...newPart);\n }\n}\n", + "html": "\n \n @for (item of list; track item; let i = $index) {\n \n \n \n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n
\n }\n @if (totalItems !== list.length) {\n \n }\n
\n" + }, { "name": "grid-list-statuses-example", "description": "Grid List Statuses", @@ -5420,18 +5420,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n id: number;\n title: string;\n description: string;\n layoutItemPattern?: string;\n}\n\n@Component({\n selector: 'fd-grid-list-layout-example',\n templateUrl: './grid-list-layout-example.component.html',\n styleUrls: ['./grid-list-layout-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListLayoutExampleComponent {\n layoutPattern = 'XL4-L3-M2-S1';\n\n list: GridListItem[] = [\n {\n id: 1,\n title: 'Title 1',\n description: 'Description 1'\n },\n {\n id: 2,\n title: 'Title 2',\n description: 'Description 2',\n layoutItemPattern: 'XL6-L8-M6-S12'\n },\n {\n id: 3,\n title: 'Title 3',\n description: 'Description 3'\n },\n {\n id: 4,\n title: 'Title 4',\n description: 'Description 4'\n },\n {\n id: 5,\n title: 'Title 5',\n description: 'Description 5'\n },\n {\n id: 6,\n title: 'Title 6',\n description: 'Description 6'\n },\n {\n id: 7,\n title: 'Title 7',\n description: 'Description 7'\n }\n ];\n}\n", "html": "\n \n {{ '(' + list.length + ')' }}\n \n @for (item of list; track item) {\n \n Custom Text \n \n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n \n }\n
\n" }, - { - "name": "grid-list-more-example", - "description": "Grid List More", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-more-example',\n templateUrl: './grid-list-more-example.component.html',\n styleUrls: ['./grid-list-more-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListMoreExampleComponent {\n totalItems = 50;\n\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n showMore(): void {\n if (this.list.length === this.totalItems) {\n return;\n }\n\n const newPart: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n this.list.push(...newPart);\n }\n}\n", - "html": "\n \n @for (item of list; track item; let i = $index) {\n \n \n \n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n
\n }\n @if (totalItems !== list.length) {\n \n }\n
\n" - }, { "name": "grid-list-states-example", "description": "Grid List States", "typescript": "import { Component } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListItemOutputEvent, GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\n@Component({\n selector: 'fd-grid-list-states-example',\n templateUrl: './grid-list-states-example.component.html',\n styleUrls: ['./grid-list-states-example.component.scss'],\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListStatesExampleComponent {\n locked(event: GridListItemOutputEvent): void {\n console.log('Locked event', event);\n }\n\n draft(event: GridListItemOutputEvent): void {\n console.log('Draft event', event);\n }\n}\n", "html": "\n \n (7)\n \n\n State: Unread \n\n \n Custom Text \n\n \n\n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n
\n\n State: Error \n\n \n Custom Text \n\n \n\n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n
\n\n \n Custom Text \n\n \n\n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n\n Custom error message \n
\n\n State: Locked \n\n \n Custom Text \n\n \n\n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n
\n\n \n Custom Text \n\n \n\n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n\n Locked button redefined to text \n
\n\n State: Draft \n\n \n Custom Text \n\n \n\n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n
\n\n \n Custom Text \n\n \n\n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n\n Draft button redefined to text \n
\n
\n" }, + { + "name": "grid-list-more-example", + "description": "Grid List More", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-more-example',\n templateUrl: './grid-list-more-example.component.html',\n styleUrls: ['./grid-list-more-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListMoreExampleComponent {\n totalItems = 50;\n\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n showMore(): void {\n if (this.list.length === this.totalItems) {\n return;\n }\n\n const newPart: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n this.list.push(...newPart);\n }\n}\n", + "html": "\n \n @for (item of list; track item; let i = $index) {\n \n \n \n \n

781 Main Street

\n

Anytown, SD 57401

\n

USA

\n john_li@example.com\n
\n
\n }\n @if (totalItems !== list.length) {\n \n }\n
\n" + }, { "name": "grid-list-statuses-example", "description": "Grid List Statuses", @@ -6073,18 +6073,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-interactive-example',\n templateUrl: './list-interactive-example.component.html',\n imports: [ListModule]\n})\nexport class ListInteractiveExampleComponent {}\n", "html": "
    \n
  • \n Interactive list item 1 \n
  • \n
  • \n Interactive list item 2 \n
  • \n
  • \n Selected list item 3 \n
  • \n
  • \n Interactive Selected list item 4 \n
  • \n
\n" }, - { - "name": "list-keyboard-example", - "description": "List Keyboard", - "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", - "html": "\n
    \n
  • \n List item 1 \n
  • \n
  • \n List item 2 \n
  • \n
  • \n List item 3 \n
  • \n
  • \n List item 4 \n
  • \n
\n" - }, { "name": "list-loading-example", "description": "List Loading", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { SkeletonComponent } from '@fundamental-ngx/core/skeleton';\n\n@Component({\n selector: 'fd-list-loading-example',\n templateUrl: './list-loading-example.component.html',\n imports: [ButtonComponent, ListModule, SkeletonComponent]\n})\nexport class ListLoadingExampleComponent {\n loading = true;\n}\n", "html": "\n
    \n @if (!loading) {\n @for (_ of [0, 1, 2]; track $index) {\n
  • \n List item 1 \n
  • \n }\n } @else {\n @for (_ of [0, 1, 2]; track $index) {\n
  • \n \n
  • \n }\n }\n
\n" }, + { + "name": "list-keyboard-example", + "description": "List Keyboard", + "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", + "html": "\n
    \n
  • \n List item 1 \n
  • \n
  • \n List item 2 \n
  • \n
  • \n List item 3 \n
  • \n
  • \n List item 4 \n
  • \n
\n" + }, { "name": "list-nav-indicator-example", "description": "List Nav Indicator", @@ -6177,18 +6177,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-interactive-example',\n templateUrl: './list-interactive-example.component.html',\n imports: [ListModule]\n})\nexport class ListInteractiveExampleComponent {}\n", "html": "
    \n
  • \n Interactive list item 1 \n
  • \n
  • \n Interactive list item 2 \n
  • \n
  • \n Selected list item 3 \n
  • \n
  • \n Interactive Selected list item 4 \n
  • \n
\n" }, - { - "name": "list-keyboard-example", - "description": "List Keyboard", - "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", - "html": "\n
    \n
  • \n List item 1 \n
  • \n
  • \n List item 2 \n
  • \n
  • \n List item 3 \n
  • \n
  • \n List item 4 \n
  • \n
\n" - }, { "name": "list-loading-example", "description": "List Loading", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { SkeletonComponent } from '@fundamental-ngx/core/skeleton';\n\n@Component({\n selector: 'fd-list-loading-example',\n templateUrl: './list-loading-example.component.html',\n imports: [ButtonComponent, ListModule, SkeletonComponent]\n})\nexport class ListLoadingExampleComponent {\n loading = true;\n}\n", "html": "\n
    \n @if (!loading) {\n @for (_ of [0, 1, 2]; track $index) {\n
  • \n List item 1 \n
  • \n }\n } @else {\n @for (_ of [0, 1, 2]; track $index) {\n
  • \n \n
  • \n }\n }\n
\n" }, + { + "name": "list-keyboard-example", + "description": "List Keyboard", + "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", + "html": "\n
    \n
  • \n List item 1 \n
  • \n
  • \n List item 2 \n
  • \n
  • \n List item 3 \n
  • \n
  • \n List item 4 \n
  • \n
\n" + }, { "name": "list-nav-indicator-example", "description": "List Nav Indicator", @@ -6272,18 +6272,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-interactive-example',\n templateUrl: './list-interactive-example.component.html',\n imports: [ListModule]\n})\nexport class ListInteractiveExampleComponent {}\n", "html": "
    \n
  • \n Interactive list item 1 \n
  • \n
  • \n Interactive list item 2 \n
  • \n
  • \n Selected list item 3 \n
  • \n
  • \n Interactive Selected list item 4 \n
  • \n
\n" }, - { - "name": "list-keyboard-example", - "description": "List Keyboard", - "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", - "html": "\n
    \n
  • \n List item 1 \n
  • \n
  • \n List item 2 \n
  • \n
  • \n List item 3 \n
  • \n
  • \n List item 4 \n
  • \n
\n" - }, { "name": "list-loading-example", "description": "List Loading", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { SkeletonComponent } from '@fundamental-ngx/core/skeleton';\n\n@Component({\n selector: 'fd-list-loading-example',\n templateUrl: './list-loading-example.component.html',\n imports: [ButtonComponent, ListModule, SkeletonComponent]\n})\nexport class ListLoadingExampleComponent {\n loading = true;\n}\n", "html": "\n
    \n @if (!loading) {\n @for (_ of [0, 1, 2]; track $index) {\n
  • \n List item 1 \n
  • \n }\n } @else {\n @for (_ of [0, 1, 2]; track $index) {\n
  • \n \n
  • \n }\n }\n
\n" }, + { + "name": "list-keyboard-example", + "description": "List Keyboard", + "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", + "html": "\n
    \n
  • \n List item 1 \n
  • \n
  • \n List item 2 \n
  • \n
  • \n List item 3 \n
  • \n
  • \n List item 4 \n
  • \n
\n" + }, { "name": "list-nav-indicator-example", "description": "List Nav Indicator", @@ -6362,18 +6362,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-interactive-example',\n templateUrl: './list-interactive-example.component.html',\n imports: [ListModule]\n})\nexport class ListInteractiveExampleComponent {}\n", "html": "
    \n
  • \n Interactive list item 1 \n
  • \n
  • \n Interactive list item 2 \n
  • \n
  • \n Selected list item 3 \n
  • \n
  • \n Interactive Selected list item 4 \n
  • \n
\n" }, - { - "name": "list-keyboard-example", - "description": "List Keyboard", - "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", - "html": "\n
    \n
  • \n List item 1 \n
  • \n
  • \n List item 2 \n
  • \n
  • \n List item 3 \n
  • \n
  • \n List item 4 \n
  • \n
\n" - }, { "name": "list-loading-example", "description": "List Loading", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { SkeletonComponent } from '@fundamental-ngx/core/skeleton';\n\n@Component({\n selector: 'fd-list-loading-example',\n templateUrl: './list-loading-example.component.html',\n imports: [ButtonComponent, ListModule, SkeletonComponent]\n})\nexport class ListLoadingExampleComponent {\n loading = true;\n}\n", "html": "\n
    \n @if (!loading) {\n @for (_ of [0, 1, 2]; track $index) {\n
  • \n List item 1 \n
  • \n }\n } @else {\n @for (_ of [0, 1, 2]; track $index) {\n
  • \n \n
  • \n }\n }\n
\n" }, + { + "name": "list-keyboard-example", + "description": "List Keyboard", + "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", + "html": "\n
    \n
  • \n List item 1 \n
  • \n
  • \n List item 2 \n
  • \n
  • \n List item 3 \n
  • \n
  • \n List item 4 \n
  • \n
\n" + }, { "name": "list-nav-indicator-example", "description": "List Nav Indicator", @@ -6444,18 +6444,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-interactive-example',\n templateUrl: './list-interactive-example.component.html',\n imports: [ListModule]\n})\nexport class ListInteractiveExampleComponent {}\n", "html": "
    \n
  • \n Interactive list item 1 \n
  • \n
  • \n Interactive list item 2 \n
  • \n
  • \n Selected list item 3 \n
  • \n
  • \n Interactive Selected list item 4 \n
  • \n
\n" }, - { - "name": "list-keyboard-example", - "description": "List Keyboard", - "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", - "html": "\n
    \n
  • \n List item 1 \n
  • \n
  • \n List item 2 \n
  • \n
  • \n List item 3 \n
  • \n
  • \n List item 4 \n
  • \n
\n" - }, { "name": "list-loading-example", "description": "List Loading", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { SkeletonComponent } from '@fundamental-ngx/core/skeleton';\n\n@Component({\n selector: 'fd-list-loading-example',\n templateUrl: './list-loading-example.component.html',\n imports: [ButtonComponent, ListModule, SkeletonComponent]\n})\nexport class ListLoadingExampleComponent {\n loading = true;\n}\n", "html": "\n
    \n @if (!loading) {\n @for (_ of [0, 1, 2]; track $index) {\n
  • \n List item 1 \n
  • \n }\n } @else {\n @for (_ of [0, 1, 2]; track $index) {\n
  • \n \n
  • \n }\n }\n
\n" }, + { + "name": "list-keyboard-example", + "description": "List Keyboard", + "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", + "html": "\n
    \n
  • \n List item 1 \n
  • \n
  • \n List item 2 \n
  • \n
  • \n List item 3 \n
  • \n
  • \n List item 4 \n
  • \n
\n" + }, { "name": "list-nav-indicator-example", "description": "List Nav Indicator", @@ -6554,18 +6554,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-interactive-example',\n templateUrl: './list-interactive-example.component.html',\n imports: [ListModule]\n})\nexport class ListInteractiveExampleComponent {}\n", "html": "
    \n
  • \n Interactive list item 1 \n
  • \n
  • \n Interactive list item 2 \n
  • \n
  • \n Selected list item 3 \n
  • \n
  • \n Interactive Selected list item 4 \n
  • \n
\n" }, - { - "name": "list-keyboard-example", - "description": "List Keyboard", - "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", - "html": "\n
    \n
  • \n List item 1 \n
  • \n
  • \n List item 2 \n
  • \n
  • \n List item 3 \n
  • \n
  • \n List item 4 \n
  • \n
\n" - }, { "name": "list-loading-example", "description": "List Loading", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { SkeletonComponent } from '@fundamental-ngx/core/skeleton';\n\n@Component({\n selector: 'fd-list-loading-example',\n templateUrl: './list-loading-example.component.html',\n imports: [ButtonComponent, ListModule, SkeletonComponent]\n})\nexport class ListLoadingExampleComponent {\n loading = true;\n}\n", "html": "\n
    \n @if (!loading) {\n @for (_ of [0, 1, 2]; track $index) {\n
  • \n List item 1 \n
  • \n }\n } @else {\n @for (_ of [0, 1, 2]; track $index) {\n
  • \n \n
  • \n }\n }\n
\n" }, + { + "name": "list-keyboard-example", + "description": "List Keyboard", + "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", + "html": "\n
    \n
  • \n List item 1 \n
  • \n
  • \n List item 2 \n
  • \n
  • \n List item 3 \n
  • \n
  • \n List item 4 \n
  • \n
\n" + }, { "name": "list-nav-indicator-example", "description": "List Nav Indicator", @@ -6643,18 +6643,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-interactive-example',\n templateUrl: './list-interactive-example.component.html',\n imports: [ListModule]\n})\nexport class ListInteractiveExampleComponent {}\n", "html": "
    \n
  • \n Interactive list item 1 \n
  • \n
  • \n Interactive list item 2 \n
  • \n
  • \n Selected list item 3 \n
  • \n
  • \n Interactive Selected list item 4 \n
  • \n
\n" }, - { - "name": "list-keyboard-example", - "description": "List Keyboard", - "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", - "html": "\n
    \n
  • \n List item 1 \n
  • \n
  • \n List item 2 \n
  • \n
  • \n List item 3 \n
  • \n
  • \n List item 4 \n
  • \n
\n" - }, { "name": "list-loading-example", "description": "List Loading", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { SkeletonComponent } from '@fundamental-ngx/core/skeleton';\n\n@Component({\n selector: 'fd-list-loading-example',\n templateUrl: './list-loading-example.component.html',\n imports: [ButtonComponent, ListModule, SkeletonComponent]\n})\nexport class ListLoadingExampleComponent {\n loading = true;\n}\n", "html": "\n
    \n @if (!loading) {\n @for (_ of [0, 1, 2]; track $index) {\n
  • \n List item 1 \n
  • \n }\n } @else {\n @for (_ of [0, 1, 2]; track $index) {\n
  • \n \n
  • \n }\n }\n
\n" }, + { + "name": "list-keyboard-example", + "description": "List Keyboard", + "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", + "html": "\n
    \n
  • \n List item 1 \n
  • \n
  • \n List item 2 \n
  • \n
  • \n List item 3 \n
  • \n
  • \n List item 4 \n
  • \n
\n" + }, { "name": "list-nav-indicator-example", "description": "List Nav Indicator", @@ -6725,18 +6725,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-interactive-example',\n templateUrl: './list-interactive-example.component.html',\n imports: [ListModule]\n})\nexport class ListInteractiveExampleComponent {}\n", "html": "
    \n
  • \n Interactive list item 1 \n
  • \n
  • \n Interactive list item 2 \n
  • \n
  • \n Selected list item 3 \n
  • \n
  • \n Interactive Selected list item 4 \n
  • \n
\n" }, - { - "name": "list-keyboard-example", - "description": "List Keyboard", - "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", - "html": "\n
    \n
  • \n List item 1 \n
  • \n
  • \n List item 2 \n
  • \n
  • \n List item 3 \n
  • \n
  • \n List item 4 \n
  • \n
\n" - }, { "name": "list-loading-example", "description": "List Loading", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { SkeletonComponent } from '@fundamental-ngx/core/skeleton';\n\n@Component({\n selector: 'fd-list-loading-example',\n templateUrl: './list-loading-example.component.html',\n imports: [ButtonComponent, ListModule, SkeletonComponent]\n})\nexport class ListLoadingExampleComponent {\n loading = true;\n}\n", "html": "\n
    \n @if (!loading) {\n @for (_ of [0, 1, 2]; track $index) {\n
  • \n List item 1 \n
  • \n }\n } @else {\n @for (_ of [0, 1, 2]; track $index) {\n
  • \n \n
  • \n }\n }\n
\n" }, + { + "name": "list-keyboard-example", + "description": "List Keyboard", + "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", + "html": "\n
    \n
  • \n List item 1 \n
  • \n
  • \n List item 2 \n
  • \n
  • \n List item 3 \n
  • \n
  • \n List item 4 \n
  • \n
\n" + }, { "name": "list-nav-indicator-example", "description": "List Nav Indicator", @@ -6826,18 +6826,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-interactive-example',\n templateUrl: './list-interactive-example.component.html',\n imports: [ListModule]\n})\nexport class ListInteractiveExampleComponent {}\n", "html": "
    \n
  • \n Interactive list item 1 \n
  • \n
  • \n Interactive list item 2 \n
  • \n
  • \n Selected list item 3 \n
  • \n
  • \n Interactive Selected list item 4 \n
  • \n
\n" }, - { - "name": "list-keyboard-example", - "description": "List Keyboard", - "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", - "html": "\n
    \n
  • \n List item 1 \n
  • \n
  • \n List item 2 \n
  • \n
  • \n List item 3 \n
  • \n
  • \n List item 4 \n
  • \n
\n" - }, { "name": "list-loading-example", "description": "List Loading", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { SkeletonComponent } from '@fundamental-ngx/core/skeleton';\n\n@Component({\n selector: 'fd-list-loading-example',\n templateUrl: './list-loading-example.component.html',\n imports: [ButtonComponent, ListModule, SkeletonComponent]\n})\nexport class ListLoadingExampleComponent {\n loading = true;\n}\n", "html": "\n
    \n @if (!loading) {\n @for (_ of [0, 1, 2]; track $index) {\n
  • \n List item 1 \n
  • \n }\n } @else {\n @for (_ of [0, 1, 2]; track $index) {\n
  • \n \n
  • \n }\n }\n
\n" }, + { + "name": "list-keyboard-example", + "description": "List Keyboard", + "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", + "html": "\n
    \n
  • \n List item 1 \n
  • \n
  • \n List item 2 \n
  • \n
  • \n List item 3 \n
  • \n
  • \n List item 4 \n
  • \n
\n" + }, { "name": "list-nav-indicator-example", "description": "List Nav Indicator", @@ -7050,18 +7050,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-interactive-example',\n templateUrl: './list-interactive-example.component.html',\n imports: [ListModule]\n})\nexport class ListInteractiveExampleComponent {}\n", "html": "
    \n
  • \n Interactive list item 1 \n
  • \n
  • \n Interactive list item 2 \n
  • \n
  • \n Selected list item 3 \n
  • \n
  • \n Interactive Selected list item 4 \n
  • \n
\n" }, - { - "name": "list-keyboard-example", - "description": "List Keyboard", - "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", - "html": "\n
    \n
  • \n List item 1 \n
  • \n
  • \n List item 2 \n
  • \n
  • \n List item 3 \n
  • \n
  • \n List item 4 \n
  • \n
\n" - }, { "name": "list-loading-example", "description": "List Loading", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { SkeletonComponent } from '@fundamental-ngx/core/skeleton';\n\n@Component({\n selector: 'fd-list-loading-example',\n templateUrl: './list-loading-example.component.html',\n imports: [ButtonComponent, ListModule, SkeletonComponent]\n})\nexport class ListLoadingExampleComponent {\n loading = true;\n}\n", "html": "\n
    \n @if (!loading) {\n @for (_ of [0, 1, 2]; track $index) {\n
  • \n List item 1 \n
  • \n }\n } @else {\n @for (_ of [0, 1, 2]; track $index) {\n
  • \n \n
  • \n }\n }\n
\n" }, + { + "name": "list-keyboard-example", + "description": "List Keyboard", + "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", + "html": "\n
    \n
  • \n List item 1 \n
  • \n
  • \n List item 2 \n
  • \n
  • \n List item 3 \n
  • \n
  • \n List item 4 \n
  • \n
\n" + }, { "name": "list-nav-indicator-example", "description": "List Nav Indicator", @@ -7807,18 +7807,18 @@ "sourceFile": "libs/core/select/option/option.component.ts", "source": "typedoc", "examples": [ - { - "name": "select-adding-example", - "description": "Select Adding", - "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { SelectModule } from '@fundamental-ngx/core/select';\n\n@Component({\n selector: 'fd-select-adding-example',\n templateUrl: './select-adding-example.component.html',\n styleUrls: ['./select-adding-example.component.scss'],\n imports: [ButtonComponent, SelectModule]\n})\nexport class SelectAddingExampleComponent {\n options: string[] = ['Apple', 'Pineapple', 'Tomato', 'Strawberry'];\n\n selectedValue: string;\n\n addedOptions = 1;\n\n addOption(): void {\n this.options.push(`New option ${this.addedOptions++}`);\n }\n\n removeOption(): void {\n if (this.options.length > 1) {\n this.options.pop();\n }\n }\n}\n", - "html": "
\n \n \n
\n\n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n
    \nSelected value: {{ selectedValue }}\n" - }, { "name": "select-custom-comparator-example", "description": "Select Custom Comparator", "typescript": "import { Component } from '@angular/core';\nimport { SelectModule } from '@fundamental-ngx/core/select';\n\ntype CarType = { id: string; name: string };\n\n@Component({\n selector: 'fd-select-custom-comparator-example',\n templateUrl: './select-custom-comparator-example.component.html',\n imports: [SelectModule]\n})\n// eslint-disable-next-line @angular-eslint/component-class-suffix\nexport class SelectCustomComparatorExample {\n carTypes: CarType[] = [\n { id: '1', name: 'Hatchback' },\n { id: '2', name: 'Sedan' },\n { id: '3', name: 'Coupe' }\n ];\n selectedCarType: CarType = { id: '1', name: 'Hatchback' };\n\n get optionMatchedByValue(): string {\n const matchingIndex = this.carTypes.findIndex((carType) => this.comparator(carType, this.selectedCarType));\n if (matchingIndex < 0) {\n return 'No available option that matches the selected option by value';\n }\n return JSON.stringify(this.carTypes[matchingIndex], undefined, 2);\n }\n\n get optionMatchedByReference(): string {\n const matchingIndex = this.carTypes.findIndex((carType) => carType === this.selectedCarType);\n if (matchingIndex < 0) {\n return 'No available option that matches the selected option by reference';\n }\n return JSON.stringify(this.carTypes[matchingIndex], undefined, 2);\n }\n\n comparator: (obj1: CarType, obj2: CarType) => boolean = (obj1: CarType, obj2: CarType) =>\n obj1 && obj2 && obj1.id === obj2.id;\n\n setCarTypeByCopy(newValue: CarType): void {\n this.selectedCarType = { ...newValue };\n }\n}\n", "html": "

    Custom comparator

    \n\n @for (carType of carTypes; track carType) {\n {{ carType.name }}\n }\n\n

    Options matching selected option by value: \"{{ optionMatchedByValue }}\".

    \n

    Options matching selected option by reference: \"{{ optionMatchedByReference }}\".

    \n" }, + { + "name": "select-adding-example", + "description": "Select Adding", + "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { SelectModule } from '@fundamental-ngx/core/select';\n\n@Component({\n selector: 'fd-select-adding-example',\n templateUrl: './select-adding-example.component.html',\n styleUrls: ['./select-adding-example.component.scss'],\n imports: [ButtonComponent, SelectModule]\n})\nexport class SelectAddingExampleComponent {\n options: string[] = ['Apple', 'Pineapple', 'Tomato', 'Strawberry'];\n\n selectedValue: string;\n\n addedOptions = 1;\n\n addOption(): void {\n this.options.push(`New option ${this.addedOptions++}`);\n }\n\n removeOption(): void {\n if (this.options.length > 1) {\n this.options.pop();\n }\n }\n}\n", + "html": "
    \n \n \n
    \n\n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n
    \nSelected value: {{ selectedValue }}\n" + }, { "name": "select-max-height-example", "description": "Select Max Height", @@ -7831,6 +7831,12 @@ "typescript": "import { Component } from '@angular/core';\nimport { MobileModeConfig } from '@fundamental-ngx/core/mobile-mode';\nimport { SelectModule } from '@fundamental-ngx/core/select';\n\n@Component({\n selector: 'fd-select-mobile-example',\n templateUrl: './select-mobile-example.component.html',\n imports: [SelectModule]\n})\nexport class SelectMobileExampleComponent {\n options: string[] = ['Apple', 'Pineapple', 'Tomato', 'Strawberry'];\n mobileConfig: MobileModeConfig = { hasCloseButton: true, title: 'Select your favourite fruit' };\n selectedValue: string;\n}\n", "html": "\n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n\nSelected value: {{ selectedValue }}\n" }, + { + "name": "select-semantic-state-example", + "description": "Select Semantic State", + "typescript": "import { Component } from '@angular/core';\nimport { FormInputMessageGroupComponent, FormItemComponent, FormMessageComponent } from '@fundamental-ngx/core/form';\nimport { SelectModule } from '@fundamental-ngx/core/select';\n\n@Component({\n selector: 'fd-select-semantic-state-example',\n templateUrl: './select-semantic-state-example.component.html',\n imports: [FormItemComponent, SelectModule, FormMessageComponent, FormInputMessageGroupComponent]\n})\nexport class SelectSemanticStateExampleComponent {\n options: string[] = ['Apple', 'Pineapple', 'Tomato', 'Strawberry'];\n selectedValue1: string;\n selectedValue2: string;\n selectedValue3: string;\n selectedValue4: string;\n}\n", + "html": "

    Success state (with visible long text)

    \n
    \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n \n Success message\n
    \n

    Warning state

    \n
    \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n
    \n Warning message\n
    \n

    Error state

    \n
    \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n
    \n Error message\n
    \n

    Information state

    \n
    \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n \n Information message\n
    \n\n

    Form message with event triggers:

    \n
    \n \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n \n \n Success message\n
    \n
    \n" + }, { "name": "select-mode-example", "description": "Select Mode", @@ -7842,12 +7848,6 @@ "description": "Select Programmatic", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { SelectModule } from '@fundamental-ngx/core/select';\n\n@Component({\n selector: 'fd-select-programmatic-example',\n templateUrl: './select-programmatic-example.component.html',\n styleUrls: ['./select-programmatic-example.component.scss'],\n imports: [ButtonComponent, SelectModule]\n})\nexport class SelectProgrammaticExampleComponent {\n options: string[] = ['Apple', 'Pineapple', 'Tomato', 'Strawberry'];\n selectedPosition = 0;\n\n selectedValue: string = this.options[0];\n newValue = this.options[0];\n\n changeValue(): void {\n this.selectedValue = this.getNewValue();\n }\n\n getPosition(selectedValue: string): number {\n return this.options.findIndex((item) => selectedValue === item);\n }\n\n getNewValue(): string {\n this.selectedPosition = this.getPosition(this.selectedValue);\n\n if (this.selectedPosition < this.options.length - 1) {\n this.selectedPosition++;\n } else {\n this.selectedPosition = 0;\n }\n\n this.newValue = this.options[this.selectedPosition];\n return this.selectedValue === this.newValue ? this.getNewValue() : this.newValue;\n }\n}\n", "html": "
    \n \n \n \n
    \n\n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n
    \nSelected value: {{ selectedValue }}\n" - }, - { - "name": "select-semantic-state-example", - "description": "Select Semantic State", - "typescript": "import { Component } from '@angular/core';\nimport { FormInputMessageGroupComponent, FormItemComponent, FormMessageComponent } from '@fundamental-ngx/core/form';\nimport { SelectModule } from '@fundamental-ngx/core/select';\n\n@Component({\n selector: 'fd-select-semantic-state-example',\n templateUrl: './select-semantic-state-example.component.html',\n imports: [FormItemComponent, SelectModule, FormMessageComponent, FormInputMessageGroupComponent]\n})\nexport class SelectSemanticStateExampleComponent {\n options: string[] = ['Apple', 'Pineapple', 'Tomato', 'Strawberry'];\n selectedValue1: string;\n selectedValue2: string;\n selectedValue3: string;\n selectedValue4: string;\n}\n", - "html": "

    Success state (with visible long text)

    \n
    \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n \n Success message\n
    \n

    Warning state

    \n
    \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n
    \n Warning message\n
    \n

    Error state

    \n
    \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n
    \n Error message\n
    \n

    Information state

    \n
    \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n \n Information message\n
    \n\n

    Form message with event triggers:

    \n
    \n \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n \n \n Success message\n
    \n
    \n" } ] }, @@ -8314,17 +8314,17 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { SliderComponent } from '@fundamental-ngx/core/slider';\n\n@Component({\n selector: 'fd-slider-ticks-and-labels-example',\n templateUrl: './slider-ticks-and-labels-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [SliderComponent, FormsModule]\n})\nexport class SliderTicksAndLabelsExampleComponent {\n value = 25;\n value1 = 25;\n}\n", "html": "
    \n

    \n You can apply tick marks to the slider. The tick marks are related to the step property and are responsive. If\n the distance between 2 tick marks is less than 8 px, all tick marks except for the first and last disappear.\n
    \n To apply tick marks to the slider set [showTicks] as true\n

    \n \n

    Value: {{ value }}

    \n
    \n
    \n\n
    \n

    \n If tick marks are set, you can define labels for the tick marks. The labels are displayed below the tick marks\n and show the corresponding value of the tick mark. You can also define labels only for specific tick marks if\n you don’t need a label for every tick mark on the slider.\n
    \n To apply tick marks to the slider set [showTicks] as true and\n [showTicksLabels] as true\n

    \n \n \n

    Value: {{ value1 }}

    \n
    \n" }, - { - "name": "slider-tooltip-example", - "description": "Slider Tooltip", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { SliderComponent } from '@fundamental-ngx/core/slider';\n\n@Component({\n selector: 'fd-slider-tooltip-example',\n templateUrl: './slider-tooltip-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [SliderComponent, FormsModule]\n})\nexport class SliderTooltipExampleComponent {\n value = 50;\n value1 = 0;\n}\n", - "html": "
    \n

    \n The slider can be used tooltip with the text field. In this case, the value of the grip is displayed.\n
    \n To use it set [tooltipMode] as readonly\n

    \n \n

    Value: {{ value }}

    \n
    \n
    \n\n
    \n

    \n The slider can be used tooltip with the input field instead of the text field. This allows entering a specific\n value.\n
    \n To use it set [tooltipMode] as editable\n

    \n \n

    Value: {{ value1 }}

    \n
    \n" - }, { "name": "vertical-slider-example", "description": "Vertical Slider", "typescript": "import { JsonPipe, NgStyle } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { SliderComponent, SliderCustomValue } from '@fundamental-ngx/core/slider';\n\n@Component({\n selector: 'fd-vertical-slider-example',\n templateUrl: './vertical-slider-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [SliderComponent, FormsModule, JsonPipe, NgStyle]\n})\nexport class VerticalSliderExampleComponent {\n value = [20, 70];\n\n customValues: SliderCustomValue[] = [\n { value: 1609452000000, label: 'Jan 1' },\n { value: 1609538400000, label: 'Jan 2' },\n { value: 1609624800000, label: 'Jan 3' },\n { value: 1609711200000, label: 'Jan 4' },\n { value: 1609797600000, label: 'Jan 5' },\n { value: 1609884000000, label: 'Jan 6' },\n { value: 1609970400000, label: 'Jan 7' },\n { value: 1610056800000, label: 'Jan 8' },\n { value: 1610143200000, label: 'Jan 9' },\n { value: 1610229600000, label: 'Jan 10' }\n ];\n\n value2 = [this.customValues[4], this.customValues[6]];\n}\n", "html": "
    \n

    \n To use Range Slider need to set [mode] as range (by default [mode] as\n single)\n

    \n
    \n \n
    \n\n

    \n Min value: {{ value[0] }}\n
    \n Max value: {{ value[1] }}\n

    \n
    \n
    \n\n
    \n

    Range slided with Custom Values.

    \n
    \n \n \n
    \n\n

    \n Min value: {{ value2[0] | json }}\n
    \n Max value: {{ value2[1] | json }}\n

    \n
    \n" + }, + { + "name": "slider-tooltip-example", + "description": "Slider Tooltip", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { SliderComponent } from '@fundamental-ngx/core/slider';\n\n@Component({\n selector: 'fd-slider-tooltip-example',\n templateUrl: './slider-tooltip-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [SliderComponent, FormsModule]\n})\nexport class SliderTooltipExampleComponent {\n value = 50;\n value1 = 0;\n}\n", + "html": "
    \n

    \n The slider can be used tooltip with the text field. In this case, the value of the grip is displayed.\n
    \n To use it set [tooltipMode] as readonly\n

    \n \n

    Value: {{ value }}

    \n
    \n
    \n\n
    \n

    \n The slider can be used tooltip with the input field instead of the text field. This allows entering a specific\n value.\n
    \n To use it set [tooltipMode] as editable\n

    \n \n

    Value: {{ value1 }}

    \n
    \n" } ] }, @@ -8612,17 +8612,17 @@ "typescript": "import { UpperCasePipe } from '@angular/common';\nimport { Component, ViewChild } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { DialogRef, DialogService } from '@fundamental-ngx/core/dialog';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableComponent, TableModule } from '@fundamental-ngx/core/table';\nimport { TableCustomDialogComponent } from './table-custom-dialog.component';\n\nexport interface DisplayedColumn {\n key: string;\n checked: boolean;\n}\n\nexport interface CellData {\n column1: string;\n column2: string;\n column3: string;\n date: string;\n type: string;\n}\n\nconst CELL_DATA: CellData[] = [\n { column1: 'Row 111', column2: 'Row 221', column3: 'Row 1', date: '09-07-18', type: 'search' },\n { column1: 'Row 112', column2: 'Row 222', column3: 'Row 2', date: '09-08-18', type: 'cart' },\n { column1: 'Row 113', column2: 'Row 223', column3: 'Row 3', date: '02-14-18', type: 'calendar' },\n { column1: 'Row 114', column2: 'Row 224', column3: 'Row 4', date: '12-30-17', type: 'search' },\n { column1: 'Row 115', column2: 'Row 225', column3: 'Row 5', date: '11-12-18', type: 'search' }\n];\n\n@Component({\n selector: 'fd-table-custom-columns-example',\n templateUrl: './table-custom-columns-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, IconComponent, ButtonComponent, UpperCasePipe]\n})\nexport class TableCustomColumnsExampleComponent {\n @ViewChild(TableComponent)\n tableComponent: TableComponent;\n\n displayedColumns: string[];\n originalDisplayedColumns: DisplayedColumn[];\n dataSource = CELL_DATA;\n dialogRef: DialogRef;\n\n constructor(private _dialogService: DialogService) {\n this.displayedColumns = Object.keys(this.dataSource[0]);\n this.originalDisplayedColumns = [];\n\n Object.keys(this.dataSource[0]).forEach((key) => {\n this.originalDisplayedColumns.push({ key, checked: true });\n });\n }\n\n openDialog(): void {\n const dialogRef = this._dialogService.open(TableCustomDialogComponent, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n data: {\n columns: this.originalDisplayedColumns\n }\n });\n\n dialogRef.afterClosed.subscribe(\n (columns) => {\n this.originalDisplayedColumns = [...columns];\n this._propagateChangeToDisplayedValue();\n },\n () => {\n console.log('closed without changes');\n }\n );\n }\n\n private _propagateChangeToDisplayedValue(): void {\n this.displayedColumns = [\n ...this.originalDisplayedColumns.filter((_col) => _col.checked).map((_col) => _col.key)\n ];\n this.tableComponent.reset(this.displayedColumns);\n }\n}\n", "html": "\n \n \n @for (column of displayedColumns; track column) {\n \n }\n \n \n \n @for (row of dataSource; track row) {\n \n \n \n \n \n \n \n }\n \n
    {{ column | uppercase }}
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}
    \n
    \n
    \nChosen Columns: {{ displayedColumns }}\n
    \n
    \n\n" }, - { - "name": "table-focusable-example", - "description": "Table Focusable", - "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", - "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" - }, { "name": "table-popin-example", "description": "Table Popin", "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-popin-example',\n templateUrl: './table-popin-example.component.html',\n styles: [\n `\n .table-example-popin-title {\n margin: 0 0 10px 0;\n }\n `\n ],\n imports: [\n FocusableGridDirective,\n TableModule,\n FormLabelComponent,\n ObjectStatusComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class TablePopinExampleComponent {\n masterCheckbox: boolean | null = false;\n\n fruits: any[] = [\n {\n name: 'Banana',\n status: 'positive',\n statusName: 'Available',\n dateOfExpire: '12.06.2020',\n price: '5 EUR',\n country: 'India',\n description: `A banana is an elongated, edible fruit – botanically a berry – produced by several kinds of large herbaceous\n flowering plants in the genus Musa.`,\n checked: false\n },\n {\n name: 'Apple',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '10.06.2020',\n price: '5,5 EUR',\n country: 'USA',\n description: `An apple is an edible fruit produced by an apple tree (Malus domestica).\n Apple trees are cultivated worldwide and are the most widely grown species in the genus Malus.`,\n checked: false\n },\n {\n name: 'Pineapple',\n status: 'negative',\n statusName: 'Out of stock',\n dateOfExpire: '08.06.2020',\n price: '6 EUR',\n country: 'Mexico',\n description: `The pineapple (Ananas comosus) is a tropical plant with an edible fruit and the most\n economically significant plant in the family Bromeliaceae.`,\n checked: false\n },\n {\n name: 'Orange',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '18.06.2020',\n price: '10 EUR',\n country: 'Spain',\n description: `The orange is the fruit of various citrus species in the family Rutaceae\n (see list of plants known as orange); it primarily refers to Citrus × sinensis.`,\n checked: false\n }\n ];\n\n constructor() {}\n\n select(index: number, checked: boolean): void {\n this.fruits[index].checked = checked;\n\n this._handleMasterCheckboxState();\n }\n\n selectMaster(checked: boolean): void {\n checked ? this._selectAll() : this._deselectAll();\n\n this._handleMasterCheckboxState();\n }\n\n private _handleMasterCheckboxState(): void {\n this.masterCheckbox = this._allSelected() ? true : this._anySelected() ? null : false;\n }\n\n private _selectAll(): void {\n this.fruits.forEach((row) => (row.checked = true));\n }\n\n private _deselectAll(): void {\n this.fruits.forEach((row) => (row.checked = false));\n }\n\n private _anySelected(): boolean {\n return this.fruits.some((_row) => _row.checked);\n }\n\n private _allSelected(): boolean {\n return this.fruits.every((_row) => _row.checked);\n }\n}\n", "html": "
    \n

    Mobile Mode

    \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Tablet Mode

    \n \n \n \n Fruit Description\n Price\n Status\n Date Of Expire\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n {{ fruit.dateOfExpire }}\n \n \n \n \n \n \n \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Desktop Mode

    \n \n \n \n \n \n \n \n \n \n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n \n \n \n \n \n \n \n }\n \n
    NamePriceCountryStatusDate Of ExpireDescription
    \n {{ fruit.name }}\n \n {{ fruit.country }}\n \n {{ fruit.price }}\n \n \n \n {{ fruit.dateOfExpire }}\n \n {{ fruit.description }}\n \n \n
    \n
    \n
    \n

    Popin Mobile Mode with Checkboxes

    \n \n \n \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit; let ind = $index) {\n \n \n \n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n" + }, + { + "name": "table-focusable-example", + "description": "Table Focusable", + "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", + "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" } ] }, @@ -10213,18 +10213,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

    Table card

    \n 3 of 10\n
    \n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    NameCountryPriceStatus
    BananaIndia5 EUR\n \n
    PineappleMexico2 EUR\n \n
    OrangeSpain6 EUR\n \n
    \n
    \n
    \n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
    \n \n \n \n

    My calendar

    \n

    {{ calendarViewSubTitle }}

    \n 4 of 10\n
    \n
    \n\n \n \n \n
    \n
    \n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -10337,18 +10337,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

    Table card

    \n 3 of 10\n
    \n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    NameCountryPriceStatus
    BananaIndia5 EUR\n \n
    PineappleMexico2 EUR\n \n
    OrangeSpain6 EUR\n \n
    \n
    \n
    \n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
    \n \n \n \n

    My calendar

    \n

    {{ calendarViewSubTitle }}

    \n 4 of 10\n
    \n
    \n\n \n \n \n
    \n
    \n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -10819,6 +10819,12 @@ "description": "Dialog", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\n\nimport { NgStyle } from '@angular/common';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogRef\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n template: `\n \n \n

    {{ dialogRef.data.title }}

    \n
    \n \n

    \n {{ dialogRef.data.pinnapleDescription }}\n

    \n
      \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
    • \n {{ fact }}\n
    • \n }\n
    \n
    \n \n \n \n \n \n \n
    \n `,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n" }, + { + "name": "dialog-configuration-example", + "description": "Dialog Configuration", + "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-configuration-example',\n templateUrl: './dialog-configuration-example.component.html',\n styleUrls: ['./dialog-configuration-example.component.scss'],\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogConfigurationExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDraggableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n draggable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openResizableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n resizable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openClosableByButtonDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n escKeyCloseable: false,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n}\n", + "html": "\n \n \n

    Origin of the Pineapple Word

    \n
    \n\n \n
    \n The word pineapple in English was first recorded in 1398, when it was originally used to describe the\n reproductive organs of conifer trees (now termed pine cones). When European explorers discovered this\n tropical fruit they called them pineapples (term first recorded in that sense in 1664) because of their\n resemblance to what is now known as the pine cone. The term pine cone was first recorded in 1694, and\n was used to replace the original meaning of pineapple.\n
    \n
    \n\n \n \n \n \n
    \n
    \n\n\n\n\n" + }, { "name": "dialog-backdrop-container-example", "description": "Dialog Backdrop Container", @@ -10831,30 +10837,24 @@ "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { AsyncPipe, NgClass } from '@angular/common';\nimport { Component, TemplateRef } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { InitialFocusDirective, TemplateDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ListModule, ListSecondaryDirective } from '@fundamental-ngx/core/list';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\ninterface Fruit {\n id: number;\n name: string;\n price: number;\n}\n\n@Component({\n selector: 'fd-dialog-complex-example',\n templateUrl: './dialog-complex-example.component.html',\n imports: [\n TemplateDirective,\n BarModule,\n TitleComponent,\n InputGroupModule,\n InitialFocusDirective,\n FormsModule,\n CdkScrollable,\n ScrollbarDirective,\n ListModule,\n NgClass,\n ListSecondaryDirective,\n ButtonComponent,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogComplexExampleComponent {\n fruitCollection: Fruit[] = [\n { id: 1, name: 'Pineapple', price: Infinity },\n { id: 2, name: 'Passion Fruit', price: 10.0 },\n { id: 3, name: 'Papaya', price: 8.99 },\n { id: 4, name: 'Kiwifruit', price: 3.0 },\n { id: 5, name: 'Mango', price: 15.0 },\n { id: 6, name: 'Pomegranate', price: 12.5 },\n { id: 7, name: 'Guava', price: 10.15 },\n { id: 8, name: 'Durian', price: 15.25 },\n { id: 9, name: 'Jackfruit', price: 10.0 },\n { id: 10, name: 'Dragon Fruit', price: 9.0 },\n { id: 11, name: 'Cherimoya', price: 7.45 },\n { id: 12, name: 'Kiwano', price: 4.5 },\n { id: 13, name: 'Korean Melon', price: 6.5 },\n { id: 14, name: 'Feijoa', price: 2.0 },\n { id: 15, name: 'Tamarillo ', price: 8.75 },\n { id: 16, name: 'Loquat', price: 0.99 }\n ];\n\n selectedFruits: Fruit[] = [];\n\n dialogRef: DialogRef;\n\n searchedPhrase = '';\n\n constructor(public _dialogService: DialogService) {}\n\n openDialog(template: TemplateRef): void {\n this.dialogRef = this._dialogService.open(template, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n ariaLabelledBy: 'fd-dialog-header-complex',\n ariaDescribedBy: 'fd-dialog-description-complex'\n });\n this.dialogRef.loading(true);\n setTimeout(() => this.dialogRef.loading(false), 2000);\n }\n\n get totalPrice(): number {\n const sum = this.selectedFruits.reduce((total, fruit) => total + fruit.price, 0);\n return Math.round(sum * 100) / 100;\n }\n\n filterFruits(fruits: Fruit[], searchedPhrase: string): Fruit[] {\n return this.fruitCollection.filter((fruit) => fruit.name.toLowerCase().includes(searchedPhrase.toLowerCase()));\n }\n\n isSelected(id: number): boolean {\n return this.selectedFruits.some((fruit) => fruit.id === id);\n }\n\n selectFruit(fruit: Fruit): void {\n const fruitIndex = this.selectedFruits.indexOf(fruit);\n\n if (fruitIndex !== -1) {\n this.selectedFruits.splice(fruitIndex, 1);\n } else {\n this.selectedFruits.push(fruit);\n }\n }\n\n clear(): void {\n this.searchedPhrase = '';\n this.selectedFruits = [];\n }\n\n checkout(): void {\n this.dialogRef.close();\n }\n}\n", "html": "\n \n \n \n
    \n \n

    Fresh Market

    \n Search for fresh produce items\n
    \n
    \n
    \n \n
    \n
    \n \n
    \n \n \n \n \n
    \n
    \n
    \n \n @if ((dialogRef.onLoading | async) === false) {\n
      \n @for (fruit of filterFruits(fruitCollection, searchedPhrase); track fruit) {\n
    • \n {{ fruit.name }}\n {{ fruit.price }} €\n
    • \n }\n
    \n }\n
    \n \n \n
    \n Total price: {{ totalPrice }}€ \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n" }, - { - "name": "dialog-configuration-example", - "description": "Dialog Configuration", - "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-configuration-example',\n templateUrl: './dialog-configuration-example.component.html',\n styleUrls: ['./dialog-configuration-example.component.scss'],\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogConfigurationExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDraggableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n draggable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openResizableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n resizable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openClosableByButtonDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n escKeyCloseable: false,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n}\n", - "html": "\n \n \n

    Origin of the Pineapple Word

    \n
    \n\n \n
    \n The word pineapple in English was first recorded in 1398, when it was originally used to describe the\n reproductive organs of conifer trees (now termed pine cones). When European explorers discovered this\n tropical fruit they called them pineapples (term first recorded in that sense in 1664) because of their\n resemblance to what is now known as the pine cone. The term pine cone was first recorded in 1694, and\n was used to replace the original meaning of pineapple.\n
    \n
    \n\n \n \n \n \n
    \n
    \n\n\n\n\n" - }, { "name": "form-dialog-example", "description": "Form Dialog", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { ChangeDetectionStrategy, ChangeDetectorRef, Component, TemplateRef } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-form-dialog-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './form-dialog-example.component.html',\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n CheckboxComponent,\n FormsModule,\n ButtonComponent,\n DialogHeaderComponent,\n DialogBodyComponent,\n DialogFooterComponent,\n DialogComponent\n ]\n})\nexport class FormDialogExampleComponent {\n confirmationReason: string;\n responsivePadding = false;\n verticalPadding = false;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openDialog(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: this.responsivePadding,\n focusTrapped: true,\n verticalPadding: this.verticalPadding,\n ariaLabelledBy: 'fd-dialog-header-form'\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.confirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.confirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", "html": "\n \n \n

    The History of Pineapple

    \n
    \n\n \n \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n \n
    \n\n \n \n\n \n \n
    \n
    \n\n\n\n\n\n

    {{ confirmationReason }}

    \n" }, - { - "name": "dialog-full-screen-example", - "description": "Dialog Full Screen", - "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\nimport { AsyncPipe, NgStyle } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n TemplateRef,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogDefaultContent,\n DialogFooterComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-full-screen-inner-example',\n template: ` \n \n

    {{ dialogRef.data.title }}

    \n \n
    \n \n \n {{ dialogRef.data.pinnapleDescription }}\n

    \n
      \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
    • \n {{ fact }}\n
    • \n }\n
    \n
    \n \n \n \n \n \n \n
    `,\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n AsyncPipe,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogFullScreenInnerExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n\n@Component({\n selector: 'fd-dialog-full-screen-example',\n imports: [\n ButtonComponent,\n BarModule,\n InputGroupModule,\n InitialFocusDirective,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n TitleComponent,\n DialogHeaderComponent,\n DialogComponent\n ],\n templateUrl: './dialog-full-screen-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DialogFullScreenExampleComponent {\n @ViewChild('dialogContent', { read: TemplateRef })\n dialogContent: TemplateRef;\n\n @ViewChild('dialogSubHeader', { read: TemplateRef })\n dialogSubHeader: TemplateRef;\n\n closeReason = '';\n\n templateBasedConfirmationReason = '';\n\n componentCloseReason = '';\n\n private _dialogReference: DialogRef;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openFromComponent(): void {\n const dialogRef = this._dialogService.open(DialogFullScreenInnerExampleComponent, {\n data: {\n title: `Pineapple Fun Facts`,\n pinnapleDescription: `\n The pineapple (Ananas comosus) is a tropical plant with an edible fruit\n and the most economically significant plant in the family Bromeliaceae.\n The pineapple is indigenous to South America,\n where it has been cultivated for many centuries.\n The introduction of the pineapple to Europe in the 17th\n century made it a significant cultural icon of luxury.\n Since the 1820s, pineapple has been commercially grown in\n greenhouses and many tropical plantations.\n `,\n pineappleFunFacts: [\n `You can grow your own pineapple by planting the top of the pineapple in soil`,\n `Pulling leaves from a pineapple is not an indication of ripeness as many people think`,\n `James Dole is considered the “King of Pineapples“`,\n `A pineapple cannot continue to ripen after it has been picked`,\n `An unripe pineapple not only tastes awful, but can also be poisonous`,\n `One of the ways you can tell if a pineapple is ripe is by smelling it`,\n `In Hawaii, the word for pineapple is “Hala kahiki“`\n ]\n },\n width: '400px',\n ariaLabelledBy: 'fd-dialog-header-fs-component',\n ariaDescribedBy: 'fd-dialog-body-fs-component',\n responsivePadding: true,\n draggable: true,\n resizable: true,\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.componentCloseReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.componentCloseReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialogFromTemplate(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: true,\n draggable: true,\n resizable: true,\n ariaLabelledBy: 'fd-dialog-header-fs-template',\n ariaDescribedBy: 'fd-dialog-body-fs-template',\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.templateBasedConfirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.templateBasedConfirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialog(): void {\n const object: DialogDefaultContent = {\n title: 'Dialog Title',\n titleId: 'fd-dialog-header-fs-object',\n content: this.dialogContent,\n contentId: 'fd-dialog-body-fs-object',\n subHeader: this.dialogSubHeader,\n approveButton: 'Ok',\n approveButtonAriaLabel: 'Ok Emphasized',\n approveButtonCallback: () => this._dialogReference.close('Approved'),\n cancelButton: 'Cancel',\n cancelButtonCallback: () => this._dialogReference.close('Canceled'),\n closeButtonCallback: () => this._dialogReference.dismiss('Dismissed'),\n fullScreenButtonCallback: () => this._dialogReference.toggleFullScreen(),\n closeButtonTitle: 'close',\n allowFullScreen: true,\n fullScreenExpandButtonText: 'Enter full-screen mode',\n fullScreenMinifyButtonText: 'Exit full-screen mode'\n };\n\n this._dialogReference = this._dialogService.open(object, {\n ariaLabelledBy: 'fd-dialog-header-fs-object',\n ariaDescribedBy: 'fd-dialog-body-fs-object',\n focusTrapped: true,\n resizable: true,\n draggable: true\n });\n\n this._dialogReference.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", - "html": "\n\n\n\n
    You can also create dialog without building whole template.
    \n
    \n\n\n
    \n \n \n \n
    \n
    \n\n

    {{ closeReason }}

    \n\n\n\n\n \n \n

    The History of Pineapple

    \n \n
    \n\n \n

    Are you interested in The Great History of Pineapple?

    \n
    \n\n \n \n\n \n \n
    \n
    \n\n\n

    {{ templateBasedConfirmationReason }}

    \n\n\n\n\n

    {{ componentCloseReason }}

    \n\n" - }, { "name": "dialog-mobile-example", "description": "Dialog Mobile", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { ContentDensityMode } from '@fundamental-ngx/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-mobile-example',\n templateUrl: './dialog-mobile-example.component.html',\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogMobileExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDialog(dialogTemplate): void {\n this._dialogService.open(dialogTemplate, {\n mobile: true,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-mobile',\n ariaDescribedBy: 'fd-dialog-body-mobile',\n contentDensity: ContentDensityMode.COZY\n });\n }\n}\n", "html": "\n \n \n

    Wild pineapples

    \n
    \n\n \n
    \n Certain bat-pollinated wild pineapples, members of the Bromeliad family, do the exact opposite of most\n flowers by opening their flowers at night and closing them during the day.\n
    \n
    \n\n \n \n \n \n
    \n
    \n\n\n" }, + { + "name": "dialog-full-screen-example", + "description": "Dialog Full Screen", + "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\nimport { AsyncPipe, NgStyle } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n TemplateRef,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogDefaultContent,\n DialogFooterComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-full-screen-inner-example',\n template: ` \n \n

    {{ dialogRef.data.title }}

    \n \n
    \n \n \n {{ dialogRef.data.pinnapleDescription }}\n

    \n
      \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
    • \n {{ fact }}\n
    • \n }\n
    \n
    \n \n \n \n \n \n \n
    `,\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n AsyncPipe,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogFullScreenInnerExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n\n@Component({\n selector: 'fd-dialog-full-screen-example',\n imports: [\n ButtonComponent,\n BarModule,\n InputGroupModule,\n InitialFocusDirective,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n TitleComponent,\n DialogHeaderComponent,\n DialogComponent\n ],\n templateUrl: './dialog-full-screen-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DialogFullScreenExampleComponent {\n @ViewChild('dialogContent', { read: TemplateRef })\n dialogContent: TemplateRef;\n\n @ViewChild('dialogSubHeader', { read: TemplateRef })\n dialogSubHeader: TemplateRef;\n\n closeReason = '';\n\n templateBasedConfirmationReason = '';\n\n componentCloseReason = '';\n\n private _dialogReference: DialogRef;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openFromComponent(): void {\n const dialogRef = this._dialogService.open(DialogFullScreenInnerExampleComponent, {\n data: {\n title: `Pineapple Fun Facts`,\n pinnapleDescription: `\n The pineapple (Ananas comosus) is a tropical plant with an edible fruit\n and the most economically significant plant in the family Bromeliaceae.\n The pineapple is indigenous to South America,\n where it has been cultivated for many centuries.\n The introduction of the pineapple to Europe in the 17th\n century made it a significant cultural icon of luxury.\n Since the 1820s, pineapple has been commercially grown in\n greenhouses and many tropical plantations.\n `,\n pineappleFunFacts: [\n `You can grow your own pineapple by planting the top of the pineapple in soil`,\n `Pulling leaves from a pineapple is not an indication of ripeness as many people think`,\n `James Dole is considered the “King of Pineapples“`,\n `A pineapple cannot continue to ripen after it has been picked`,\n `An unripe pineapple not only tastes awful, but can also be poisonous`,\n `One of the ways you can tell if a pineapple is ripe is by smelling it`,\n `In Hawaii, the word for pineapple is “Hala kahiki“`\n ]\n },\n width: '400px',\n ariaLabelledBy: 'fd-dialog-header-fs-component',\n ariaDescribedBy: 'fd-dialog-body-fs-component',\n responsivePadding: true,\n draggable: true,\n resizable: true,\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.componentCloseReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.componentCloseReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialogFromTemplate(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: true,\n draggable: true,\n resizable: true,\n ariaLabelledBy: 'fd-dialog-header-fs-template',\n ariaDescribedBy: 'fd-dialog-body-fs-template',\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.templateBasedConfirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.templateBasedConfirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialog(): void {\n const object: DialogDefaultContent = {\n title: 'Dialog Title',\n titleId: 'fd-dialog-header-fs-object',\n content: this.dialogContent,\n contentId: 'fd-dialog-body-fs-object',\n subHeader: this.dialogSubHeader,\n approveButton: 'Ok',\n approveButtonAriaLabel: 'Ok Emphasized',\n approveButtonCallback: () => this._dialogReference.close('Approved'),\n cancelButton: 'Cancel',\n cancelButtonCallback: () => this._dialogReference.close('Canceled'),\n closeButtonCallback: () => this._dialogReference.dismiss('Dismissed'),\n fullScreenButtonCallback: () => this._dialogReference.toggleFullScreen(),\n closeButtonTitle: 'close',\n allowFullScreen: true,\n fullScreenExpandButtonText: 'Enter full-screen mode',\n fullScreenMinifyButtonText: 'Exit full-screen mode'\n };\n\n this._dialogReference = this._dialogService.open(object, {\n ariaLabelledBy: 'fd-dialog-header-fs-object',\n ariaDescribedBy: 'fd-dialog-body-fs-object',\n focusTrapped: true,\n resizable: true,\n draggable: true\n });\n\n this._dialogReference.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", + "html": "\n\n\n\n
    You can also create dialog without building whole template.
    \n
    \n\n\n
    \n \n \n \n
    \n
    \n\n

    {{ closeReason }}

    \n\n\n\n\n \n \n

    The History of Pineapple

    \n \n
    \n\n \n

    Are you interested in The Great History of Pineapple?

    \n
    \n\n \n \n\n \n \n
    \n
    \n\n\n

    {{ templateBasedConfirmationReason }}

    \n\n\n\n\n

    {{ componentCloseReason }}

    \n\n" + }, { "name": "dialog-object-example", "description": "Dialog Object", @@ -10949,6 +10949,12 @@ "typescript": "import { Component } from '@angular/core';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\n\nimport { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { FlexibleColumnLayout, FlexibleColumnLayoutModule } from '@fundamental-ngx/core/flexible-column-layout';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\n@Component({\n selector: 'fd-dynamic-page-column-layout-example',\n templateUrl: './dynamic-page-column-layout-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n FlexibleColumnLayoutModule,\n DynamicPageModule,\n BreadcrumbModule,\n LinkComponent,\n ContentDensityDirective,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n FDP_ICON_TAB_BAR,\n MessageToastModule\n ]\n})\nexport class DynamicPageColumnLayoutExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n /**\n * documentation related property\n * sets the initial layout of the component to 'OneColumnStartFullScreen'\n * sets a new layout for the component\n */\n localLayout: FlexibleColumnLayout = 'OneColumnStartFullScreen';\n\n separatorAriaLabel = 'separator';\n\n expandTitle = 'Expand';\n\n collapseTitle = 'Collapse';\n\n constructor(private _messageToastService: MessageToastService) {}\n\n /**\n * this function is reacting to events (button clicks) and\n * updates the local property which sets a new layout for the component.\n * Available values for the layouts include:\n * 'OneColumnStartFullScreen' | 'OneColumnMidFullScreen' | 'OneColumnEndFullScreen' |\n * 'TwoColumnsStartExpanded' | 'TwoColumnsMidExpanded' | 'TwoColumnsEndExpanded' |\n * 'ThreeColumnsMidExpanded' | 'ThreeColumnsEndExpanded' | 'ThreeColumnsStartMinimized' |\n * 'ThreeColumnsEndMinimized';\n */\n changeLayout(newValue: FlexibleColumnLayout): void {\n this.localLayout = newValue;\n }\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum\n consequuntur impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n \n

    Mid Column

    \n
    \n \n Open Column 3\n \n
    \n \n @for (tab of [1, 2, 3, 4]; track tab) {\n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor\n incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud\n exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure\n dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt\n mollit anim id est laborum.\n
    \n
    \n }\n
    \n
    \n \n

    End Column

    \n
    \n @if (localLayout !== 'OneColumnEndFullScreen') {\n \n \n } @else {\n \n }\n
    \n
    \n \n \n}\n" }, + { + "name": "dynamic-page-responsive-example", + "description": "Dynamic Page Responsive", + "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-responsive-example',\n templateUrl: './dynamic-page-responsive-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n BreadcrumbModule,\n ContentDensityDirective,\n LinkComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n MessageToastModule\n ]\n})\nexport class DynamicPageResponsiveExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n compact = true;\n\n constructor(private _messageToastService: MessageToastService) {}\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", + "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum consequuntur\n impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n}\n" + }, { "name": "dynamic-page-dynamic-container-height-example", "description": "Dynamic Page Dynamic Container Height", @@ -10961,12 +10967,6 @@ "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n DynamicPageHeaderSubtitleDirective,\n DynamicPageHeaderTitleDirective,\n DynamicPageModule\n} from '@fundamental-ngx/core/dynamic-page';\nimport { FacetModule } from '@fundamental-ngx/core/facets';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ObjectNumberComponent } from '@fundamental-ngx/core/object-number';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { RatingIndicatorComponent } from '@fundamental-ngx/core/rating-indicator';\nimport { TextComponent } from '@fundamental-ngx/core/text';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-facets-example',\n templateUrl: './dynamic-page-facets-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n .red-subtitle {\n color: red;\n }\n .blue-subtitle {\n color: blue;\n }\n .green-subtitle {\n color: green;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n DynamicPageHeaderTitleDirective,\n DynamicPageHeaderSubtitleDirective,\n BreadcrumbModule,\n LinkComponent,\n FacetModule,\n AvatarComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ContentDensityDirective,\n ToolbarSeparatorComponent,\n FormLabelComponent,\n TextComponent,\n RatingIndicatorComponent,\n ObjectStatusComponent,\n ObjectNumberComponent,\n CdkScrollable,\n BarModule\n ]\n})\nexport class DynamicPageFacetsExampleComponent {\n visible = false;\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n }\n\n closePage(): void {\n this.visible = false;\n }\n}\n", "html": "\n@if (visible) {\n
    \n \n \n \n Lorem ipsum dolor sit amet, consectetur adipiscing elit ({{\n collapsed ? 'collapsed' : 'not collapsed'\n }})\n \n \n Different parts | of the |\n subtitle | with\n {{ collapsed ? 'collapsed' : 'not collapsed' }} header\n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n}\n" }, - { - "name": "dynamic-page-responsive-example", - "description": "Dynamic Page Responsive", - "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-responsive-example',\n templateUrl: './dynamic-page-responsive-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n BreadcrumbModule,\n ContentDensityDirective,\n LinkComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n MessageToastModule\n ]\n})\nexport class DynamicPageResponsiveExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n compact = true;\n\n constructor(private _messageToastService: MessageToastService) {}\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", - "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum consequuntur\n impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n}\n" - }, { "name": "dynamic-page-routing-example", "description": "Dynamic Page Routing", @@ -11013,6 +11013,12 @@ "typescript": "import { Component } from '@angular/core';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\n\nimport { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { FlexibleColumnLayout, FlexibleColumnLayoutModule } from '@fundamental-ngx/core/flexible-column-layout';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\n@Component({\n selector: 'fd-dynamic-page-column-layout-example',\n templateUrl: './dynamic-page-column-layout-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n FlexibleColumnLayoutModule,\n DynamicPageModule,\n BreadcrumbModule,\n LinkComponent,\n ContentDensityDirective,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n FDP_ICON_TAB_BAR,\n MessageToastModule\n ]\n})\nexport class DynamicPageColumnLayoutExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n /**\n * documentation related property\n * sets the initial layout of the component to 'OneColumnStartFullScreen'\n * sets a new layout for the component\n */\n localLayout: FlexibleColumnLayout = 'OneColumnStartFullScreen';\n\n separatorAriaLabel = 'separator';\n\n expandTitle = 'Expand';\n\n collapseTitle = 'Collapse';\n\n constructor(private _messageToastService: MessageToastService) {}\n\n /**\n * this function is reacting to events (button clicks) and\n * updates the local property which sets a new layout for the component.\n * Available values for the layouts include:\n * 'OneColumnStartFullScreen' | 'OneColumnMidFullScreen' | 'OneColumnEndFullScreen' |\n * 'TwoColumnsStartExpanded' | 'TwoColumnsMidExpanded' | 'TwoColumnsEndExpanded' |\n * 'ThreeColumnsMidExpanded' | 'ThreeColumnsEndExpanded' | 'ThreeColumnsStartMinimized' |\n * 'ThreeColumnsEndMinimized';\n */\n changeLayout(newValue: FlexibleColumnLayout): void {\n this.localLayout = newValue;\n }\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum\n consequuntur impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n \n

    Mid Column

    \n
    \n \n Open Column 3\n \n
    \n \n @for (tab of [1, 2, 3, 4]; track tab) {\n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor\n incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud\n exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure\n dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt\n mollit anim id est laborum.\n
    \n
    \n }\n
    \n
    \n \n

    End Column

    \n
    \n @if (localLayout !== 'OneColumnEndFullScreen') {\n \n \n } @else {\n \n }\n
    \n
    \n \n \n}\n" }, + { + "name": "dynamic-page-responsive-example", + "description": "Dynamic Page Responsive", + "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-responsive-example',\n templateUrl: './dynamic-page-responsive-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n BreadcrumbModule,\n ContentDensityDirective,\n LinkComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n MessageToastModule\n ]\n})\nexport class DynamicPageResponsiveExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n compact = true;\n\n constructor(private _messageToastService: MessageToastService) {}\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", + "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum consequuntur\n impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n}\n" + }, { "name": "dynamic-page-dynamic-container-height-example", "description": "Dynamic Page Dynamic Container Height", @@ -11025,12 +11031,6 @@ "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n DynamicPageHeaderSubtitleDirective,\n DynamicPageHeaderTitleDirective,\n DynamicPageModule\n} from '@fundamental-ngx/core/dynamic-page';\nimport { FacetModule } from '@fundamental-ngx/core/facets';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ObjectNumberComponent } from '@fundamental-ngx/core/object-number';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { RatingIndicatorComponent } from '@fundamental-ngx/core/rating-indicator';\nimport { TextComponent } from '@fundamental-ngx/core/text';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-facets-example',\n templateUrl: './dynamic-page-facets-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n .red-subtitle {\n color: red;\n }\n .blue-subtitle {\n color: blue;\n }\n .green-subtitle {\n color: green;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n DynamicPageHeaderTitleDirective,\n DynamicPageHeaderSubtitleDirective,\n BreadcrumbModule,\n LinkComponent,\n FacetModule,\n AvatarComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ContentDensityDirective,\n ToolbarSeparatorComponent,\n FormLabelComponent,\n TextComponent,\n RatingIndicatorComponent,\n ObjectStatusComponent,\n ObjectNumberComponent,\n CdkScrollable,\n BarModule\n ]\n})\nexport class DynamicPageFacetsExampleComponent {\n visible = false;\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n }\n\n closePage(): void {\n this.visible = false;\n }\n}\n", "html": "\n@if (visible) {\n
    \n \n \n \n Lorem ipsum dolor sit amet, consectetur adipiscing elit ({{\n collapsed ? 'collapsed' : 'not collapsed'\n }})\n \n \n Different parts | of the |\n subtitle | with\n {{ collapsed ? 'collapsed' : 'not collapsed' }} header\n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n}\n" }, - { - "name": "dynamic-page-responsive-example", - "description": "Dynamic Page Responsive", - "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-responsive-example',\n templateUrl: './dynamic-page-responsive-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n BreadcrumbModule,\n ContentDensityDirective,\n LinkComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n MessageToastModule\n ]\n})\nexport class DynamicPageResponsiveExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n compact = true;\n\n constructor(private _messageToastService: MessageToastService) {}\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", - "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum consequuntur\n impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n}\n" - }, { "name": "dynamic-page-routing-example", "description": "Dynamic Page Routing", @@ -11077,6 +11077,12 @@ "typescript": "import { Component } from '@angular/core';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\n\nimport { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { FlexibleColumnLayout, FlexibleColumnLayoutModule } from '@fundamental-ngx/core/flexible-column-layout';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\n@Component({\n selector: 'fd-dynamic-page-column-layout-example',\n templateUrl: './dynamic-page-column-layout-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n FlexibleColumnLayoutModule,\n DynamicPageModule,\n BreadcrumbModule,\n LinkComponent,\n ContentDensityDirective,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n FDP_ICON_TAB_BAR,\n MessageToastModule\n ]\n})\nexport class DynamicPageColumnLayoutExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n /**\n * documentation related property\n * sets the initial layout of the component to 'OneColumnStartFullScreen'\n * sets a new layout for the component\n */\n localLayout: FlexibleColumnLayout = 'OneColumnStartFullScreen';\n\n separatorAriaLabel = 'separator';\n\n expandTitle = 'Expand';\n\n collapseTitle = 'Collapse';\n\n constructor(private _messageToastService: MessageToastService) {}\n\n /**\n * this function is reacting to events (button clicks) and\n * updates the local property which sets a new layout for the component.\n * Available values for the layouts include:\n * 'OneColumnStartFullScreen' | 'OneColumnMidFullScreen' | 'OneColumnEndFullScreen' |\n * 'TwoColumnsStartExpanded' | 'TwoColumnsMidExpanded' | 'TwoColumnsEndExpanded' |\n * 'ThreeColumnsMidExpanded' | 'ThreeColumnsEndExpanded' | 'ThreeColumnsStartMinimized' |\n * 'ThreeColumnsEndMinimized';\n */\n changeLayout(newValue: FlexibleColumnLayout): void {\n this.localLayout = newValue;\n }\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum\n consequuntur impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n \n

    Mid Column

    \n
    \n \n Open Column 3\n \n
    \n \n @for (tab of [1, 2, 3, 4]; track tab) {\n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor\n incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud\n exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure\n dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt\n mollit anim id est laborum.\n
    \n
    \n }\n
    \n
    \n \n

    End Column

    \n
    \n @if (localLayout !== 'OneColumnEndFullScreen') {\n \n \n } @else {\n \n }\n
    \n
    \n \n \n}\n" }, + { + "name": "dynamic-page-responsive-example", + "description": "Dynamic Page Responsive", + "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-responsive-example',\n templateUrl: './dynamic-page-responsive-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n BreadcrumbModule,\n ContentDensityDirective,\n LinkComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n MessageToastModule\n ]\n})\nexport class DynamicPageResponsiveExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n compact = true;\n\n constructor(private _messageToastService: MessageToastService) {}\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", + "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum consequuntur\n impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n}\n" + }, { "name": "dynamic-page-dynamic-container-height-example", "description": "Dynamic Page Dynamic Container Height", @@ -11089,12 +11095,6 @@ "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n DynamicPageHeaderSubtitleDirective,\n DynamicPageHeaderTitleDirective,\n DynamicPageModule\n} from '@fundamental-ngx/core/dynamic-page';\nimport { FacetModule } from '@fundamental-ngx/core/facets';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ObjectNumberComponent } from '@fundamental-ngx/core/object-number';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { RatingIndicatorComponent } from '@fundamental-ngx/core/rating-indicator';\nimport { TextComponent } from '@fundamental-ngx/core/text';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-facets-example',\n templateUrl: './dynamic-page-facets-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n .red-subtitle {\n color: red;\n }\n .blue-subtitle {\n color: blue;\n }\n .green-subtitle {\n color: green;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n DynamicPageHeaderTitleDirective,\n DynamicPageHeaderSubtitleDirective,\n BreadcrumbModule,\n LinkComponent,\n FacetModule,\n AvatarComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ContentDensityDirective,\n ToolbarSeparatorComponent,\n FormLabelComponent,\n TextComponent,\n RatingIndicatorComponent,\n ObjectStatusComponent,\n ObjectNumberComponent,\n CdkScrollable,\n BarModule\n ]\n})\nexport class DynamicPageFacetsExampleComponent {\n visible = false;\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n }\n\n closePage(): void {\n this.visible = false;\n }\n}\n", "html": "\n@if (visible) {\n
    \n \n \n \n Lorem ipsum dolor sit amet, consectetur adipiscing elit ({{\n collapsed ? 'collapsed' : 'not collapsed'\n }})\n \n \n Different parts | of the |\n subtitle | with\n {{ collapsed ? 'collapsed' : 'not collapsed' }} header\n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n}\n" }, - { - "name": "dynamic-page-responsive-example", - "description": "Dynamic Page Responsive", - "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-responsive-example',\n templateUrl: './dynamic-page-responsive-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n BreadcrumbModule,\n ContentDensityDirective,\n LinkComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n MessageToastModule\n ]\n})\nexport class DynamicPageResponsiveExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n compact = true;\n\n constructor(private _messageToastService: MessageToastService) {}\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", - "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum consequuntur\n impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n}\n" - }, { "name": "dynamic-page-routing-example", "description": "Dynamic Page Routing", @@ -11149,10 +11149,10 @@ "html": "\n \n\n \n\n \n\n" }, { - "name": "feed-input-grow-example", - "description": "Feed Input Grow", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { FeedInputModule } from '@fundamental-ngx/core/feed-input';\nimport { FormControlComponent } from '@fundamental-ngx/core/form';\n\n@Component({\n selector: 'fd-feed-input-grow-example',\n templateUrl: './feed-input-grow-example.component.html',\n imports: [FeedInputModule, AvatarComponent, FormControlComponent]\n})\nexport class FeedInputGrowExampleComponent {}\n", - "html": "\n \n\n \n\n \n\n" + "name": "feed-input-placeholder-example", + "description": "Feed Input Placeholder", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { FeedInputModule } from '@fundamental-ngx/core/feed-input';\nimport { FormControlComponent } from '@fundamental-ngx/core/form';\n\n@Component({\n selector: 'fd-feed-input-placeholder-example',\n templateUrl: './feed-input-placeholder-example.component.html',\n imports: [FeedInputModule, AvatarComponent, FormControlComponent]\n})\nexport class FeedInputPlaceholderExampleComponent {}\n", + "html": "\n \n\n \n\n \n\n" }, { "name": "feed-input-no-avatar-example", @@ -11161,10 +11161,10 @@ "html": "\n \n\n \n\n" }, { - "name": "feed-input-placeholder-example", - "description": "Feed Input Placeholder", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { FeedInputModule } from '@fundamental-ngx/core/feed-input';\nimport { FormControlComponent } from '@fundamental-ngx/core/form';\n\n@Component({\n selector: 'fd-feed-input-placeholder-example',\n templateUrl: './feed-input-placeholder-example.component.html',\n imports: [FeedInputModule, AvatarComponent, FormControlComponent]\n})\nexport class FeedInputPlaceholderExampleComponent {}\n", - "html": "\n \n\n \n\n \n\n" + "name": "feed-input-grow-example", + "description": "Feed Input Grow", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { FeedInputModule } from '@fundamental-ngx/core/feed-input';\nimport { FormControlComponent } from '@fundamental-ngx/core/form';\n\n@Component({\n selector: 'fd-feed-input-grow-example',\n templateUrl: './feed-input-grow-example.component.html',\n imports: [FeedInputModule, AvatarComponent, FormControlComponent]\n})\nexport class FeedInputGrowExampleComponent {}\n", + "html": "\n \n\n \n\n \n\n" } ] }, @@ -11201,10 +11201,10 @@ "html": "\n \n\n \n\n \n\n" }, { - "name": "feed-input-grow-example", - "description": "Feed Input Grow", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { FeedInputModule } from '@fundamental-ngx/core/feed-input';\nimport { FormControlComponent } from '@fundamental-ngx/core/form';\n\n@Component({\n selector: 'fd-feed-input-grow-example',\n templateUrl: './feed-input-grow-example.component.html',\n imports: [FeedInputModule, AvatarComponent, FormControlComponent]\n})\nexport class FeedInputGrowExampleComponent {}\n", - "html": "\n \n\n \n\n \n\n" + "name": "feed-input-placeholder-example", + "description": "Feed Input Placeholder", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { FeedInputModule } from '@fundamental-ngx/core/feed-input';\nimport { FormControlComponent } from '@fundamental-ngx/core/form';\n\n@Component({\n selector: 'fd-feed-input-placeholder-example',\n templateUrl: './feed-input-placeholder-example.component.html',\n imports: [FeedInputModule, AvatarComponent, FormControlComponent]\n})\nexport class FeedInputPlaceholderExampleComponent {}\n", + "html": "\n \n\n \n\n \n\n" }, { "name": "feed-input-no-avatar-example", @@ -11213,10 +11213,10 @@ "html": "\n \n\n \n\n" }, { - "name": "feed-input-placeholder-example", - "description": "Feed Input Placeholder", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { FeedInputModule } from '@fundamental-ngx/core/feed-input';\nimport { FormControlComponent } from '@fundamental-ngx/core/form';\n\n@Component({\n selector: 'fd-feed-input-placeholder-example',\n templateUrl: './feed-input-placeholder-example.component.html',\n imports: [FeedInputModule, AvatarComponent, FormControlComponent]\n})\nexport class FeedInputPlaceholderExampleComponent {}\n", - "html": "\n \n\n \n\n \n\n" + "name": "feed-input-grow-example", + "description": "Feed Input Grow", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { FeedInputModule } from '@fundamental-ngx/core/feed-input';\nimport { FormControlComponent } from '@fundamental-ngx/core/form';\n\n@Component({\n selector: 'fd-feed-input-grow-example',\n templateUrl: './feed-input-grow-example.component.html',\n imports: [FeedInputModule, AvatarComponent, FormControlComponent]\n})\nexport class FeedInputGrowExampleComponent {}\n", + "html": "\n \n\n \n\n \n\n" } ] }, @@ -14479,18 +14479,6 @@ "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-byline-button-example',\n templateUrl: './list-byline-button-example.component.html',\n imports: [ListModule, IconComponent, ButtonComponent]\n})\nexport class ListBylineButtonExampleComponent {}\n", "html": "
      \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n \n \n
    • \n
    • \n \n
      \n
      Byline list with counter
      \n
      Byline Text
      \n
      \n
    • \n
    \n" }, - { - "name": "list-byline-interactive-example", - "description": "List Byline Interactive", - "typescript": "import { Component } from '@angular/core';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-byline-interactive-example',\n templateUrl: './list-byline-interactive-example.component.html',\n imports: [ListModule, IconComponent]\n})\nexport class ListBylineInteractiveExampleComponent {}\n", - "html": "
      \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n
    • \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n
    • \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n
    • \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n
    • \n
    \n" - }, - { - "name": "list-byline-loading-example", - "description": "List Byline Loading", - "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { SkeletonComponent } from '@fundamental-ngx/core/skeleton';\n\n@Component({\n selector: 'fd-list-byline-loading-example',\n templateUrl: './list-byline-loading-example.component.html',\n imports: [ButtonComponent, ListModule, IconComponent, SkeletonComponent]\n})\nexport class ListBylineLoadingExampleComponent {\n loading = true;\n}\n", - "html": "\n
      \n @if (!loading) {\n @for (_ of [0, 1, 2]; track $index) {\n
    • \n \n
      \n
      \n Long Title - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ut laoreet lorem.\n Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Aenean\n sagittis aliquam justo et suscipit. Nam molestie, magna at elementum pulvinar, nisi enim\n venenatis ante, id convallis mi neque nec risus.\n
      \n
      \n Long byline text - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ut laoreet\n lorem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae;\n Aenean sagittis aliquam justo et suscipit. Nam molestie, magna at elementum pulvinar, nisi enim\n venenatis ante, id convallis mi neque nec risus.\n
      \n
      \n
    • \n }\n } @else {\n @for (_ of [0, 1, 2]; track $index) {\n
    • \n \n \n \n \n \n
    • \n }\n }\n
    \n" - }, { "name": "list-byline-navigation-example", "description": "List Byline Navigation", @@ -14503,6 +14491,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { RadioModule } from '@fundamental-ngx/core/radio';\n\n@Component({\n selector: 'fd-list-byline-selection-example',\n templateUrl: './list-byline-selection-example.component.html',\n imports: [ListModule, CheckboxComponent, FormsModule, IconComponent, RadioModule]\n})\nexport class ListBylineSelectionExampleComponent {\n selectionValue: string | null = null;\n selectionValueTwo: string | null = null;\n\n bylineSelectionItems = [\n {\n selected: true,\n title: 'List item 1',\n byline: 'Byline text for item 1',\n glyph: 'calendar'\n },\n {\n selected: false,\n title: 'List item 2',\n byline: 'Byline text for item 2',\n glyph: 'activate'\n },\n {\n selected: false,\n title: 'List item 3',\n byline: 'Byline text for item 3',\n glyph: 'employee'\n }\n ];\n}\n", "html": "

    With Checkboxes

    \n
      \n @for (item of bylineSelectionItems; track item) {\n
    • \n \n \n
      \n
      {{ item.title }}
      \n
      {{ item.byline }}
      \n
      \n
    • \n }\n
    \n

    With Radio Buttons

    \n
      \n
    • \n \n \n
      \n
      Title 1
      \n
      Byline 1
      \n
      \n
    • \n
    • \n \n \n
      \n
      Title 2
      \n
      Byline 2
      \n
      \n
    • \n
    • \n \n \n
      \n
      Title 3
      \n
      Byline 3
      \n
      \n
    • \n
    \n" }, + { + "name": "list-byline-loading-example", + "description": "List Byline Loading", + "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { SkeletonComponent } from '@fundamental-ngx/core/skeleton';\n\n@Component({\n selector: 'fd-list-byline-loading-example',\n templateUrl: './list-byline-loading-example.component.html',\n imports: [ButtonComponent, ListModule, IconComponent, SkeletonComponent]\n})\nexport class ListBylineLoadingExampleComponent {\n loading = true;\n}\n", + "html": "\n
      \n @if (!loading) {\n @for (_ of [0, 1, 2]; track $index) {\n
    • \n \n
      \n
      \n Long Title - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ut laoreet lorem.\n Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Aenean\n sagittis aliquam justo et suscipit. Nam molestie, magna at elementum pulvinar, nisi enim\n venenatis ante, id convallis mi neque nec risus.\n
      \n
      \n Long byline text - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ut laoreet\n lorem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae;\n Aenean sagittis aliquam justo et suscipit. Nam molestie, magna at elementum pulvinar, nisi enim\n venenatis ante, id convallis mi neque nec risus.\n
      \n
      \n
    • \n }\n } @else {\n @for (_ of [0, 1, 2]; track $index) {\n
    • \n \n \n \n \n \n
    • \n }\n }\n
    \n" + }, + { + "name": "list-byline-interactive-example", + "description": "List Byline Interactive", + "typescript": "import { Component } from '@angular/core';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-byline-interactive-example',\n templateUrl: './list-byline-interactive-example.component.html',\n imports: [ListModule, IconComponent]\n})\nexport class ListBylineInteractiveExampleComponent {}\n", + "html": "
      \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n
    • \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n
    • \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n
    • \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n
    • \n
    \n" + }, { "name": "list-byline-standard-example", "description": "List Byline Standard", @@ -14556,18 +14556,6 @@ "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-byline-button-example',\n templateUrl: './list-byline-button-example.component.html',\n imports: [ListModule, IconComponent, ButtonComponent]\n})\nexport class ListBylineButtonExampleComponent {}\n", "html": "
      \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n \n \n
    • \n
    • \n \n
      \n
      Byline list with counter
      \n
      Byline Text
      \n
      \n
    • \n
    \n" }, - { - "name": "list-byline-interactive-example", - "description": "List Byline Interactive", - "typescript": "import { Component } from '@angular/core';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-byline-interactive-example',\n templateUrl: './list-byline-interactive-example.component.html',\n imports: [ListModule, IconComponent]\n})\nexport class ListBylineInteractiveExampleComponent {}\n", - "html": "
      \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n
    • \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n
    • \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n
    • \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n
    • \n
    \n" - }, - { - "name": "list-byline-loading-example", - "description": "List Byline Loading", - "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { SkeletonComponent } from '@fundamental-ngx/core/skeleton';\n\n@Component({\n selector: 'fd-list-byline-loading-example',\n templateUrl: './list-byline-loading-example.component.html',\n imports: [ButtonComponent, ListModule, IconComponent, SkeletonComponent]\n})\nexport class ListBylineLoadingExampleComponent {\n loading = true;\n}\n", - "html": "\n
      \n @if (!loading) {\n @for (_ of [0, 1, 2]; track $index) {\n
    • \n \n
      \n
      \n Long Title - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ut laoreet lorem.\n Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Aenean\n sagittis aliquam justo et suscipit. Nam molestie, magna at elementum pulvinar, nisi enim\n venenatis ante, id convallis mi neque nec risus.\n
      \n
      \n Long byline text - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ut laoreet\n lorem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae;\n Aenean sagittis aliquam justo et suscipit. Nam molestie, magna at elementum pulvinar, nisi enim\n venenatis ante, id convallis mi neque nec risus.\n
      \n
      \n
    • \n }\n } @else {\n @for (_ of [0, 1, 2]; track $index) {\n
    • \n \n \n \n \n \n
    • \n }\n }\n
    \n" - }, { "name": "list-byline-navigation-example", "description": "List Byline Navigation", @@ -14580,6 +14568,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { RadioModule } from '@fundamental-ngx/core/radio';\n\n@Component({\n selector: 'fd-list-byline-selection-example',\n templateUrl: './list-byline-selection-example.component.html',\n imports: [ListModule, CheckboxComponent, FormsModule, IconComponent, RadioModule]\n})\nexport class ListBylineSelectionExampleComponent {\n selectionValue: string | null = null;\n selectionValueTwo: string | null = null;\n\n bylineSelectionItems = [\n {\n selected: true,\n title: 'List item 1',\n byline: 'Byline text for item 1',\n glyph: 'calendar'\n },\n {\n selected: false,\n title: 'List item 2',\n byline: 'Byline text for item 2',\n glyph: 'activate'\n },\n {\n selected: false,\n title: 'List item 3',\n byline: 'Byline text for item 3',\n glyph: 'employee'\n }\n ];\n}\n", "html": "

    With Checkboxes

    \n
      \n @for (item of bylineSelectionItems; track item) {\n
    • \n \n \n
      \n
      {{ item.title }}
      \n
      {{ item.byline }}
      \n
      \n
    • \n }\n
    \n

    With Radio Buttons

    \n
      \n
    • \n \n \n
      \n
      Title 1
      \n
      Byline 1
      \n
      \n
    • \n
    • \n \n \n
      \n
      Title 2
      \n
      Byline 2
      \n
      \n
    • \n
    • \n \n \n
      \n
      Title 3
      \n
      Byline 3
      \n
      \n
    • \n
    \n" }, + { + "name": "list-byline-loading-example", + "description": "List Byline Loading", + "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { SkeletonComponent } from '@fundamental-ngx/core/skeleton';\n\n@Component({\n selector: 'fd-list-byline-loading-example',\n templateUrl: './list-byline-loading-example.component.html',\n imports: [ButtonComponent, ListModule, IconComponent, SkeletonComponent]\n})\nexport class ListBylineLoadingExampleComponent {\n loading = true;\n}\n", + "html": "\n
      \n @if (!loading) {\n @for (_ of [0, 1, 2]; track $index) {\n
    • \n \n
      \n
      \n Long Title - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ut laoreet lorem.\n Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Aenean\n sagittis aliquam justo et suscipit. Nam molestie, magna at elementum pulvinar, nisi enim\n venenatis ante, id convallis mi neque nec risus.\n
      \n
      \n Long byline text - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ut laoreet\n lorem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae;\n Aenean sagittis aliquam justo et suscipit. Nam molestie, magna at elementum pulvinar, nisi enim\n venenatis ante, id convallis mi neque nec risus.\n
      \n
      \n
    • \n }\n } @else {\n @for (_ of [0, 1, 2]; track $index) {\n
    • \n \n \n \n \n \n
    • \n }\n }\n
    \n" + }, + { + "name": "list-byline-interactive-example", + "description": "List Byline Interactive", + "typescript": "import { Component } from '@angular/core';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-byline-interactive-example',\n templateUrl: './list-byline-interactive-example.component.html',\n imports: [ListModule, IconComponent]\n})\nexport class ListBylineInteractiveExampleComponent {}\n", + "html": "
      \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n
    • \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n
    • \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n
    • \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n
    • \n
    \n" + }, { "name": "list-byline-standard-example", "description": "List Byline Standard", @@ -14639,18 +14639,6 @@ "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-byline-button-example',\n templateUrl: './list-byline-button-example.component.html',\n imports: [ListModule, IconComponent, ButtonComponent]\n})\nexport class ListBylineButtonExampleComponent {}\n", "html": "
      \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n \n \n
    • \n
    • \n \n
      \n
      Byline list with counter
      \n
      Byline Text
      \n
      \n
    • \n
    \n" }, - { - "name": "list-byline-interactive-example", - "description": "List Byline Interactive", - "typescript": "import { Component } from '@angular/core';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-byline-interactive-example',\n templateUrl: './list-byline-interactive-example.component.html',\n imports: [ListModule, IconComponent]\n})\nexport class ListBylineInteractiveExampleComponent {}\n", - "html": "
      \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n
    • \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n
    • \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n
    • \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n
    • \n
    \n" - }, - { - "name": "list-byline-loading-example", - "description": "List Byline Loading", - "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { SkeletonComponent } from '@fundamental-ngx/core/skeleton';\n\n@Component({\n selector: 'fd-list-byline-loading-example',\n templateUrl: './list-byline-loading-example.component.html',\n imports: [ButtonComponent, ListModule, IconComponent, SkeletonComponent]\n})\nexport class ListBylineLoadingExampleComponent {\n loading = true;\n}\n", - "html": "\n
      \n @if (!loading) {\n @for (_ of [0, 1, 2]; track $index) {\n
    • \n \n
      \n
      \n Long Title - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ut laoreet lorem.\n Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Aenean\n sagittis aliquam justo et suscipit. Nam molestie, magna at elementum pulvinar, nisi enim\n venenatis ante, id convallis mi neque nec risus.\n
      \n
      \n Long byline text - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ut laoreet\n lorem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae;\n Aenean sagittis aliquam justo et suscipit. Nam molestie, magna at elementum pulvinar, nisi enim\n venenatis ante, id convallis mi neque nec risus.\n
      \n
      \n
    • \n }\n } @else {\n @for (_ of [0, 1, 2]; track $index) {\n
    • \n \n \n \n \n \n
    • \n }\n }\n
    \n" - }, { "name": "list-byline-navigation-example", "description": "List Byline Navigation", @@ -14663,6 +14651,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { RadioModule } from '@fundamental-ngx/core/radio';\n\n@Component({\n selector: 'fd-list-byline-selection-example',\n templateUrl: './list-byline-selection-example.component.html',\n imports: [ListModule, CheckboxComponent, FormsModule, IconComponent, RadioModule]\n})\nexport class ListBylineSelectionExampleComponent {\n selectionValue: string | null = null;\n selectionValueTwo: string | null = null;\n\n bylineSelectionItems = [\n {\n selected: true,\n title: 'List item 1',\n byline: 'Byline text for item 1',\n glyph: 'calendar'\n },\n {\n selected: false,\n title: 'List item 2',\n byline: 'Byline text for item 2',\n glyph: 'activate'\n },\n {\n selected: false,\n title: 'List item 3',\n byline: 'Byline text for item 3',\n glyph: 'employee'\n }\n ];\n}\n", "html": "

    With Checkboxes

    \n
      \n @for (item of bylineSelectionItems; track item) {\n
    • \n \n \n
      \n
      {{ item.title }}
      \n
      {{ item.byline }}
      \n
      \n
    • \n }\n
    \n

    With Radio Buttons

    \n
      \n
    • \n \n \n
      \n
      Title 1
      \n
      Byline 1
      \n
      \n
    • \n
    • \n \n \n
      \n
      Title 2
      \n
      Byline 2
      \n
      \n
    • \n
    • \n \n \n
      \n
      Title 3
      \n
      Byline 3
      \n
      \n
    • \n
    \n" }, + { + "name": "list-byline-loading-example", + "description": "List Byline Loading", + "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { SkeletonComponent } from '@fundamental-ngx/core/skeleton';\n\n@Component({\n selector: 'fd-list-byline-loading-example',\n templateUrl: './list-byline-loading-example.component.html',\n imports: [ButtonComponent, ListModule, IconComponent, SkeletonComponent]\n})\nexport class ListBylineLoadingExampleComponent {\n loading = true;\n}\n", + "html": "\n
      \n @if (!loading) {\n @for (_ of [0, 1, 2]; track $index) {\n
    • \n \n
      \n
      \n Long Title - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ut laoreet lorem.\n Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Aenean\n sagittis aliquam justo et suscipit. Nam molestie, magna at elementum pulvinar, nisi enim\n venenatis ante, id convallis mi neque nec risus.\n
      \n
      \n Long byline text - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ut laoreet\n lorem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae;\n Aenean sagittis aliquam justo et suscipit. Nam molestie, magna at elementum pulvinar, nisi enim\n venenatis ante, id convallis mi neque nec risus.\n
      \n
      \n
    • \n }\n } @else {\n @for (_ of [0, 1, 2]; track $index) {\n
    • \n \n \n \n \n \n
    • \n }\n }\n
    \n" + }, + { + "name": "list-byline-interactive-example", + "description": "List Byline Interactive", + "typescript": "import { Component } from '@angular/core';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-byline-interactive-example',\n templateUrl: './list-byline-interactive-example.component.html',\n imports: [ListModule, IconComponent]\n})\nexport class ListBylineInteractiveExampleComponent {}\n", + "html": "
      \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n
    • \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n
    • \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n
    • \n
    • \n \n
      \n
      Title
      \n
      Byline Text
      \n
      \n
    • \n
    \n" + }, { "name": "list-byline-standard-example", "description": "List Byline Standard", @@ -14741,18 +14741,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-interactive-example',\n templateUrl: './list-interactive-example.component.html',\n imports: [ListModule]\n})\nexport class ListInteractiveExampleComponent {}\n", "html": "
      \n
    • \n Interactive list item 1 \n
    • \n
    • \n Interactive list item 2 \n
    • \n
    • \n Selected list item 3 \n
    • \n
    • \n Interactive Selected list item 4 \n
    • \n
    \n" }, - { - "name": "list-keyboard-example", - "description": "List Keyboard", - "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", - "html": "\n
      \n
    • \n List item 1 \n
    • \n
    • \n List item 2 \n
    • \n
    • \n List item 3 \n
    • \n
    • \n List item 4 \n
    • \n
    \n" - }, { "name": "list-loading-example", "description": "List Loading", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { SkeletonComponent } from '@fundamental-ngx/core/skeleton';\n\n@Component({\n selector: 'fd-list-loading-example',\n templateUrl: './list-loading-example.component.html',\n imports: [ButtonComponent, ListModule, SkeletonComponent]\n})\nexport class ListLoadingExampleComponent {\n loading = true;\n}\n", "html": "\n
      \n @if (!loading) {\n @for (_ of [0, 1, 2]; track $index) {\n
    • \n List item 1 \n
    • \n }\n } @else {\n @for (_ of [0, 1, 2]; track $index) {\n
    • \n \n
    • \n }\n }\n
    \n" }, + { + "name": "list-keyboard-example", + "description": "List Keyboard", + "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", + "html": "\n
      \n
    • \n List item 1 \n
    • \n
    • \n List item 2 \n
    • \n
    • \n List item 3 \n
    • \n
    • \n List item 4 \n
    • \n
    \n" + }, { "name": "list-nav-indicator-example", "description": "List Nav Indicator", @@ -14823,18 +14823,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-interactive-example',\n templateUrl: './list-interactive-example.component.html',\n imports: [ListModule]\n})\nexport class ListInteractiveExampleComponent {}\n", "html": "
      \n
    • \n Interactive list item 1 \n
    • \n
    • \n Interactive list item 2 \n
    • \n
    • \n Selected list item 3 \n
    • \n
    • \n Interactive Selected list item 4 \n
    • \n
    \n" }, - { - "name": "list-keyboard-example", - "description": "List Keyboard", - "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", - "html": "\n
      \n
    • \n List item 1 \n
    • \n
    • \n List item 2 \n
    • \n
    • \n List item 3 \n
    • \n
    • \n List item 4 \n
    • \n
    \n" - }, { "name": "list-loading-example", "description": "List Loading", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { SkeletonComponent } from '@fundamental-ngx/core/skeleton';\n\n@Component({\n selector: 'fd-list-loading-example',\n templateUrl: './list-loading-example.component.html',\n imports: [ButtonComponent, ListModule, SkeletonComponent]\n})\nexport class ListLoadingExampleComponent {\n loading = true;\n}\n", "html": "\n
      \n @if (!loading) {\n @for (_ of [0, 1, 2]; track $index) {\n
    • \n List item 1 \n
    • \n }\n } @else {\n @for (_ of [0, 1, 2]; track $index) {\n
    • \n \n
    • \n }\n }\n
    \n" }, + { + "name": "list-keyboard-example", + "description": "List Keyboard", + "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", + "html": "\n
      \n
    • \n List item 1 \n
    • \n
    • \n List item 2 \n
    • \n
    • \n List item 3 \n
    • \n
    • \n List item 4 \n
    • \n
    \n" + }, { "name": "list-nav-indicator-example", "description": "List Nav Indicator", @@ -14912,18 +14912,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-interactive-example',\n templateUrl: './list-interactive-example.component.html',\n imports: [ListModule]\n})\nexport class ListInteractiveExampleComponent {}\n", "html": "
      \n
    • \n Interactive list item 1 \n
    • \n
    • \n Interactive list item 2 \n
    • \n
    • \n Selected list item 3 \n
    • \n
    • \n Interactive Selected list item 4 \n
    • \n
    \n" }, - { - "name": "list-keyboard-example", - "description": "List Keyboard", - "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", - "html": "\n
      \n
    • \n List item 1 \n
    • \n
    • \n List item 2 \n
    • \n
    • \n List item 3 \n
    • \n
    • \n List item 4 \n
    • \n
    \n" - }, { "name": "list-loading-example", "description": "List Loading", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { SkeletonComponent } from '@fundamental-ngx/core/skeleton';\n\n@Component({\n selector: 'fd-list-loading-example',\n templateUrl: './list-loading-example.component.html',\n imports: [ButtonComponent, ListModule, SkeletonComponent]\n})\nexport class ListLoadingExampleComponent {\n loading = true;\n}\n", "html": "\n
      \n @if (!loading) {\n @for (_ of [0, 1, 2]; track $index) {\n
    • \n List item 1 \n
    • \n }\n } @else {\n @for (_ of [0, 1, 2]; track $index) {\n
    • \n \n
    • \n }\n }\n
    \n" }, + { + "name": "list-keyboard-example", + "description": "List Keyboard", + "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", + "html": "\n
      \n
    • \n List item 1 \n
    • \n
    • \n List item 2 \n
    • \n
    • \n List item 3 \n
    • \n
    • \n List item 4 \n
    • \n
    \n" + }, { "name": "list-nav-indicator-example", "description": "List Nav Indicator", @@ -15028,18 +15028,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-interactive-example',\n templateUrl: './list-interactive-example.component.html',\n imports: [ListModule]\n})\nexport class ListInteractiveExampleComponent {}\n", "html": "
      \n
    • \n Interactive list item 1 \n
    • \n
    • \n Interactive list item 2 \n
    • \n
    • \n Selected list item 3 \n
    • \n
    • \n Interactive Selected list item 4 \n
    • \n
    \n" }, - { - "name": "list-keyboard-example", - "description": "List Keyboard", - "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", - "html": "\n
      \n
    • \n List item 1 \n
    • \n
    • \n List item 2 \n
    • \n
    • \n List item 3 \n
    • \n
    • \n List item 4 \n
    • \n
    \n" - }, { "name": "list-loading-example", "description": "List Loading", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { SkeletonComponent } from '@fundamental-ngx/core/skeleton';\n\n@Component({\n selector: 'fd-list-loading-example',\n templateUrl: './list-loading-example.component.html',\n imports: [ButtonComponent, ListModule, SkeletonComponent]\n})\nexport class ListLoadingExampleComponent {\n loading = true;\n}\n", "html": "\n
      \n @if (!loading) {\n @for (_ of [0, 1, 2]; track $index) {\n
    • \n List item 1 \n
    • \n }\n } @else {\n @for (_ of [0, 1, 2]; track $index) {\n
    • \n \n
    • \n }\n }\n
    \n" }, + { + "name": "list-keyboard-example", + "description": "List Keyboard", + "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", + "html": "\n
      \n
    • \n List item 1 \n
    • \n
    • \n List item 2 \n
    • \n
    • \n List item 3 \n
    • \n
    • \n List item 4 \n
    • \n
    \n" + }, { "name": "list-nav-indicator-example", "description": "List Nav Indicator", @@ -15236,18 +15236,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-interactive-example',\n templateUrl: './list-interactive-example.component.html',\n imports: [ListModule]\n})\nexport class ListInteractiveExampleComponent {}\n", "html": "
      \n
    • \n Interactive list item 1 \n
    • \n
    • \n Interactive list item 2 \n
    • \n
    • \n Selected list item 3 \n
    • \n
    • \n Interactive Selected list item 4 \n
    • \n
    \n" }, - { - "name": "list-keyboard-example", - "description": "List Keyboard", - "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", - "html": "\n
      \n
    • \n List item 1 \n
    • \n
    • \n List item 2 \n
    • \n
    • \n List item 3 \n
    • \n
    • \n List item 4 \n
    • \n
    \n" - }, { "name": "list-loading-example", "description": "List Loading", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { SkeletonComponent } from '@fundamental-ngx/core/skeleton';\n\n@Component({\n selector: 'fd-list-loading-example',\n templateUrl: './list-loading-example.component.html',\n imports: [ButtonComponent, ListModule, SkeletonComponent]\n})\nexport class ListLoadingExampleComponent {\n loading = true;\n}\n", "html": "\n
      \n @if (!loading) {\n @for (_ of [0, 1, 2]; track $index) {\n
    • \n List item 1 \n
    • \n }\n } @else {\n @for (_ of [0, 1, 2]; track $index) {\n
    • \n \n
    • \n }\n }\n
    \n" }, + { + "name": "list-keyboard-example", + "description": "List Keyboard", + "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", + "html": "\n
      \n
    • \n List item 1 \n
    • \n
    • \n List item 2 \n
    • \n
    • \n List item 3 \n
    • \n
    • \n List item 4 \n
    • \n
    \n" + }, { "name": "list-nav-indicator-example", "description": "List Nav Indicator", @@ -15347,18 +15347,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-interactive-example',\n templateUrl: './list-interactive-example.component.html',\n imports: [ListModule]\n})\nexport class ListInteractiveExampleComponent {}\n", "html": "
      \n
    • \n Interactive list item 1 \n
    • \n
    • \n Interactive list item 2 \n
    • \n
    • \n Selected list item 3 \n
    • \n
    • \n Interactive Selected list item 4 \n
    • \n
    \n" }, - { - "name": "list-keyboard-example", - "description": "List Keyboard", - "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", - "html": "\n
      \n
    • \n List item 1 \n
    • \n
    • \n List item 2 \n
    • \n
    • \n List item 3 \n
    • \n
    • \n List item 4 \n
    • \n
    \n" - }, { "name": "list-loading-example", "description": "List Loading", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { SkeletonComponent } from '@fundamental-ngx/core/skeleton';\n\n@Component({\n selector: 'fd-list-loading-example',\n templateUrl: './list-loading-example.component.html',\n imports: [ButtonComponent, ListModule, SkeletonComponent]\n})\nexport class ListLoadingExampleComponent {\n loading = true;\n}\n", "html": "\n
      \n @if (!loading) {\n @for (_ of [0, 1, 2]; track $index) {\n
    • \n List item 1 \n
    • \n }\n } @else {\n @for (_ of [0, 1, 2]; track $index) {\n
    • \n \n
    • \n }\n }\n
    \n" }, + { + "name": "list-keyboard-example", + "description": "List Keyboard", + "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { FocusEscapeDirection } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ListComponent, ListModule } from '@fundamental-ngx/core/list';\n\n@Component({\n selector: 'fd-list-keyboard-example',\n templateUrl: './list-keyboard-example.component.html',\n imports: [ButtonComponent, ListModule]\n})\nexport class ListKeyboardExampleComponent {\n @ViewChild(ButtonComponent, { read: ElementRef })\n button: ElementRef;\n\n @ViewChild(ListComponent)\n list: ListComponent;\n\n handleFocusEscape(direction: FocusEscapeDirection): void {\n if (direction === 'up') {\n this.button.nativeElement.focus();\n } else {\n alert('End of list approached');\n }\n }\n\n focusFirst(): void {\n this.list.setItemActive(0);\n }\n}\n", + "html": "\n
      \n
    • \n List item 1 \n
    • \n
    • \n List item 2 \n
    • \n
    • \n List item 3 \n
    • \n
    • \n List item 4 \n
    • \n
    \n" + }, { "name": "list-nav-indicator-example", "description": "List Nav Indicator", @@ -15548,12 +15548,6 @@ "typescript": "import { Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-message-box-mobile-example',\n templateUrl: './message-box-mobile-example.component.html',\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class MessageBoxMobileExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n\n constructor(private _messageBoxService: MessageBoxService) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content, {\n mobile: true\n });\n }\n}\n", "html": "\n\n{{ title }}\n{{ content }}\n" }, - { - "name": "object-based-message-box-example", - "description": "Object Based Message Box", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-object-based-message-box-example',\n templateUrl: './object-based-message-box-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class ObjectBasedMessageBoxExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n closeReason = '';\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content);\n\n messageBoxRef.afterClosed.subscribe({\n next: (result) => {\n this.closeReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n error: (error) => {\n this.closeReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n });\n }\n}\n", - "html": "\n\n

    {{ closeReason }}

    \n\n{{ title }}\n{{ content }}\n" - }, { "name": "semantic-types-example", "description": "Semantic Types", @@ -15565,6 +15559,12 @@ "description": "Template Based Message Box", "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, TemplateRef } from '@angular/core';\n\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxModule, MessageBoxService } from '@fundamental-ngx/core/message-box';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-template-based-message-box-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './template-based-message-box-example.component.html',\n imports: [MessageBoxModule, TitleComponent, BarModule, InitialFocusDirective, ButtonComponent]\n})\nexport class TemplateBasedMessageBoxExampleComponent {\n confirmationReason: string;\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(messageBox: TemplateRef): void {\n const messageBoxRef = this._messageBoxService.open(messageBox, {\n focusTrapped: true,\n ariaLabelledBy: 'fd-message-box-template-base-header',\n ariaDescribedBy: 'fd-message-box-template-base-body'\n });\n\n messageBoxRef.afterClosed.subscribe(\n (result) => {\n this.confirmationReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.confirmationReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", "html": "\n \n \n \n

    Fruit facts

    \n
    \n \n

    The World's Most Popular Fruit is the tomato.

    \n
    \n \n \n \n \n \n
    \n
    \n\n\n

    {{ confirmationReason }}

    \n" + }, + { + "name": "object-based-message-box-example", + "description": "Object Based Message Box", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-object-based-message-box-example',\n templateUrl: './object-based-message-box-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class ObjectBasedMessageBoxExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n closeReason = '';\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content);\n\n messageBoxRef.afterClosed.subscribe({\n next: (result) => {\n this.closeReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n error: (error) => {\n this.closeReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n });\n }\n}\n", + "html": "\n\n

    {{ closeReason }}

    \n\n{{ title }}\n{{ content }}\n" } ] }, @@ -16238,17 +16238,17 @@ "sourceFile": "libs/core/notification/directives/notification-footer-content.directive.ts", "source": "typedoc", "examples": [ - { - "name": "notification-component-as-content-example", - "description": "Notification Component As Content", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" - }, { "name": "notification-group-example", "description": "Notification Group", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { NgTemplateOutlet } from '@angular/common';\nimport { TitleComponent } from '@fundamental-ngx/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { MessageStripModule } from '@fundamental-ngx/core/message-strip';\nimport { NotificationModule } from '@fundamental-ngx/core/notification';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ToolbarModule } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\nexport type Notification = {\n avatar: string;\n title: string;\n unread: boolean;\n paragraph: string;\n footerContent1: string;\n footerContent2: string;\n actionButton: string;\n};\n\n@Component({\n selector: 'fd-notification-group-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './notification-group-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n NotificationModule,\n FDP_ICON_TAB_BAR,\n NgTemplateOutlet,\n AvatarComponent,\n MessageStripModule,\n ToolbarModule,\n ObjectStatusComponent,\n IconComponent,\n TitleComponent\n ]\n})\nexport class NotificationGroupExampleComponent {\n expandedByDate = true;\n expandedByType1 = true;\n expandedByType2 = false;\n expandedByPriority = true;\n\n notifications: Notification[] = [\n {\n avatar: 'batch-payments',\n title: 'Your leave request has been accepted',\n unread: false,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'customer',\n title: 'Your leave request has been accepted',\n unread: true,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n }\n ];\n\n notificationsWarning: Notification[] = [\n {\n avatar: 'work-history',\n title: 'Approve order #1234',\n unread: true,\n paragraph: 'Adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'sap-box',\n title: 'Approve order #5678',\n unread: true,\n paragraph: 'Consectetur adipiscing elit tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '2 days ago',\n actionButton: 'Accept'\n }\n ];\n}\n", "html": "
    \n \n \n \n \n \n
    \n \n

    Notifications (30)

    \n \n \n \n \n
    \n
    \n A dismissible warning message strip. \n
    \n
      \n \n \n \n \n Today\n \n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n \n More\n \n
      \n\n \n \n \n Yesterday\n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n
      \n
    \n
    \n
    \n
    \n
    \n" }, + { + "name": "notification-component-as-content-example", + "description": "Notification Component As Content", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" + }, { "name": "notification-options-example", "description": "Notification Options", @@ -16277,17 +16277,17 @@ "sourceFile": "libs/core/notification/directives/notification-group-growing-item-title.directive.ts", "source": "typedoc", "examples": [ - { - "name": "notification-component-as-content-example", - "description": "Notification Component As Content", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" - }, { "name": "notification-group-example", "description": "Notification Group", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { NgTemplateOutlet } from '@angular/common';\nimport { TitleComponent } from '@fundamental-ngx/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { MessageStripModule } from '@fundamental-ngx/core/message-strip';\nimport { NotificationModule } from '@fundamental-ngx/core/notification';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ToolbarModule } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\nexport type Notification = {\n avatar: string;\n title: string;\n unread: boolean;\n paragraph: string;\n footerContent1: string;\n footerContent2: string;\n actionButton: string;\n};\n\n@Component({\n selector: 'fd-notification-group-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './notification-group-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n NotificationModule,\n FDP_ICON_TAB_BAR,\n NgTemplateOutlet,\n AvatarComponent,\n MessageStripModule,\n ToolbarModule,\n ObjectStatusComponent,\n IconComponent,\n TitleComponent\n ]\n})\nexport class NotificationGroupExampleComponent {\n expandedByDate = true;\n expandedByType1 = true;\n expandedByType2 = false;\n expandedByPriority = true;\n\n notifications: Notification[] = [\n {\n avatar: 'batch-payments',\n title: 'Your leave request has been accepted',\n unread: false,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'customer',\n title: 'Your leave request has been accepted',\n unread: true,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n }\n ];\n\n notificationsWarning: Notification[] = [\n {\n avatar: 'work-history',\n title: 'Approve order #1234',\n unread: true,\n paragraph: 'Adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'sap-box',\n title: 'Approve order #5678',\n unread: true,\n paragraph: 'Consectetur adipiscing elit tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '2 days ago',\n actionButton: 'Accept'\n }\n ];\n}\n", "html": "
    \n \n \n \n \n \n
    \n \n

    Notifications (30)

    \n \n \n \n \n
    \n
    \n A dismissible warning message strip. \n
    \n
      \n \n \n \n \n Today\n \n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n \n More\n \n
      \n\n \n \n \n Yesterday\n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n
      \n
    \n
    \n
    \n
    \n
    \n" }, + { + "name": "notification-component-as-content-example", + "description": "Notification Component As Content", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" + }, { "name": "notification-options-example", "description": "Notification Options", @@ -16329,17 +16329,17 @@ "sourceFile": "libs/core/notification/directives/notification-group-header-title.directive.ts", "source": "typedoc", "examples": [ - { - "name": "notification-component-as-content-example", - "description": "Notification Component As Content", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" - }, { "name": "notification-group-example", "description": "Notification Group", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { NgTemplateOutlet } from '@angular/common';\nimport { TitleComponent } from '@fundamental-ngx/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { MessageStripModule } from '@fundamental-ngx/core/message-strip';\nimport { NotificationModule } from '@fundamental-ngx/core/notification';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ToolbarModule } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\nexport type Notification = {\n avatar: string;\n title: string;\n unread: boolean;\n paragraph: string;\n footerContent1: string;\n footerContent2: string;\n actionButton: string;\n};\n\n@Component({\n selector: 'fd-notification-group-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './notification-group-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n NotificationModule,\n FDP_ICON_TAB_BAR,\n NgTemplateOutlet,\n AvatarComponent,\n MessageStripModule,\n ToolbarModule,\n ObjectStatusComponent,\n IconComponent,\n TitleComponent\n ]\n})\nexport class NotificationGroupExampleComponent {\n expandedByDate = true;\n expandedByType1 = true;\n expandedByType2 = false;\n expandedByPriority = true;\n\n notifications: Notification[] = [\n {\n avatar: 'batch-payments',\n title: 'Your leave request has been accepted',\n unread: false,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'customer',\n title: 'Your leave request has been accepted',\n unread: true,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n }\n ];\n\n notificationsWarning: Notification[] = [\n {\n avatar: 'work-history',\n title: 'Approve order #1234',\n unread: true,\n paragraph: 'Adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'sap-box',\n title: 'Approve order #5678',\n unread: true,\n paragraph: 'Consectetur adipiscing elit tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '2 days ago',\n actionButton: 'Accept'\n }\n ];\n}\n", "html": "
    \n \n \n \n \n \n
    \n \n

    Notifications (30)

    \n \n \n \n \n
    \n
    \n A dismissible warning message strip. \n
    \n
      \n \n \n \n \n Today\n \n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n \n More\n \n
      \n\n \n \n \n Yesterday\n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n
      \n
    \n
    \n
    \n
    \n
    \n" }, + { + "name": "notification-component-as-content-example", + "description": "Notification Component As Content", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" + }, { "name": "notification-options-example", "description": "Notification Options", @@ -16375,17 +16375,17 @@ "sourceFile": "libs/core/notification/directives/notification-list.directive.ts", "source": "typedoc", "examples": [ - { - "name": "notification-component-as-content-example", - "description": "Notification Component As Content", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" - }, { "name": "notification-group-example", "description": "Notification Group", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { NgTemplateOutlet } from '@angular/common';\nimport { TitleComponent } from '@fundamental-ngx/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { MessageStripModule } from '@fundamental-ngx/core/message-strip';\nimport { NotificationModule } from '@fundamental-ngx/core/notification';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ToolbarModule } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\nexport type Notification = {\n avatar: string;\n title: string;\n unread: boolean;\n paragraph: string;\n footerContent1: string;\n footerContent2: string;\n actionButton: string;\n};\n\n@Component({\n selector: 'fd-notification-group-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './notification-group-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n NotificationModule,\n FDP_ICON_TAB_BAR,\n NgTemplateOutlet,\n AvatarComponent,\n MessageStripModule,\n ToolbarModule,\n ObjectStatusComponent,\n IconComponent,\n TitleComponent\n ]\n})\nexport class NotificationGroupExampleComponent {\n expandedByDate = true;\n expandedByType1 = true;\n expandedByType2 = false;\n expandedByPriority = true;\n\n notifications: Notification[] = [\n {\n avatar: 'batch-payments',\n title: 'Your leave request has been accepted',\n unread: false,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'customer',\n title: 'Your leave request has been accepted',\n unread: true,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n }\n ];\n\n notificationsWarning: Notification[] = [\n {\n avatar: 'work-history',\n title: 'Approve order #1234',\n unread: true,\n paragraph: 'Adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'sap-box',\n title: 'Approve order #5678',\n unread: true,\n paragraph: 'Consectetur adipiscing elit tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '2 days ago',\n actionButton: 'Accept'\n }\n ];\n}\n", "html": "
    \n \n \n \n \n \n
    \n \n

    Notifications (30)

    \n \n \n \n \n
    \n
    \n A dismissible warning message strip. \n
    \n
      \n \n \n \n \n Today\n \n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n \n More\n \n
      \n\n \n \n \n Yesterday\n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n
      \n
    \n
    \n
    \n
    \n
    \n" }, + { + "name": "notification-component-as-content-example", + "description": "Notification Component As Content", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" + }, { "name": "notification-options-example", "description": "Notification Options", @@ -16414,17 +16414,17 @@ "sourceFile": "libs/core/notification/directives/notification-message-strip.directive.ts", "source": "typedoc", "examples": [ - { - "name": "notification-component-as-content-example", - "description": "Notification Component As Content", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" - }, { "name": "notification-group-example", "description": "Notification Group", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { NgTemplateOutlet } from '@angular/common';\nimport { TitleComponent } from '@fundamental-ngx/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { MessageStripModule } from '@fundamental-ngx/core/message-strip';\nimport { NotificationModule } from '@fundamental-ngx/core/notification';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ToolbarModule } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\nexport type Notification = {\n avatar: string;\n title: string;\n unread: boolean;\n paragraph: string;\n footerContent1: string;\n footerContent2: string;\n actionButton: string;\n};\n\n@Component({\n selector: 'fd-notification-group-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './notification-group-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n NotificationModule,\n FDP_ICON_TAB_BAR,\n NgTemplateOutlet,\n AvatarComponent,\n MessageStripModule,\n ToolbarModule,\n ObjectStatusComponent,\n IconComponent,\n TitleComponent\n ]\n})\nexport class NotificationGroupExampleComponent {\n expandedByDate = true;\n expandedByType1 = true;\n expandedByType2 = false;\n expandedByPriority = true;\n\n notifications: Notification[] = [\n {\n avatar: 'batch-payments',\n title: 'Your leave request has been accepted',\n unread: false,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'customer',\n title: 'Your leave request has been accepted',\n unread: true,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n }\n ];\n\n notificationsWarning: Notification[] = [\n {\n avatar: 'work-history',\n title: 'Approve order #1234',\n unread: true,\n paragraph: 'Adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'sap-box',\n title: 'Approve order #5678',\n unread: true,\n paragraph: 'Consectetur adipiscing elit tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '2 days ago',\n actionButton: 'Accept'\n }\n ];\n}\n", "html": "
    \n \n \n \n \n \n
    \n \n

    Notifications (30)

    \n \n \n \n \n
    \n
    \n A dismissible warning message strip. \n
    \n
      \n \n \n \n \n Today\n \n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n \n More\n \n
      \n\n \n \n \n Yesterday\n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n
      \n
    \n
    \n
    \n
    \n
    \n" }, + { + "name": "notification-component-as-content-example", + "description": "Notification Component As Content", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" + }, { "name": "notification-options-example", "description": "Notification Options", @@ -16453,17 +16453,17 @@ "sourceFile": "libs/core/notification/directives/notification-message-strip-container.directive.ts", "source": "typedoc", "examples": [ - { - "name": "notification-component-as-content-example", - "description": "Notification Component As Content", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" - }, { "name": "notification-group-example", "description": "Notification Group", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { NgTemplateOutlet } from '@angular/common';\nimport { TitleComponent } from '@fundamental-ngx/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { MessageStripModule } from '@fundamental-ngx/core/message-strip';\nimport { NotificationModule } from '@fundamental-ngx/core/notification';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ToolbarModule } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\nexport type Notification = {\n avatar: string;\n title: string;\n unread: boolean;\n paragraph: string;\n footerContent1: string;\n footerContent2: string;\n actionButton: string;\n};\n\n@Component({\n selector: 'fd-notification-group-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './notification-group-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n NotificationModule,\n FDP_ICON_TAB_BAR,\n NgTemplateOutlet,\n AvatarComponent,\n MessageStripModule,\n ToolbarModule,\n ObjectStatusComponent,\n IconComponent,\n TitleComponent\n ]\n})\nexport class NotificationGroupExampleComponent {\n expandedByDate = true;\n expandedByType1 = true;\n expandedByType2 = false;\n expandedByPriority = true;\n\n notifications: Notification[] = [\n {\n avatar: 'batch-payments',\n title: 'Your leave request has been accepted',\n unread: false,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'customer',\n title: 'Your leave request has been accepted',\n unread: true,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n }\n ];\n\n notificationsWarning: Notification[] = [\n {\n avatar: 'work-history',\n title: 'Approve order #1234',\n unread: true,\n paragraph: 'Adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'sap-box',\n title: 'Approve order #5678',\n unread: true,\n paragraph: 'Consectetur adipiscing elit tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '2 days ago',\n actionButton: 'Accept'\n }\n ];\n}\n", "html": "
    \n \n \n \n \n \n
    \n \n

    Notifications (30)

    \n \n \n \n \n
    \n
    \n A dismissible warning message strip. \n
    \n
      \n \n \n \n \n Today\n \n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n \n More\n \n
      \n\n \n \n \n Yesterday\n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n
      \n
    \n
    \n
    \n
    \n
    \n" }, + { + "name": "notification-component-as-content-example", + "description": "Notification Component As Content", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" + }, { "name": "notification-options-example", "description": "Notification Options", @@ -16499,17 +16499,17 @@ "sourceFile": "libs/core/notification/directives/notification-paragraph.directive.ts", "source": "typedoc", "examples": [ - { - "name": "notification-component-as-content-example", - "description": "Notification Component As Content", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" - }, { "name": "notification-group-example", "description": "Notification Group", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { NgTemplateOutlet } from '@angular/common';\nimport { TitleComponent } from '@fundamental-ngx/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { MessageStripModule } from '@fundamental-ngx/core/message-strip';\nimport { NotificationModule } from '@fundamental-ngx/core/notification';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ToolbarModule } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\nexport type Notification = {\n avatar: string;\n title: string;\n unread: boolean;\n paragraph: string;\n footerContent1: string;\n footerContent2: string;\n actionButton: string;\n};\n\n@Component({\n selector: 'fd-notification-group-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './notification-group-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n NotificationModule,\n FDP_ICON_TAB_BAR,\n NgTemplateOutlet,\n AvatarComponent,\n MessageStripModule,\n ToolbarModule,\n ObjectStatusComponent,\n IconComponent,\n TitleComponent\n ]\n})\nexport class NotificationGroupExampleComponent {\n expandedByDate = true;\n expandedByType1 = true;\n expandedByType2 = false;\n expandedByPriority = true;\n\n notifications: Notification[] = [\n {\n avatar: 'batch-payments',\n title: 'Your leave request has been accepted',\n unread: false,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'customer',\n title: 'Your leave request has been accepted',\n unread: true,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n }\n ];\n\n notificationsWarning: Notification[] = [\n {\n avatar: 'work-history',\n title: 'Approve order #1234',\n unread: true,\n paragraph: 'Adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'sap-box',\n title: 'Approve order #5678',\n unread: true,\n paragraph: 'Consectetur adipiscing elit tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '2 days ago',\n actionButton: 'Accept'\n }\n ];\n}\n", "html": "
    \n \n \n \n \n \n
    \n \n

    Notifications (30)

    \n \n \n \n \n
    \n
    \n A dismissible warning message strip. \n
    \n
      \n \n \n \n \n Today\n \n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n \n More\n \n
      \n\n \n \n \n Yesterday\n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n
      \n
    \n
    \n
    \n
    \n
    \n" }, + { + "name": "notification-component-as-content-example", + "description": "Notification Component As Content", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" + }, { "name": "notification-options-example", "description": "Notification Options", @@ -16538,17 +16538,17 @@ "sourceFile": "libs/core/notification/directives/notification-popover.directive.ts", "source": "typedoc", "examples": [ - { - "name": "notification-component-as-content-example", - "description": "Notification Component As Content", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" - }, { "name": "notification-group-example", "description": "Notification Group", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { NgTemplateOutlet } from '@angular/common';\nimport { TitleComponent } from '@fundamental-ngx/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { MessageStripModule } from '@fundamental-ngx/core/message-strip';\nimport { NotificationModule } from '@fundamental-ngx/core/notification';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ToolbarModule } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\nexport type Notification = {\n avatar: string;\n title: string;\n unread: boolean;\n paragraph: string;\n footerContent1: string;\n footerContent2: string;\n actionButton: string;\n};\n\n@Component({\n selector: 'fd-notification-group-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './notification-group-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n NotificationModule,\n FDP_ICON_TAB_BAR,\n NgTemplateOutlet,\n AvatarComponent,\n MessageStripModule,\n ToolbarModule,\n ObjectStatusComponent,\n IconComponent,\n TitleComponent\n ]\n})\nexport class NotificationGroupExampleComponent {\n expandedByDate = true;\n expandedByType1 = true;\n expandedByType2 = false;\n expandedByPriority = true;\n\n notifications: Notification[] = [\n {\n avatar: 'batch-payments',\n title: 'Your leave request has been accepted',\n unread: false,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'customer',\n title: 'Your leave request has been accepted',\n unread: true,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n }\n ];\n\n notificationsWarning: Notification[] = [\n {\n avatar: 'work-history',\n title: 'Approve order #1234',\n unread: true,\n paragraph: 'Adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'sap-box',\n title: 'Approve order #5678',\n unread: true,\n paragraph: 'Consectetur adipiscing elit tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '2 days ago',\n actionButton: 'Accept'\n }\n ];\n}\n", "html": "
    \n \n \n \n \n \n
    \n \n

    Notifications (30)

    \n \n \n \n \n
    \n
    \n A dismissible warning message strip. \n
    \n
      \n \n \n \n \n Today\n \n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n \n More\n \n
      \n\n \n \n \n Yesterday\n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n
      \n
    \n
    \n
    \n
    \n
    \n" }, + { + "name": "notification-component-as-content-example", + "description": "Notification Component As Content", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" + }, { "name": "notification-options-example", "description": "Notification Options", @@ -16577,17 +16577,17 @@ "sourceFile": "libs/core/notification/directives/notification-separator.directive.ts", "source": "typedoc", "examples": [ - { - "name": "notification-component-as-content-example", - "description": "Notification Component As Content", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" - }, { "name": "notification-group-example", "description": "Notification Group", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { NgTemplateOutlet } from '@angular/common';\nimport { TitleComponent } from '@fundamental-ngx/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { MessageStripModule } from '@fundamental-ngx/core/message-strip';\nimport { NotificationModule } from '@fundamental-ngx/core/notification';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ToolbarModule } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\nexport type Notification = {\n avatar: string;\n title: string;\n unread: boolean;\n paragraph: string;\n footerContent1: string;\n footerContent2: string;\n actionButton: string;\n};\n\n@Component({\n selector: 'fd-notification-group-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './notification-group-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n NotificationModule,\n FDP_ICON_TAB_BAR,\n NgTemplateOutlet,\n AvatarComponent,\n MessageStripModule,\n ToolbarModule,\n ObjectStatusComponent,\n IconComponent,\n TitleComponent\n ]\n})\nexport class NotificationGroupExampleComponent {\n expandedByDate = true;\n expandedByType1 = true;\n expandedByType2 = false;\n expandedByPriority = true;\n\n notifications: Notification[] = [\n {\n avatar: 'batch-payments',\n title: 'Your leave request has been accepted',\n unread: false,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'customer',\n title: 'Your leave request has been accepted',\n unread: true,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n }\n ];\n\n notificationsWarning: Notification[] = [\n {\n avatar: 'work-history',\n title: 'Approve order #1234',\n unread: true,\n paragraph: 'Adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'sap-box',\n title: 'Approve order #5678',\n unread: true,\n paragraph: 'Consectetur adipiscing elit tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '2 days ago',\n actionButton: 'Accept'\n }\n ];\n}\n", "html": "
    \n \n \n \n \n \n
    \n \n

    Notifications (30)

    \n \n \n \n \n
    \n
    \n A dismissible warning message strip. \n
    \n
      \n \n \n \n \n Today\n \n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n \n More\n \n
      \n\n \n \n \n Yesterday\n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n
      \n
    \n
    \n
    \n
    \n
    \n" }, + { + "name": "notification-component-as-content-example", + "description": "Notification Component As Content", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" + }, { "name": "notification-options-example", "description": "Notification Options", @@ -16629,17 +16629,17 @@ "sourceFile": "libs/core/notification/directives/notification-title.directive.ts", "source": "typedoc", "examples": [ - { - "name": "notification-component-as-content-example", - "description": "Notification Component As Content", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" - }, { "name": "notification-group-example", "description": "Notification Group", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { NgTemplateOutlet } from '@angular/common';\nimport { TitleComponent } from '@fundamental-ngx/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { MessageStripModule } from '@fundamental-ngx/core/message-strip';\nimport { NotificationModule } from '@fundamental-ngx/core/notification';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ToolbarModule } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\nexport type Notification = {\n avatar: string;\n title: string;\n unread: boolean;\n paragraph: string;\n footerContent1: string;\n footerContent2: string;\n actionButton: string;\n};\n\n@Component({\n selector: 'fd-notification-group-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './notification-group-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n NotificationModule,\n FDP_ICON_TAB_BAR,\n NgTemplateOutlet,\n AvatarComponent,\n MessageStripModule,\n ToolbarModule,\n ObjectStatusComponent,\n IconComponent,\n TitleComponent\n ]\n})\nexport class NotificationGroupExampleComponent {\n expandedByDate = true;\n expandedByType1 = true;\n expandedByType2 = false;\n expandedByPriority = true;\n\n notifications: Notification[] = [\n {\n avatar: 'batch-payments',\n title: 'Your leave request has been accepted',\n unread: false,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'customer',\n title: 'Your leave request has been accepted',\n unread: true,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n }\n ];\n\n notificationsWarning: Notification[] = [\n {\n avatar: 'work-history',\n title: 'Approve order #1234',\n unread: true,\n paragraph: 'Adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'sap-box',\n title: 'Approve order #5678',\n unread: true,\n paragraph: 'Consectetur adipiscing elit tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '2 days ago',\n actionButton: 'Accept'\n }\n ];\n}\n", "html": "
    \n \n \n \n \n \n
    \n \n

    Notifications (30)

    \n \n \n \n \n
    \n
    \n A dismissible warning message strip. \n
    \n
      \n \n \n \n \n Today\n \n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n \n More\n \n
      \n\n \n \n \n Yesterday\n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n
      \n
    \n
    \n
    \n
    \n
    \n" }, + { + "name": "notification-component-as-content-example", + "description": "Notification Component As Content", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" + }, { "name": "notification-options-example", "description": "Notification Options", @@ -17152,18 +17152,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { textTypeConfig } from '../config-for-examples/text-type.config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-dynamic-overflow-example',\n templateUrl: './platform-icon-tab-bar-dynamic-overflow-example.component.html',\n imports: [IconTabBarComponent, ButtonComponent]\n})\nexport class PlatformIconTabBarDynamicOverflowExampleComponent {\n items: TabConfig[] = structuredClone(textTypeConfig);\n\n /** Whether the long labels variant is active. */\n useLongLabels = false;\n\n /** Toggle tab labels between short and long text to simulate a structure change (e.g. language switch). */\n toggleLabels(): void {\n this.useLongLabels = !this.useLongLabels;\n const base = structuredClone(textTypeConfig);\n if (this.useLongLabels) {\n base.forEach((item) => {\n item.label = `Very Long Label For ${item.label} With Extra Text`;\n });\n }\n this.items = base;\n }\n\n /** Add five more tabs dynamically to force overflow. */\n addMoreTabs(): void {\n const startIndex = this.items.length;\n const extra: TabConfig[] = Array.from({ length: 5 }, (_, i) => ({\n label: `New Tab ${startIndex + i}`,\n counter: Math.floor(Math.random() * 100),\n color: null\n }));\n this.items = [...this.items, ...extra];\n }\n}\n", "html": "
    \n \n \n
    \n\n\n" }, - { - "name": "platform-icon-tab-bar-filter-type-example", - "description": "Platform Icon Tab Bar Filter Type", - "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-filter-type-example',\n templateUrl: './platform-icon-tab-bar-filter-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarFilterTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", - "html": "\n" - }, { "name": "platform-icon-tab-bar-icon-only-type-example", "description": "Platform Icon Tab Bar Icon Only Type", "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-icon-only-type-example',\n templateUrl: './platform-icon-tab-bar-icon-only-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarIconOnlyTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", "html": "\n" }, + { + "name": "platform-icon-tab-bar-filter-type-example", + "description": "Platform Icon Tab Bar Filter Type", + "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-filter-type-example',\n templateUrl: './platform-icon-tab-bar-filter-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarFilterTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", + "html": "\n" + }, { "name": "platform-icon-tab-bar-icon-type-example", "description": "Platform Icon Tab Bar Icon Type", @@ -17544,6 +17544,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule } from '@fundamental-ngx/platform/table';\nimport {\n ChildTableDataSource,\n CollectionNumberFilter,\n CollectionStringFilter,\n FdpTableDataSource,\n FilterType,\n FilterableColumnDataType,\n SortDirection,\n TableChildrenDataProvider,\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableRow,\n TableState,\n TableVirtualScrollDirective,\n TreeTableItem\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, of } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-doc-advanced-scrolling-example',\n templateUrl: './advanced-scrolling-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule\n ]\n})\nexport class AdvancedScrollingExampleComponent {\n source: TableDataSource;\n childSource: ChildTableDataSource;\n readonly filterTypeEnum = FilterType;\n readonly dataTypeEnum = FilterableColumnDataType;\n readonly selectOptions = ['Laptops 1 (Level 1)', 'Laptops 12 (Level 1)'];\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n this.childSource = new ChildTableDataSource(new ChildTableProviderExample());\n }\n}\n\nexport interface ExampleItem extends TreeTableItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n hasChildren: boolean;\n children?: FdpTableDataSource;\n}\n\nclass ChildTableProviderExample extends TableChildrenDataProvider {\n items: Map, ExampleItem[]> = new Map();\n totalItems = 200;\n startIndex = 0;\n allItemsMap = new Map, ExampleItem[]>();\n\n rowChildrenCount(row: TableRow): Observable {\n return of(this.totalItems);\n }\n\n /**\n * Unlike default dataSource, childDataSource accepts array of table rows as a second argument.\n * This is done to load child rows in bulk for the cases when multiple rows being expanded at the same time.\n * @param tableState\n * @param tableRows\n */\n fetch(\n tableState?: TableState,\n tableRows?: TableRow[]\n ): Observable, ExampleItem[]>> {\n const itemsMap = new Map, ExampleItem[]>();\n\n /** Logic of retrieving the child rows for a particular row in tableRows array. */\n tableRows?.forEach((row) => {\n let allItems = this.allItemsMap.get(row);\n const currentPage = tableState?.page.currentPage;\n if (!allItems) {\n allItems = generateItems(this.totalItems, row.level + 1);\n this.allItemsMap.set(row, allItems);\n }\n\n // apply searching\n if (tableState?.searchInput) {\n allItems = this.search(allItems, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n allItems = this.sort(allItems, tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n allItems = this.filter(allItems, tableState);\n }\n\n // Apply paging\n if (currentPage && tableState?.page) {\n const startIndex = (currentPage - 1) * tableState.page.pageSize;\n allItems = allItems.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n itemsMap.set(row, allItems);\n });\n\n return of(itemsMap).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort(items: ExampleItem[], { sortBy }: TableState): ExampleItem[] {\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 5000;\n startIndex = 0;\n allItems: ExampleItem[];\n\n constructor(public level = 0) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.allItems = this.allItems || generateItems(this.totalItems, this.level);\n this.items = [...this.allItems];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(this.items, tableState);\n }\n\n // Apply paging\n if (tableState?.page?.currentPage) {\n const startIndex = (tableState.page.currentPage - 1) * tableState.page.pageSize;\n this.items = this.items.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n return of(this.items).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\nfunction generateItems(size = 5000, level = 0, startIndex = 0): ExampleItem[] {\n return new Array(size).fill(null).map(() => ({\n name: `Laptops ${startIndex++} (Level ${level + 1})`,\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true,\n hasChildren: level < 2 ? true : false\n }));\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => (a ? a[b] : null), object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n", "html": "\n \n\n \n \n\n \n\n \n \n\n \n \n\n\n\n\n" }, + { + "name": "platform-table-initial-loading-example", + "description": "Platform Table Initial Loading", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", + "html": "\n \n\n \n\n \n\n \n\n" + }, + { + "name": "platform-table-editable-rows-example", + "description": "Platform Table Editable Rows", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", + "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" + }, { "name": "table-custom-pagination-example", "description": "Table Custom Pagination", @@ -17556,18 +17568,6 @@ "typescript": "import { ChangeDetectionStrategy, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { PlatformTableModule, TableComponent } from '@fundamental-ngx/platform/table';\nimport {\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableState,\n TableVirtualScrollDirective\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, delay, of } from 'rxjs';\n\n@Component({\n selector: 'fdp-table-custom-pagination-outer-scroll-example',\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule,\n PaginationModule\n ],\n templateUrl: './table-custom-pagination-outer-scroll-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class TableCustomPaginationOuterScrollExampleComponent implements OnInit {\n @ViewChild(TableComponent)\n table: TableComponent;\n\n source: TableDataSource;\n state: TableState;\n currentPage = 1;\n pageSize = 50;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n\n ngOnInit(): void {\n this.state = this._getDefaultState();\n }\n\n pageChanged(currentPage: number): void {\n this.currentPage = currentPage;\n this.table.setCurrentPage(this.currentPage);\n }\n\n itemsPerPageChanged(itemsPerPage: number): void {\n this.pageSize = itemsPerPage;\n this.table.setPageSize(this.pageSize, true);\n }\n\n /**\n * Simulating scroll position update. Once table is initialized app can set back preserved scrolling table\n * position so table can scroll it its original state.\n *\n * Note: Bellow scrollTopPosition property is set based on the scrolling position that was read from\n * this table example. Just some number to showcase this.\n */\n _getDefaultState(): TableState {\n return {\n columnKeys: [],\n sortBy: [],\n filterBy: [],\n groupBy: [],\n columns: [],\n searchInput: {\n category: null,\n text: ''\n },\n freezeToColumn: null,\n freezeToEndColumn: null,\n page: {\n pageSize: this.pageSize,\n currentPage: this.currentPage\n },\n scrollTopPosition: 0\n };\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n children?: ExampleItem[];\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [...ITEMS];\n totalItems = ITEMS.length;\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n this.totalItems = this.items.length;\n\n const currentPage = tableState?.page.currentPage || 1;\n const size = tableState?.page.pageSize || 50;\n const skip = (currentPage - 1) * size;\n\n const paginatedItems = this.items.slice(skip, size * currentPage);\n\n return of(paginatedItems).pipe(delay(1000));\n }\n}\n\n// Example items\nconst ITEMS: ExampleItem[] = new Array(5000).fill(null).map((_, index) => ({\n name: 'Laptops ' + index,\n price: {\n value: Math.floor(Math.random() * 1000),\n currency: 'USD'\n }\n}));\n", "html": "
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n


    \n \n \n \n\n \n\n \n\n \n\n \n \n
    \n" }, - { - "name": "platform-table-editable-rows-example", - "description": "Platform Table Editable Rows", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", - "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" - }, - { - "name": "platform-table-initial-loading-example", - "description": "Platform Table Initial Loading", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", - "html": "\n \n\n \n\n \n\n \n\n" - }, { "name": "platform-table-preserved-state-example", "description": "Platform Table Preserved State", @@ -17978,6 +17978,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule } from '@fundamental-ngx/platform/table';\nimport {\n ChildTableDataSource,\n CollectionNumberFilter,\n CollectionStringFilter,\n FdpTableDataSource,\n FilterType,\n FilterableColumnDataType,\n SortDirection,\n TableChildrenDataProvider,\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableRow,\n TableState,\n TableVirtualScrollDirective,\n TreeTableItem\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, of } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-doc-advanced-scrolling-example',\n templateUrl: './advanced-scrolling-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule\n ]\n})\nexport class AdvancedScrollingExampleComponent {\n source: TableDataSource;\n childSource: ChildTableDataSource;\n readonly filterTypeEnum = FilterType;\n readonly dataTypeEnum = FilterableColumnDataType;\n readonly selectOptions = ['Laptops 1 (Level 1)', 'Laptops 12 (Level 1)'];\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n this.childSource = new ChildTableDataSource(new ChildTableProviderExample());\n }\n}\n\nexport interface ExampleItem extends TreeTableItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n hasChildren: boolean;\n children?: FdpTableDataSource;\n}\n\nclass ChildTableProviderExample extends TableChildrenDataProvider {\n items: Map, ExampleItem[]> = new Map();\n totalItems = 200;\n startIndex = 0;\n allItemsMap = new Map, ExampleItem[]>();\n\n rowChildrenCount(row: TableRow): Observable {\n return of(this.totalItems);\n }\n\n /**\n * Unlike default dataSource, childDataSource accepts array of table rows as a second argument.\n * This is done to load child rows in bulk for the cases when multiple rows being expanded at the same time.\n * @param tableState\n * @param tableRows\n */\n fetch(\n tableState?: TableState,\n tableRows?: TableRow[]\n ): Observable, ExampleItem[]>> {\n const itemsMap = new Map, ExampleItem[]>();\n\n /** Logic of retrieving the child rows for a particular row in tableRows array. */\n tableRows?.forEach((row) => {\n let allItems = this.allItemsMap.get(row);\n const currentPage = tableState?.page.currentPage;\n if (!allItems) {\n allItems = generateItems(this.totalItems, row.level + 1);\n this.allItemsMap.set(row, allItems);\n }\n\n // apply searching\n if (tableState?.searchInput) {\n allItems = this.search(allItems, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n allItems = this.sort(allItems, tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n allItems = this.filter(allItems, tableState);\n }\n\n // Apply paging\n if (currentPage && tableState?.page) {\n const startIndex = (currentPage - 1) * tableState.page.pageSize;\n allItems = allItems.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n itemsMap.set(row, allItems);\n });\n\n return of(itemsMap).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort(items: ExampleItem[], { sortBy }: TableState): ExampleItem[] {\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 5000;\n startIndex = 0;\n allItems: ExampleItem[];\n\n constructor(public level = 0) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.allItems = this.allItems || generateItems(this.totalItems, this.level);\n this.items = [...this.allItems];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(this.items, tableState);\n }\n\n // Apply paging\n if (tableState?.page?.currentPage) {\n const startIndex = (tableState.page.currentPage - 1) * tableState.page.pageSize;\n this.items = this.items.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n return of(this.items).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\nfunction generateItems(size = 5000, level = 0, startIndex = 0): ExampleItem[] {\n return new Array(size).fill(null).map(() => ({\n name: `Laptops ${startIndex++} (Level ${level + 1})`,\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true,\n hasChildren: level < 2 ? true : false\n }));\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => (a ? a[b] : null), object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n", "html": "\n \n\n \n \n\n \n\n \n \n\n \n \n\n\n\n\n" }, + { + "name": "platform-table-initial-loading-example", + "description": "Platform Table Initial Loading", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", + "html": "\n \n\n \n\n \n\n \n\n" + }, + { + "name": "platform-table-editable-rows-example", + "description": "Platform Table Editable Rows", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", + "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" + }, { "name": "table-custom-pagination-example", "description": "Table Custom Pagination", @@ -17990,18 +18002,6 @@ "typescript": "import { ChangeDetectionStrategy, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { PlatformTableModule, TableComponent } from '@fundamental-ngx/platform/table';\nimport {\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableState,\n TableVirtualScrollDirective\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, delay, of } from 'rxjs';\n\n@Component({\n selector: 'fdp-table-custom-pagination-outer-scroll-example',\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule,\n PaginationModule\n ],\n templateUrl: './table-custom-pagination-outer-scroll-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class TableCustomPaginationOuterScrollExampleComponent implements OnInit {\n @ViewChild(TableComponent)\n table: TableComponent;\n\n source: TableDataSource;\n state: TableState;\n currentPage = 1;\n pageSize = 50;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n\n ngOnInit(): void {\n this.state = this._getDefaultState();\n }\n\n pageChanged(currentPage: number): void {\n this.currentPage = currentPage;\n this.table.setCurrentPage(this.currentPage);\n }\n\n itemsPerPageChanged(itemsPerPage: number): void {\n this.pageSize = itemsPerPage;\n this.table.setPageSize(this.pageSize, true);\n }\n\n /**\n * Simulating scroll position update. Once table is initialized app can set back preserved scrolling table\n * position so table can scroll it its original state.\n *\n * Note: Bellow scrollTopPosition property is set based on the scrolling position that was read from\n * this table example. Just some number to showcase this.\n */\n _getDefaultState(): TableState {\n return {\n columnKeys: [],\n sortBy: [],\n filterBy: [],\n groupBy: [],\n columns: [],\n searchInput: {\n category: null,\n text: ''\n },\n freezeToColumn: null,\n freezeToEndColumn: null,\n page: {\n pageSize: this.pageSize,\n currentPage: this.currentPage\n },\n scrollTopPosition: 0\n };\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n children?: ExampleItem[];\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [...ITEMS];\n totalItems = ITEMS.length;\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n this.totalItems = this.items.length;\n\n const currentPage = tableState?.page.currentPage || 1;\n const size = tableState?.page.pageSize || 50;\n const skip = (currentPage - 1) * size;\n\n const paginatedItems = this.items.slice(skip, size * currentPage);\n\n return of(paginatedItems).pipe(delay(1000));\n }\n}\n\n// Example items\nconst ITEMS: ExampleItem[] = new Array(5000).fill(null).map((_, index) => ({\n name: 'Laptops ' + index,\n price: {\n value: Math.floor(Math.random() * 1000),\n currency: 'USD'\n }\n}));\n", "html": "
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n


    \n \n \n \n\n \n\n \n\n \n\n \n \n
    \n" }, - { - "name": "platform-table-editable-rows-example", - "description": "Platform Table Editable Rows", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", - "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" - }, - { - "name": "platform-table-initial-loading-example", - "description": "Platform Table Initial Loading", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", - "html": "\n \n\n \n\n \n\n \n\n" - }, { "name": "platform-table-preserved-state-example", "description": "Platform Table Preserved State", @@ -18439,6 +18439,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule } from '@fundamental-ngx/platform/table';\nimport {\n ChildTableDataSource,\n CollectionNumberFilter,\n CollectionStringFilter,\n FdpTableDataSource,\n FilterType,\n FilterableColumnDataType,\n SortDirection,\n TableChildrenDataProvider,\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableRow,\n TableState,\n TableVirtualScrollDirective,\n TreeTableItem\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, of } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-doc-advanced-scrolling-example',\n templateUrl: './advanced-scrolling-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule\n ]\n})\nexport class AdvancedScrollingExampleComponent {\n source: TableDataSource;\n childSource: ChildTableDataSource;\n readonly filterTypeEnum = FilterType;\n readonly dataTypeEnum = FilterableColumnDataType;\n readonly selectOptions = ['Laptops 1 (Level 1)', 'Laptops 12 (Level 1)'];\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n this.childSource = new ChildTableDataSource(new ChildTableProviderExample());\n }\n}\n\nexport interface ExampleItem extends TreeTableItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n hasChildren: boolean;\n children?: FdpTableDataSource;\n}\n\nclass ChildTableProviderExample extends TableChildrenDataProvider {\n items: Map, ExampleItem[]> = new Map();\n totalItems = 200;\n startIndex = 0;\n allItemsMap = new Map, ExampleItem[]>();\n\n rowChildrenCount(row: TableRow): Observable {\n return of(this.totalItems);\n }\n\n /**\n * Unlike default dataSource, childDataSource accepts array of table rows as a second argument.\n * This is done to load child rows in bulk for the cases when multiple rows being expanded at the same time.\n * @param tableState\n * @param tableRows\n */\n fetch(\n tableState?: TableState,\n tableRows?: TableRow[]\n ): Observable, ExampleItem[]>> {\n const itemsMap = new Map, ExampleItem[]>();\n\n /** Logic of retrieving the child rows for a particular row in tableRows array. */\n tableRows?.forEach((row) => {\n let allItems = this.allItemsMap.get(row);\n const currentPage = tableState?.page.currentPage;\n if (!allItems) {\n allItems = generateItems(this.totalItems, row.level + 1);\n this.allItemsMap.set(row, allItems);\n }\n\n // apply searching\n if (tableState?.searchInput) {\n allItems = this.search(allItems, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n allItems = this.sort(allItems, tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n allItems = this.filter(allItems, tableState);\n }\n\n // Apply paging\n if (currentPage && tableState?.page) {\n const startIndex = (currentPage - 1) * tableState.page.pageSize;\n allItems = allItems.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n itemsMap.set(row, allItems);\n });\n\n return of(itemsMap).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort(items: ExampleItem[], { sortBy }: TableState): ExampleItem[] {\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 5000;\n startIndex = 0;\n allItems: ExampleItem[];\n\n constructor(public level = 0) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.allItems = this.allItems || generateItems(this.totalItems, this.level);\n this.items = [...this.allItems];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(this.items, tableState);\n }\n\n // Apply paging\n if (tableState?.page?.currentPage) {\n const startIndex = (tableState.page.currentPage - 1) * tableState.page.pageSize;\n this.items = this.items.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n return of(this.items).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\nfunction generateItems(size = 5000, level = 0, startIndex = 0): ExampleItem[] {\n return new Array(size).fill(null).map(() => ({\n name: `Laptops ${startIndex++} (Level ${level + 1})`,\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true,\n hasChildren: level < 2 ? true : false\n }));\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => (a ? a[b] : null), object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n", "html": "\n \n\n \n \n\n \n\n \n \n\n \n \n\n\n\n\n" }, + { + "name": "platform-table-initial-loading-example", + "description": "Platform Table Initial Loading", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", + "html": "\n \n\n \n\n \n\n \n\n" + }, + { + "name": "platform-table-editable-rows-example", + "description": "Platform Table Editable Rows", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", + "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" + }, { "name": "table-custom-pagination-example", "description": "Table Custom Pagination", @@ -18451,18 +18463,6 @@ "typescript": "import { ChangeDetectionStrategy, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { PlatformTableModule, TableComponent } from '@fundamental-ngx/platform/table';\nimport {\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableState,\n TableVirtualScrollDirective\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, delay, of } from 'rxjs';\n\n@Component({\n selector: 'fdp-table-custom-pagination-outer-scroll-example',\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule,\n PaginationModule\n ],\n templateUrl: './table-custom-pagination-outer-scroll-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class TableCustomPaginationOuterScrollExampleComponent implements OnInit {\n @ViewChild(TableComponent)\n table: TableComponent;\n\n source: TableDataSource;\n state: TableState;\n currentPage = 1;\n pageSize = 50;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n\n ngOnInit(): void {\n this.state = this._getDefaultState();\n }\n\n pageChanged(currentPage: number): void {\n this.currentPage = currentPage;\n this.table.setCurrentPage(this.currentPage);\n }\n\n itemsPerPageChanged(itemsPerPage: number): void {\n this.pageSize = itemsPerPage;\n this.table.setPageSize(this.pageSize, true);\n }\n\n /**\n * Simulating scroll position update. Once table is initialized app can set back preserved scrolling table\n * position so table can scroll it its original state.\n *\n * Note: Bellow scrollTopPosition property is set based on the scrolling position that was read from\n * this table example. Just some number to showcase this.\n */\n _getDefaultState(): TableState {\n return {\n columnKeys: [],\n sortBy: [],\n filterBy: [],\n groupBy: [],\n columns: [],\n searchInput: {\n category: null,\n text: ''\n },\n freezeToColumn: null,\n freezeToEndColumn: null,\n page: {\n pageSize: this.pageSize,\n currentPage: this.currentPage\n },\n scrollTopPosition: 0\n };\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n children?: ExampleItem[];\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [...ITEMS];\n totalItems = ITEMS.length;\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n this.totalItems = this.items.length;\n\n const currentPage = tableState?.page.currentPage || 1;\n const size = tableState?.page.pageSize || 50;\n const skip = (currentPage - 1) * size;\n\n const paginatedItems = this.items.slice(skip, size * currentPage);\n\n return of(paginatedItems).pipe(delay(1000));\n }\n}\n\n// Example items\nconst ITEMS: ExampleItem[] = new Array(5000).fill(null).map((_, index) => ({\n name: 'Laptops ' + index,\n price: {\n value: Math.floor(Math.random() * 1000),\n currency: 'USD'\n }\n}));\n", "html": "
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n


    \n \n \n \n\n \n\n \n\n \n\n \n \n
    \n" }, - { - "name": "platform-table-editable-rows-example", - "description": "Platform Table Editable Rows", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", - "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" - }, - { - "name": "platform-table-initial-loading-example", - "description": "Platform Table Initial Loading", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", - "html": "\n \n\n \n\n \n\n \n\n" - }, { "name": "platform-table-preserved-state-example", "description": "Platform Table Preserved State", @@ -18859,6 +18859,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule } from '@fundamental-ngx/platform/table';\nimport {\n ChildTableDataSource,\n CollectionNumberFilter,\n CollectionStringFilter,\n FdpTableDataSource,\n FilterType,\n FilterableColumnDataType,\n SortDirection,\n TableChildrenDataProvider,\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableRow,\n TableState,\n TableVirtualScrollDirective,\n TreeTableItem\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, of } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-doc-advanced-scrolling-example',\n templateUrl: './advanced-scrolling-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule\n ]\n})\nexport class AdvancedScrollingExampleComponent {\n source: TableDataSource;\n childSource: ChildTableDataSource;\n readonly filterTypeEnum = FilterType;\n readonly dataTypeEnum = FilterableColumnDataType;\n readonly selectOptions = ['Laptops 1 (Level 1)', 'Laptops 12 (Level 1)'];\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n this.childSource = new ChildTableDataSource(new ChildTableProviderExample());\n }\n}\n\nexport interface ExampleItem extends TreeTableItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n hasChildren: boolean;\n children?: FdpTableDataSource;\n}\n\nclass ChildTableProviderExample extends TableChildrenDataProvider {\n items: Map, ExampleItem[]> = new Map();\n totalItems = 200;\n startIndex = 0;\n allItemsMap = new Map, ExampleItem[]>();\n\n rowChildrenCount(row: TableRow): Observable {\n return of(this.totalItems);\n }\n\n /**\n * Unlike default dataSource, childDataSource accepts array of table rows as a second argument.\n * This is done to load child rows in bulk for the cases when multiple rows being expanded at the same time.\n * @param tableState\n * @param tableRows\n */\n fetch(\n tableState?: TableState,\n tableRows?: TableRow[]\n ): Observable, ExampleItem[]>> {\n const itemsMap = new Map, ExampleItem[]>();\n\n /** Logic of retrieving the child rows for a particular row in tableRows array. */\n tableRows?.forEach((row) => {\n let allItems = this.allItemsMap.get(row);\n const currentPage = tableState?.page.currentPage;\n if (!allItems) {\n allItems = generateItems(this.totalItems, row.level + 1);\n this.allItemsMap.set(row, allItems);\n }\n\n // apply searching\n if (tableState?.searchInput) {\n allItems = this.search(allItems, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n allItems = this.sort(allItems, tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n allItems = this.filter(allItems, tableState);\n }\n\n // Apply paging\n if (currentPage && tableState?.page) {\n const startIndex = (currentPage - 1) * tableState.page.pageSize;\n allItems = allItems.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n itemsMap.set(row, allItems);\n });\n\n return of(itemsMap).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort(items: ExampleItem[], { sortBy }: TableState): ExampleItem[] {\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 5000;\n startIndex = 0;\n allItems: ExampleItem[];\n\n constructor(public level = 0) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.allItems = this.allItems || generateItems(this.totalItems, this.level);\n this.items = [...this.allItems];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(this.items, tableState);\n }\n\n // Apply paging\n if (tableState?.page?.currentPage) {\n const startIndex = (tableState.page.currentPage - 1) * tableState.page.pageSize;\n this.items = this.items.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n return of(this.items).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\nfunction generateItems(size = 5000, level = 0, startIndex = 0): ExampleItem[] {\n return new Array(size).fill(null).map(() => ({\n name: `Laptops ${startIndex++} (Level ${level + 1})`,\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true,\n hasChildren: level < 2 ? true : false\n }));\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => (a ? a[b] : null), object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n", "html": "\n \n\n \n \n\n \n\n \n \n\n \n \n\n\n\n\n" }, + { + "name": "platform-table-initial-loading-example", + "description": "Platform Table Initial Loading", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", + "html": "\n \n\n \n\n \n\n \n\n" + }, + { + "name": "platform-table-editable-rows-example", + "description": "Platform Table Editable Rows", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", + "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" + }, { "name": "table-custom-pagination-example", "description": "Table Custom Pagination", @@ -18871,18 +18883,6 @@ "typescript": "import { ChangeDetectionStrategy, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { PlatformTableModule, TableComponent } from '@fundamental-ngx/platform/table';\nimport {\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableState,\n TableVirtualScrollDirective\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, delay, of } from 'rxjs';\n\n@Component({\n selector: 'fdp-table-custom-pagination-outer-scroll-example',\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule,\n PaginationModule\n ],\n templateUrl: './table-custom-pagination-outer-scroll-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class TableCustomPaginationOuterScrollExampleComponent implements OnInit {\n @ViewChild(TableComponent)\n table: TableComponent;\n\n source: TableDataSource;\n state: TableState;\n currentPage = 1;\n pageSize = 50;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n\n ngOnInit(): void {\n this.state = this._getDefaultState();\n }\n\n pageChanged(currentPage: number): void {\n this.currentPage = currentPage;\n this.table.setCurrentPage(this.currentPage);\n }\n\n itemsPerPageChanged(itemsPerPage: number): void {\n this.pageSize = itemsPerPage;\n this.table.setPageSize(this.pageSize, true);\n }\n\n /**\n * Simulating scroll position update. Once table is initialized app can set back preserved scrolling table\n * position so table can scroll it its original state.\n *\n * Note: Bellow scrollTopPosition property is set based on the scrolling position that was read from\n * this table example. Just some number to showcase this.\n */\n _getDefaultState(): TableState {\n return {\n columnKeys: [],\n sortBy: [],\n filterBy: [],\n groupBy: [],\n columns: [],\n searchInput: {\n category: null,\n text: ''\n },\n freezeToColumn: null,\n freezeToEndColumn: null,\n page: {\n pageSize: this.pageSize,\n currentPage: this.currentPage\n },\n scrollTopPosition: 0\n };\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n children?: ExampleItem[];\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [...ITEMS];\n totalItems = ITEMS.length;\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n this.totalItems = this.items.length;\n\n const currentPage = tableState?.page.currentPage || 1;\n const size = tableState?.page.pageSize || 50;\n const skip = (currentPage - 1) * size;\n\n const paginatedItems = this.items.slice(skip, size * currentPage);\n\n return of(paginatedItems).pipe(delay(1000));\n }\n}\n\n// Example items\nconst ITEMS: ExampleItem[] = new Array(5000).fill(null).map((_, index) => ({\n name: 'Laptops ' + index,\n price: {\n value: Math.floor(Math.random() * 1000),\n currency: 'USD'\n }\n}));\n", "html": "
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n


    \n \n \n \n\n \n\n \n\n \n\n \n \n
    \n" }, - { - "name": "platform-table-editable-rows-example", - "description": "Platform Table Editable Rows", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", - "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" - }, - { - "name": "platform-table-initial-loading-example", - "description": "Platform Table Initial Loading", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", - "html": "\n \n\n \n\n \n\n \n\n" - }, { "name": "platform-table-preserved-state-example", "description": "Platform Table Preserved State", @@ -19316,6 +19316,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule } from '@fundamental-ngx/platform/table';\nimport {\n ChildTableDataSource,\n CollectionNumberFilter,\n CollectionStringFilter,\n FdpTableDataSource,\n FilterType,\n FilterableColumnDataType,\n SortDirection,\n TableChildrenDataProvider,\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableRow,\n TableState,\n TableVirtualScrollDirective,\n TreeTableItem\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, of } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-doc-advanced-scrolling-example',\n templateUrl: './advanced-scrolling-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule\n ]\n})\nexport class AdvancedScrollingExampleComponent {\n source: TableDataSource;\n childSource: ChildTableDataSource;\n readonly filterTypeEnum = FilterType;\n readonly dataTypeEnum = FilterableColumnDataType;\n readonly selectOptions = ['Laptops 1 (Level 1)', 'Laptops 12 (Level 1)'];\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n this.childSource = new ChildTableDataSource(new ChildTableProviderExample());\n }\n}\n\nexport interface ExampleItem extends TreeTableItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n hasChildren: boolean;\n children?: FdpTableDataSource;\n}\n\nclass ChildTableProviderExample extends TableChildrenDataProvider {\n items: Map, ExampleItem[]> = new Map();\n totalItems = 200;\n startIndex = 0;\n allItemsMap = new Map, ExampleItem[]>();\n\n rowChildrenCount(row: TableRow): Observable {\n return of(this.totalItems);\n }\n\n /**\n * Unlike default dataSource, childDataSource accepts array of table rows as a second argument.\n * This is done to load child rows in bulk for the cases when multiple rows being expanded at the same time.\n * @param tableState\n * @param tableRows\n */\n fetch(\n tableState?: TableState,\n tableRows?: TableRow[]\n ): Observable, ExampleItem[]>> {\n const itemsMap = new Map, ExampleItem[]>();\n\n /** Logic of retrieving the child rows for a particular row in tableRows array. */\n tableRows?.forEach((row) => {\n let allItems = this.allItemsMap.get(row);\n const currentPage = tableState?.page.currentPage;\n if (!allItems) {\n allItems = generateItems(this.totalItems, row.level + 1);\n this.allItemsMap.set(row, allItems);\n }\n\n // apply searching\n if (tableState?.searchInput) {\n allItems = this.search(allItems, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n allItems = this.sort(allItems, tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n allItems = this.filter(allItems, tableState);\n }\n\n // Apply paging\n if (currentPage && tableState?.page) {\n const startIndex = (currentPage - 1) * tableState.page.pageSize;\n allItems = allItems.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n itemsMap.set(row, allItems);\n });\n\n return of(itemsMap).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort(items: ExampleItem[], { sortBy }: TableState): ExampleItem[] {\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 5000;\n startIndex = 0;\n allItems: ExampleItem[];\n\n constructor(public level = 0) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.allItems = this.allItems || generateItems(this.totalItems, this.level);\n this.items = [...this.allItems];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(this.items, tableState);\n }\n\n // Apply paging\n if (tableState?.page?.currentPage) {\n const startIndex = (tableState.page.currentPage - 1) * tableState.page.pageSize;\n this.items = this.items.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n return of(this.items).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\nfunction generateItems(size = 5000, level = 0, startIndex = 0): ExampleItem[] {\n return new Array(size).fill(null).map(() => ({\n name: `Laptops ${startIndex++} (Level ${level + 1})`,\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true,\n hasChildren: level < 2 ? true : false\n }));\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => (a ? a[b] : null), object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n", "html": "\n \n\n \n \n\n \n\n \n \n\n \n \n\n\n\n\n" }, + { + "name": "platform-table-initial-loading-example", + "description": "Platform Table Initial Loading", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", + "html": "\n \n\n \n\n \n\n \n\n" + }, + { + "name": "platform-table-editable-rows-example", + "description": "Platform Table Editable Rows", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", + "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" + }, { "name": "table-custom-pagination-example", "description": "Table Custom Pagination", @@ -19328,18 +19340,6 @@ "typescript": "import { ChangeDetectionStrategy, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { PlatformTableModule, TableComponent } from '@fundamental-ngx/platform/table';\nimport {\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableState,\n TableVirtualScrollDirective\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, delay, of } from 'rxjs';\n\n@Component({\n selector: 'fdp-table-custom-pagination-outer-scroll-example',\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule,\n PaginationModule\n ],\n templateUrl: './table-custom-pagination-outer-scroll-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class TableCustomPaginationOuterScrollExampleComponent implements OnInit {\n @ViewChild(TableComponent)\n table: TableComponent;\n\n source: TableDataSource;\n state: TableState;\n currentPage = 1;\n pageSize = 50;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n\n ngOnInit(): void {\n this.state = this._getDefaultState();\n }\n\n pageChanged(currentPage: number): void {\n this.currentPage = currentPage;\n this.table.setCurrentPage(this.currentPage);\n }\n\n itemsPerPageChanged(itemsPerPage: number): void {\n this.pageSize = itemsPerPage;\n this.table.setPageSize(this.pageSize, true);\n }\n\n /**\n * Simulating scroll position update. Once table is initialized app can set back preserved scrolling table\n * position so table can scroll it its original state.\n *\n * Note: Bellow scrollTopPosition property is set based on the scrolling position that was read from\n * this table example. Just some number to showcase this.\n */\n _getDefaultState(): TableState {\n return {\n columnKeys: [],\n sortBy: [],\n filterBy: [],\n groupBy: [],\n columns: [],\n searchInput: {\n category: null,\n text: ''\n },\n freezeToColumn: null,\n freezeToEndColumn: null,\n page: {\n pageSize: this.pageSize,\n currentPage: this.currentPage\n },\n scrollTopPosition: 0\n };\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n children?: ExampleItem[];\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [...ITEMS];\n totalItems = ITEMS.length;\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n this.totalItems = this.items.length;\n\n const currentPage = tableState?.page.currentPage || 1;\n const size = tableState?.page.pageSize || 50;\n const skip = (currentPage - 1) * size;\n\n const paginatedItems = this.items.slice(skip, size * currentPage);\n\n return of(paginatedItems).pipe(delay(1000));\n }\n}\n\n// Example items\nconst ITEMS: ExampleItem[] = new Array(5000).fill(null).map((_, index) => ({\n name: 'Laptops ' + index,\n price: {\n value: Math.floor(Math.random() * 1000),\n currency: 'USD'\n }\n}));\n", "html": "
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n


    \n \n \n \n\n \n\n \n\n \n\n \n \n
    \n" }, - { - "name": "platform-table-editable-rows-example", - "description": "Platform Table Editable Rows", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", - "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" - }, - { - "name": "platform-table-initial-loading-example", - "description": "Platform Table Initial Loading", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", - "html": "\n \n\n \n\n \n\n \n\n" - }, { "name": "platform-table-preserved-state-example", "description": "Platform Table Preserved State", @@ -19958,18 +19958,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { textTypeConfig } from '../config-for-examples/text-type.config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-dynamic-overflow-example',\n templateUrl: './platform-icon-tab-bar-dynamic-overflow-example.component.html',\n imports: [IconTabBarComponent, ButtonComponent]\n})\nexport class PlatformIconTabBarDynamicOverflowExampleComponent {\n items: TabConfig[] = structuredClone(textTypeConfig);\n\n /** Whether the long labels variant is active. */\n useLongLabels = false;\n\n /** Toggle tab labels between short and long text to simulate a structure change (e.g. language switch). */\n toggleLabels(): void {\n this.useLongLabels = !this.useLongLabels;\n const base = structuredClone(textTypeConfig);\n if (this.useLongLabels) {\n base.forEach((item) => {\n item.label = `Very Long Label For ${item.label} With Extra Text`;\n });\n }\n this.items = base;\n }\n\n /** Add five more tabs dynamically to force overflow. */\n addMoreTabs(): void {\n const startIndex = this.items.length;\n const extra: TabConfig[] = Array.from({ length: 5 }, (_, i) => ({\n label: `New Tab ${startIndex + i}`,\n counter: Math.floor(Math.random() * 100),\n color: null\n }));\n this.items = [...this.items, ...extra];\n }\n}\n", "html": "
    \n \n \n
    \n\n\n" }, - { - "name": "platform-icon-tab-bar-filter-type-example", - "description": "Platform Icon Tab Bar Filter Type", - "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-filter-type-example',\n templateUrl: './platform-icon-tab-bar-filter-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarFilterTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", - "html": "\n" - }, { "name": "platform-icon-tab-bar-icon-only-type-example", "description": "Platform Icon Tab Bar Icon Only Type", "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-icon-only-type-example',\n templateUrl: './platform-icon-tab-bar-icon-only-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarIconOnlyTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", "html": "\n" }, + { + "name": "platform-icon-tab-bar-filter-type-example", + "description": "Platform Icon Tab Bar Filter Type", + "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-filter-type-example',\n templateUrl: './platform-icon-tab-bar-filter-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarFilterTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", + "html": "\n" + }, { "name": "platform-icon-tab-bar-icon-type-example", "description": "Platform Icon Tab Bar Icon Type", @@ -20097,18 +20097,18 @@ "typescript": "import { Component, ViewEncapsulation } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverBodyDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-closing-example',\n templateUrl: './popover-closing-example.component.html',\n styleUrls: ['./popover-closing-example.component.scss'],\n encapsulation: ViewEncapsulation.None,\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n ButtonComponent,\n PopoverBodyHeaderDirective,\n PopoverBodyDirective,\n AvatarComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective\n ]\n})\nexport class PopoverClosingExampleComponent {}\n", "html": "
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n \n \n \n \n \n \n
    \n

    This popover stays open during router navigation.

    \n
    \n
    \n
    \n
    \n" }, - { - "name": "popover-complex-example", - "description": "Popover Complex", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-popover-complex-example',\n templateUrl: './popover-complex-example.component.html',\n styleUrls: ['./popover-complex-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonComponent,\n PopoverBodyComponent,\n TitleComponent,\n AvatarComponent,\n PopoverBodyHeaderDirective,\n ContentDensityDirective,\n PopoverBodyFooterDirective\n ]\n})\nexport class PopoverComplexExampleComponent {}\n", - "html": "
    \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n
    \n SubHeader\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n" - }, { "name": "popover-container-example", "description": "Popover Container", "typescript": "import { Component } from '@angular/core';\nimport { FocusableItemDirective } from '@fundamental-ngx/cdk';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-container-example',\n templateUrl: './popover-container-example.component.html',\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, FocusableItemDirective]\n})\nexport class PopoverContainerExampleComponent {}\n", "html": "

    appendTo

    \n

    Position the popover relative to a different element (the dashed box below).

    \n
    \n \n \n \n \n \n
    This popover is positioned relative to the container below
    \n
    \n
    \n
    \n\n
    Container (appendTo target)
    \n\n

    \n\n

    placementContainer

    \n

    \n Appends the overlay DOM element inside a container instead of body. Useful for z-index stacking contexts (e.g.,\n inside modals/dialogs). The popover still appears at the trigger, but its DOM is inside the container.\n

    \n
    \n \n \n \n \n \n
    Overlay DOM is inside the blue container
    \n
    \n
    \n (Inspect DOM to see overlay inside this container)\n
    \n" }, + { + "name": "popover-complex-example", + "description": "Popover Complex", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-popover-complex-example',\n templateUrl: './popover-complex-example.component.html',\n styleUrls: ['./popover-complex-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonComponent,\n PopoverBodyComponent,\n TitleComponent,\n AvatarComponent,\n PopoverBodyHeaderDirective,\n ContentDensityDirective,\n PopoverBodyFooterDirective\n ]\n})\nexport class PopoverComplexExampleComponent {}\n", + "html": "
    \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n
    \n SubHeader\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, { "name": "popover-dialog-example", "description": "Popover Dialog", @@ -20132,12 +20132,6 @@ "typescript": "import { Component, signal } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverComponent,\n PopoverContainerDirective,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-dynamic-container-height-example',\n templateUrl: './popover-dynamic-container-height-example.component.html',\n styles: [\n `\n .fd-docs-flex-display-helper {\n display: flex;\n align-items: center;\n justify-content: space-around;\n flex-flow: row wrap;\n width: 100%;\n }\n `\n ],\n imports: [\n PopoverContainerDirective,\n ButtonComponent,\n PopoverComponent,\n PopoverControlComponent,\n AvatarComponent,\n PopoverBodyComponent\n ]\n})\nexport class PopoverDynamicContainerHeightExampleComponent {\n showOverflowContainer = signal(false);\n\n private _overflowContainerTimeout: ReturnType | null = null;\n\n resetOverflowContainer(): void {\n if (this._overflowContainerTimeout) {\n clearTimeout(this._overflowContainerTimeout);\n }\n this.showOverflowContainer.set(false);\n this._overflowContainerTimeout = setTimeout(() => {\n this.showOverflowContainer.set(true);\n }, 2000);\n }\n}\n", "html": "
    \n @if (showOverflowContainer()) {\n
    \n }\n \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" }, - { - "name": "popover-focus-example", - "description": "Popover Focus", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-focus-example',\n templateUrl: './popover-focus-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n PopoverBodyHeaderDirective,\n BarModule,\n AvatarComponent,\n PopoverBodyFooterDirective,\n ContentDensityDirective\n ]\n})\nexport class PopoverFocusExampleComponent {}\n", - "html": "

    Focus Trapped & Auto Capture (default behavior)

    \n\n \n \n \n \n
    \n
    \n
    \n \n Header\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n

    \n\n

    Focus NOT Auto Captured

    \n\n \n \n \n \n
    \n

    Focus is not automatically moved to this popover when opened.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Restore Focus On Close (default: true)

    \n\n \n \n \n \n
    \n

    When closed, focus returns to the trigger button.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Do NOT Restore Focus On Close

    \n\n \n \n \n \n
    \n

    When closed, focus does NOT return to the trigger.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Prevent Space Key Scroll (default: true)

    \n

    \n By default, pressing Space on the trigger prevents page scrolling. Set\n [preventSpaceKeyScroll]=\"false\" to allow normal scroll behavior.\n

    \n\n \n \n \n \n
    \n

    When this popover's trigger is focused, pressing Space allows page scroll.

    \n
    \n
    \n
    \n" - }, { "name": "popover-inside-popover-example", "description": "Popover Inside Popover", @@ -20149,6 +20143,12 @@ "description": "Popover Lazy Init Of Body", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyDirective,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { PopoverLazyLoadedBodyComponent } from './popover-lazy-loaded-body.component';\n\n@Component({\n selector: 'fd-popover-lazy-init-of-body-example',\n template: `\n \n \n \n \n \n

    Header

    \n \n
    Footer
    \n
    \n
    \n `,\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyDirective,\n PopoverBodyHeaderDirective,\n PopoverBodyFooterDirective,\n ButtonComponent,\n PopoverLazyLoadedBodyComponent\n ]\n})\nexport class PopoverLazyInitOfBodyExampleComponent {}\n" }, + { + "name": "popover-focus-example", + "description": "Popover Focus", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-focus-example',\n templateUrl: './popover-focus-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n PopoverBodyHeaderDirective,\n BarModule,\n AvatarComponent,\n PopoverBodyFooterDirective,\n ContentDensityDirective\n ]\n})\nexport class PopoverFocusExampleComponent {}\n", + "html": "

    Focus Trapped & Auto Capture (default behavior)

    \n\n \n \n \n \n
    \n
    \n
    \n \n Header\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n

    \n\n

    Focus NOT Auto Captured

    \n\n \n \n \n \n
    \n

    Focus is not automatically moved to this popover when opened.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Restore Focus On Close (default: true)

    \n\n \n \n \n \n
    \n

    When closed, focus returns to the trigger button.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Do NOT Restore Focus On Close

    \n\n \n \n \n \n
    \n

    When closed, focus does NOT return to the trigger.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Prevent Space Key Scroll (default: true)

    \n

    \n By default, pressing Space on the trigger prevents page scrolling. Set\n [preventSpaceKeyScroll]=\"false\" to allow normal scroll behavior.\n

    \n\n \n \n \n \n
    \n

    When this popover's trigger is focused, pressing Space allows page scroll.

    \n
    \n
    \n
    \n" + }, { "name": "popover-mobile-example", "description": "Popover Mobile", @@ -20161,30 +20161,30 @@ "typescript": "import { ConnectionPositionPair } from '@angular/cdk/overlay';\nimport { Component, signal, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport { XPositions, YPositions } from '@fundamental-ngx/core/shared';\n\n@Component({\n selector: 'fd-popover-cdk-placement-example',\n templateUrl: './popover-cdk-placement-example.component.html',\n imports: [\n FormLabelComponent,\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent\n ]\n})\nexport class PopoverCdkPlacementExampleComponent {\n readonly popover = viewChild(PopoverComponent);\n\n readonly yPositions: YPositions[] = ['bottom', 'center', 'top'];\n readonly xPositions: XPositions[] = ['start', 'center', 'end'];\n\n originX = signal('center');\n originY = signal('center');\n overlayX = signal('center');\n overlayY = signal('center');\n\n cdkPosition = signal(this._buildCdkPositionObject());\n\n refresh(): void {\n this.cdkPosition.set(this._buildCdkPositionObject());\n this.popover()?.applyNewPosition(this.cdkPosition());\n }\n\n private _buildCdkPositionObject(): ConnectionPositionPair[] {\n return [\n {\n originX: this.originX(),\n originY: this.originY(),\n overlayX: this.overlayX(),\n overlayY: this.overlayY()\n }\n ];\n }\n}\n", "html": "
    \n \n \n @for (option of xPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of yPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of xPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of yPositions; track option) {\n \n }\n \n
    \n

    \n\n \n \n \n \n \n \n \n \n\n" }, - { - "name": "popover-placement-example", - "description": "Popover Placement", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-placement-example',\n templateUrl: './popover-placement-example.component.html',\n styleUrls: ['popover-placement-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, AvatarComponent]\n})\nexport class PopoverPlacementExampleComponent {}\n", - "html": "
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" - }, { "name": "popover-programmatic-open-example", "description": "Popover Programmatic Open", "typescript": "import { JsonPipe } from '@angular/common';\nimport { Component, signal } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverComponent,\n PopoverConfig,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-programmatic-open-example',\n templateUrl: './popover-programmatic-open-example.component.html',\n styleUrls: ['popover-programmatic-open-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n AvatarComponent,\n PopoverBodyComponent,\n ButtonComponent,\n JsonPipe\n ]\n})\nexport class PopoverProgrammaticOpenExampleComponent {\n /** Signal-based open state for two-way binding */\n isOpen = signal(false);\n\n /** Disabled state for the popover */\n isDisabled = signal(false);\n\n /** Config object example - can be used instead of individual inputs */\n popoverConfig: PopoverConfig = {\n placement: 'bottom-start',\n noArrow: false,\n closeOnEscapeKey: true,\n focusTrapped: true\n };\n\n /** Track open/close events */\n eventLog = signal([]);\n\n /** Called before popover opens */\n onBeforeOpen(): void {\n this.addToLog('beforeOpen event fired');\n }\n\n /** Called when open state changes */\n onOpenChange(isOpen: boolean): void {\n this.addToLog(`isOpenChange: ${isOpen}`);\n }\n\n /** Toggle disabled state */\n toggleDisabled(): void {\n this.isDisabled.update((v) => !v);\n this.addToLog(`Popover ${this.isDisabled() ? 'disabled' : 'enabled'}`);\n }\n\n /** Clear event log */\n clearLog(): void {\n this.eventLog.set([]);\n }\n\n private addToLog(message: string): void {\n this.eventLog.update((log) => [...log, `${new Date().toLocaleTimeString()}: ${message}`]);\n }\n}\n", "html": "\n

    Signal-based Programmatic Control

    \n
    \n \n \n \n \n \n \n \n \n \n \n \n
    \n\n\n

    Using Config Object

    \n\n \n \n \n \n
    \n

    This popover uses the [config] input:

    \n
    {{ popoverConfig | json }}
    \n
    \n
    \n
    \n\n\n

    Event Log

    \n
    \n @if (eventLog().length === 0) {\n

    No events yet. Open the popover to see events.

    \n } @else {\n
      \n @for (event of eventLog(); track event) {\n
    • {{ event }}
    • \n }\n
    \n \n }\n
    \n" }, + { + "name": "popover-non-dialog-example", + "description": "Popover Non Dialog", + "typescript": "import { Component } from '@angular/core';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-non-dialog-example',\n templateUrl: './popover-non-dialog-example.component.html',\n imports: [PopoverModule]\n})\nexport class PopoverNonDialogExampleComponent {}\n", + "html": "

    \n Use [bodyRole]=\"region\" (or null) when the popover is a non-modal disclosure rather than a\n dialog. Match the role to the popover's actual ARIA semantics.\n

    \n\n\n \n \n \n \n
    \n

    Quick Filters

    \n \n \n
    \n
    \n
    \n" + }, + { + "name": "popover-placement-example", + "description": "Popover Placement", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-placement-example',\n templateUrl: './popover-placement-example.component.html',\n styleUrls: ['popover-placement-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, AvatarComponent]\n})\nexport class PopoverPlacementExampleComponent {}\n", + "html": "
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" + }, { "name": "popover-resizable-example", "description": "Popover Resizable", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-resizable-example',\n templateUrl: './popover-resizable-example.component.html',\n styleUrls: ['popover-resizable-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent]\n})\nexport class PopoverResizableExampleComponent {}\n", "html": "
    \n \n \n \n \n\n \n
    \n

    Resizable content area

    \n

    \n Drag the resize handle to make room for longer content, tables, previews, or forms while keeping the\n popover within its configured limits.\n

    \n \n
    \n
    \n
    \n
    \n" }, - { - "name": "popover-scroll-example", - "description": "Popover Scroll", - "typescript": "import { Overlay, ScrollStrategy } from '@angular/cdk/overlay';\nimport { Component, inject } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-scroll-example',\n templateUrl: './popover-scroll-example.component.html',\n styleUrls: ['./popover-scroll-example.component.scss'],\n imports: [\n FormLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class PopoverScrollExampleComponent {\n /** Do nothing on scroll. */\n noopScrollStrategy: ScrollStrategy;\n\n /**\n * Close the overlay as soon as the user scrolls.\n * @param config Configuration to be used inside the scroll strategy.\n */\n closeScrollStrategy: ScrollStrategy;\n\n /** Block scrolling. */\n blockScrollStrategy: ScrollStrategy;\n\n /** Whether to close the overlay once the user has scrolled away completely. */\n autoClose = false;\n\n /** Time in milliseconds to throttle the scroll events. Use to increase performance. */\n scrollThrottle = 0;\n\n /**\n * Update the overlay's position on scroll.\n * @param config Configuration to be used inside the scroll strategy.\n * Allows debouncing the reposition calls.\n */\n repositionScrollStrategy: ScrollStrategy;\n\n private readonly _overlay = inject(Overlay);\n\n constructor() {\n this.noopScrollStrategy = this._overlay.scrollStrategies.noop();\n this.closeScrollStrategy = this._overlay.scrollStrategies.close();\n this.blockScrollStrategy = this._overlay.scrollStrategies.block();\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n\n refreshRepositionScrollStrategy(): void {\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n}\n", - "html": "\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n Close the overlay once the user has scrolled away completely?\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n" - }, { "name": "popover-example", "description": "Popover", @@ -20196,6 +20196,12 @@ "description": "Popover Trigger", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverComponent, PopoverTriggerDirective } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-trigger-example',\n templateUrl: './popover-trigger-example.component.html',\n imports: [ButtonComponent, PopoverTriggerDirective, PopoverComponent]\n})\nexport class PopoverTriggerExampleComponent {}\n", "html": "\n\n\n
    This popover is connected to trigger element
    \n
    \n" + }, + { + "name": "popover-scroll-example", + "description": "Popover Scroll", + "typescript": "import { Overlay, ScrollStrategy } from '@angular/cdk/overlay';\nimport { Component, inject } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-scroll-example',\n templateUrl: './popover-scroll-example.component.html',\n styleUrls: ['./popover-scroll-example.component.scss'],\n imports: [\n FormLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class PopoverScrollExampleComponent {\n /** Do nothing on scroll. */\n noopScrollStrategy: ScrollStrategy;\n\n /**\n * Close the overlay as soon as the user scrolls.\n * @param config Configuration to be used inside the scroll strategy.\n */\n closeScrollStrategy: ScrollStrategy;\n\n /** Block scrolling. */\n blockScrollStrategy: ScrollStrategy;\n\n /** Whether to close the overlay once the user has scrolled away completely. */\n autoClose = false;\n\n /** Time in milliseconds to throttle the scroll events. Use to increase performance. */\n scrollThrottle = 0;\n\n /**\n * Update the overlay's position on scroll.\n * @param config Configuration to be used inside the scroll strategy.\n * Allows debouncing the reposition calls.\n */\n repositionScrollStrategy: ScrollStrategy;\n\n private readonly _overlay = inject(Overlay);\n\n constructor() {\n this.noopScrollStrategy = this._overlay.scrollStrategies.noop();\n this.closeScrollStrategy = this._overlay.scrollStrategies.close();\n this.blockScrollStrategy = this._overlay.scrollStrategies.block();\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n\n refreshRepositionScrollStrategy(): void {\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n}\n", + "html": "\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n Close the overlay once the user has scrolled away completely?\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n" } ] }, @@ -20219,18 +20225,18 @@ "typescript": "import { Component, ViewEncapsulation } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverBodyDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-closing-example',\n templateUrl: './popover-closing-example.component.html',\n styleUrls: ['./popover-closing-example.component.scss'],\n encapsulation: ViewEncapsulation.None,\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n ButtonComponent,\n PopoverBodyHeaderDirective,\n PopoverBodyDirective,\n AvatarComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective\n ]\n})\nexport class PopoverClosingExampleComponent {}\n", "html": "
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n \n \n \n \n \n \n
    \n

    This popover stays open during router navigation.

    \n
    \n
    \n
    \n
    \n" }, - { - "name": "popover-complex-example", - "description": "Popover Complex", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-popover-complex-example',\n templateUrl: './popover-complex-example.component.html',\n styleUrls: ['./popover-complex-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonComponent,\n PopoverBodyComponent,\n TitleComponent,\n AvatarComponent,\n PopoverBodyHeaderDirective,\n ContentDensityDirective,\n PopoverBodyFooterDirective\n ]\n})\nexport class PopoverComplexExampleComponent {}\n", - "html": "
    \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n
    \n SubHeader\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n" - }, { "name": "popover-container-example", "description": "Popover Container", "typescript": "import { Component } from '@angular/core';\nimport { FocusableItemDirective } from '@fundamental-ngx/cdk';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-container-example',\n templateUrl: './popover-container-example.component.html',\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, FocusableItemDirective]\n})\nexport class PopoverContainerExampleComponent {}\n", "html": "

    appendTo

    \n

    Position the popover relative to a different element (the dashed box below).

    \n
    \n \n \n \n \n \n
    This popover is positioned relative to the container below
    \n
    \n
    \n
    \n\n
    Container (appendTo target)
    \n\n

    \n\n

    placementContainer

    \n

    \n Appends the overlay DOM element inside a container instead of body. Useful for z-index stacking contexts (e.g.,\n inside modals/dialogs). The popover still appears at the trigger, but its DOM is inside the container.\n

    \n
    \n \n \n \n \n \n
    Overlay DOM is inside the blue container
    \n
    \n
    \n (Inspect DOM to see overlay inside this container)\n
    \n" }, + { + "name": "popover-complex-example", + "description": "Popover Complex", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-popover-complex-example',\n templateUrl: './popover-complex-example.component.html',\n styleUrls: ['./popover-complex-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonComponent,\n PopoverBodyComponent,\n TitleComponent,\n AvatarComponent,\n PopoverBodyHeaderDirective,\n ContentDensityDirective,\n PopoverBodyFooterDirective\n ]\n})\nexport class PopoverComplexExampleComponent {}\n", + "html": "
    \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n
    \n SubHeader\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, { "name": "popover-dialog-example", "description": "Popover Dialog", @@ -20254,12 +20260,6 @@ "typescript": "import { Component, signal } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverComponent,\n PopoverContainerDirective,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-dynamic-container-height-example',\n templateUrl: './popover-dynamic-container-height-example.component.html',\n styles: [\n `\n .fd-docs-flex-display-helper {\n display: flex;\n align-items: center;\n justify-content: space-around;\n flex-flow: row wrap;\n width: 100%;\n }\n `\n ],\n imports: [\n PopoverContainerDirective,\n ButtonComponent,\n PopoverComponent,\n PopoverControlComponent,\n AvatarComponent,\n PopoverBodyComponent\n ]\n})\nexport class PopoverDynamicContainerHeightExampleComponent {\n showOverflowContainer = signal(false);\n\n private _overflowContainerTimeout: ReturnType | null = null;\n\n resetOverflowContainer(): void {\n if (this._overflowContainerTimeout) {\n clearTimeout(this._overflowContainerTimeout);\n }\n this.showOverflowContainer.set(false);\n this._overflowContainerTimeout = setTimeout(() => {\n this.showOverflowContainer.set(true);\n }, 2000);\n }\n}\n", "html": "
    \n @if (showOverflowContainer()) {\n
    \n }\n \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" }, - { - "name": "popover-focus-example", - "description": "Popover Focus", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-focus-example',\n templateUrl: './popover-focus-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n PopoverBodyHeaderDirective,\n BarModule,\n AvatarComponent,\n PopoverBodyFooterDirective,\n ContentDensityDirective\n ]\n})\nexport class PopoverFocusExampleComponent {}\n", - "html": "

    Focus Trapped & Auto Capture (default behavior)

    \n\n \n \n \n \n
    \n
    \n
    \n \n Header\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n

    \n\n

    Focus NOT Auto Captured

    \n\n \n \n \n \n
    \n

    Focus is not automatically moved to this popover when opened.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Restore Focus On Close (default: true)

    \n\n \n \n \n \n
    \n

    When closed, focus returns to the trigger button.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Do NOT Restore Focus On Close

    \n\n \n \n \n \n
    \n

    When closed, focus does NOT return to the trigger.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Prevent Space Key Scroll (default: true)

    \n

    \n By default, pressing Space on the trigger prevents page scrolling. Set\n [preventSpaceKeyScroll]=\"false\" to allow normal scroll behavior.\n

    \n\n \n \n \n \n
    \n

    When this popover's trigger is focused, pressing Space allows page scroll.

    \n
    \n
    \n
    \n" - }, { "name": "popover-inside-popover-example", "description": "Popover Inside Popover", @@ -20271,6 +20271,12 @@ "description": "Popover Lazy Init Of Body", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyDirective,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { PopoverLazyLoadedBodyComponent } from './popover-lazy-loaded-body.component';\n\n@Component({\n selector: 'fd-popover-lazy-init-of-body-example',\n template: `\n \n \n \n \n \n

    Header

    \n \n
    Footer
    \n
    \n
    \n `,\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyDirective,\n PopoverBodyHeaderDirective,\n PopoverBodyFooterDirective,\n ButtonComponent,\n PopoverLazyLoadedBodyComponent\n ]\n})\nexport class PopoverLazyInitOfBodyExampleComponent {}\n" }, + { + "name": "popover-focus-example", + "description": "Popover Focus", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-focus-example',\n templateUrl: './popover-focus-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n PopoverBodyHeaderDirective,\n BarModule,\n AvatarComponent,\n PopoverBodyFooterDirective,\n ContentDensityDirective\n ]\n})\nexport class PopoverFocusExampleComponent {}\n", + "html": "

    Focus Trapped & Auto Capture (default behavior)

    \n\n \n \n \n \n
    \n
    \n
    \n \n Header\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n

    \n\n

    Focus NOT Auto Captured

    \n\n \n \n \n \n
    \n

    Focus is not automatically moved to this popover when opened.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Restore Focus On Close (default: true)

    \n\n \n \n \n \n
    \n

    When closed, focus returns to the trigger button.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Do NOT Restore Focus On Close

    \n\n \n \n \n \n
    \n

    When closed, focus does NOT return to the trigger.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Prevent Space Key Scroll (default: true)

    \n

    \n By default, pressing Space on the trigger prevents page scrolling. Set\n [preventSpaceKeyScroll]=\"false\" to allow normal scroll behavior.\n

    \n\n \n \n \n \n
    \n

    When this popover's trigger is focused, pressing Space allows page scroll.

    \n
    \n
    \n
    \n" + }, { "name": "popover-mobile-example", "description": "Popover Mobile", @@ -20283,30 +20289,30 @@ "typescript": "import { ConnectionPositionPair } from '@angular/cdk/overlay';\nimport { Component, signal, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport { XPositions, YPositions } from '@fundamental-ngx/core/shared';\n\n@Component({\n selector: 'fd-popover-cdk-placement-example',\n templateUrl: './popover-cdk-placement-example.component.html',\n imports: [\n FormLabelComponent,\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent\n ]\n})\nexport class PopoverCdkPlacementExampleComponent {\n readonly popover = viewChild(PopoverComponent);\n\n readonly yPositions: YPositions[] = ['bottom', 'center', 'top'];\n readonly xPositions: XPositions[] = ['start', 'center', 'end'];\n\n originX = signal('center');\n originY = signal('center');\n overlayX = signal('center');\n overlayY = signal('center');\n\n cdkPosition = signal(this._buildCdkPositionObject());\n\n refresh(): void {\n this.cdkPosition.set(this._buildCdkPositionObject());\n this.popover()?.applyNewPosition(this.cdkPosition());\n }\n\n private _buildCdkPositionObject(): ConnectionPositionPair[] {\n return [\n {\n originX: this.originX(),\n originY: this.originY(),\n overlayX: this.overlayX(),\n overlayY: this.overlayY()\n }\n ];\n }\n}\n", "html": "
    \n \n \n @for (option of xPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of yPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of xPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of yPositions; track option) {\n \n }\n \n
    \n

    \n\n \n \n \n \n \n \n \n \n\n" }, - { - "name": "popover-placement-example", - "description": "Popover Placement", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-placement-example',\n templateUrl: './popover-placement-example.component.html',\n styleUrls: ['popover-placement-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, AvatarComponent]\n})\nexport class PopoverPlacementExampleComponent {}\n", - "html": "
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" - }, { "name": "popover-programmatic-open-example", "description": "Popover Programmatic Open", "typescript": "import { JsonPipe } from '@angular/common';\nimport { Component, signal } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverComponent,\n PopoverConfig,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-programmatic-open-example',\n templateUrl: './popover-programmatic-open-example.component.html',\n styleUrls: ['popover-programmatic-open-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n AvatarComponent,\n PopoverBodyComponent,\n ButtonComponent,\n JsonPipe\n ]\n})\nexport class PopoverProgrammaticOpenExampleComponent {\n /** Signal-based open state for two-way binding */\n isOpen = signal(false);\n\n /** Disabled state for the popover */\n isDisabled = signal(false);\n\n /** Config object example - can be used instead of individual inputs */\n popoverConfig: PopoverConfig = {\n placement: 'bottom-start',\n noArrow: false,\n closeOnEscapeKey: true,\n focusTrapped: true\n };\n\n /** Track open/close events */\n eventLog = signal([]);\n\n /** Called before popover opens */\n onBeforeOpen(): void {\n this.addToLog('beforeOpen event fired');\n }\n\n /** Called when open state changes */\n onOpenChange(isOpen: boolean): void {\n this.addToLog(`isOpenChange: ${isOpen}`);\n }\n\n /** Toggle disabled state */\n toggleDisabled(): void {\n this.isDisabled.update((v) => !v);\n this.addToLog(`Popover ${this.isDisabled() ? 'disabled' : 'enabled'}`);\n }\n\n /** Clear event log */\n clearLog(): void {\n this.eventLog.set([]);\n }\n\n private addToLog(message: string): void {\n this.eventLog.update((log) => [...log, `${new Date().toLocaleTimeString()}: ${message}`]);\n }\n}\n", "html": "\n

    Signal-based Programmatic Control

    \n
    \n \n \n \n \n \n \n \n \n \n \n \n
    \n\n\n

    Using Config Object

    \n\n \n \n \n \n
    \n

    This popover uses the [config] input:

    \n
    {{ popoverConfig | json }}
    \n
    \n
    \n
    \n\n\n

    Event Log

    \n
    \n @if (eventLog().length === 0) {\n

    No events yet. Open the popover to see events.

    \n } @else {\n
      \n @for (event of eventLog(); track event) {\n
    • {{ event }}
    • \n }\n
    \n \n }\n
    \n" }, + { + "name": "popover-non-dialog-example", + "description": "Popover Non Dialog", + "typescript": "import { Component } from '@angular/core';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-non-dialog-example',\n templateUrl: './popover-non-dialog-example.component.html',\n imports: [PopoverModule]\n})\nexport class PopoverNonDialogExampleComponent {}\n", + "html": "

    \n Use [bodyRole]=\"region\" (or null) when the popover is a non-modal disclosure rather than a\n dialog. Match the role to the popover's actual ARIA semantics.\n

    \n\n\n \n \n \n \n
    \n

    Quick Filters

    \n \n \n
    \n
    \n
    \n" + }, + { + "name": "popover-placement-example", + "description": "Popover Placement", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-placement-example',\n templateUrl: './popover-placement-example.component.html',\n styleUrls: ['popover-placement-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, AvatarComponent]\n})\nexport class PopoverPlacementExampleComponent {}\n", + "html": "
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" + }, { "name": "popover-resizable-example", "description": "Popover Resizable", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-resizable-example',\n templateUrl: './popover-resizable-example.component.html',\n styleUrls: ['popover-resizable-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent]\n})\nexport class PopoverResizableExampleComponent {}\n", "html": "
    \n \n \n \n \n\n \n
    \n

    Resizable content area

    \n

    \n Drag the resize handle to make room for longer content, tables, previews, or forms while keeping the\n popover within its configured limits.\n

    \n \n
    \n
    \n
    \n
    \n" }, - { - "name": "popover-scroll-example", - "description": "Popover Scroll", - "typescript": "import { Overlay, ScrollStrategy } from '@angular/cdk/overlay';\nimport { Component, inject } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-scroll-example',\n templateUrl: './popover-scroll-example.component.html',\n styleUrls: ['./popover-scroll-example.component.scss'],\n imports: [\n FormLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class PopoverScrollExampleComponent {\n /** Do nothing on scroll. */\n noopScrollStrategy: ScrollStrategy;\n\n /**\n * Close the overlay as soon as the user scrolls.\n * @param config Configuration to be used inside the scroll strategy.\n */\n closeScrollStrategy: ScrollStrategy;\n\n /** Block scrolling. */\n blockScrollStrategy: ScrollStrategy;\n\n /** Whether to close the overlay once the user has scrolled away completely. */\n autoClose = false;\n\n /** Time in milliseconds to throttle the scroll events. Use to increase performance. */\n scrollThrottle = 0;\n\n /**\n * Update the overlay's position on scroll.\n * @param config Configuration to be used inside the scroll strategy.\n * Allows debouncing the reposition calls.\n */\n repositionScrollStrategy: ScrollStrategy;\n\n private readonly _overlay = inject(Overlay);\n\n constructor() {\n this.noopScrollStrategy = this._overlay.scrollStrategies.noop();\n this.closeScrollStrategy = this._overlay.scrollStrategies.close();\n this.blockScrollStrategy = this._overlay.scrollStrategies.block();\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n\n refreshRepositionScrollStrategy(): void {\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n}\n", - "html": "\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n Close the overlay once the user has scrolled away completely?\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n" - }, { "name": "popover-example", "description": "Popover", @@ -20318,6 +20324,12 @@ "description": "Popover Trigger", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverComponent, PopoverTriggerDirective } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-trigger-example',\n templateUrl: './popover-trigger-example.component.html',\n imports: [ButtonComponent, PopoverTriggerDirective, PopoverComponent]\n})\nexport class PopoverTriggerExampleComponent {}\n", "html": "\n\n\n
    This popover is connected to trigger element
    \n
    \n" + }, + { + "name": "popover-scroll-example", + "description": "Popover Scroll", + "typescript": "import { Overlay, ScrollStrategy } from '@angular/cdk/overlay';\nimport { Component, inject } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-scroll-example',\n templateUrl: './popover-scroll-example.component.html',\n styleUrls: ['./popover-scroll-example.component.scss'],\n imports: [\n FormLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class PopoverScrollExampleComponent {\n /** Do nothing on scroll. */\n noopScrollStrategy: ScrollStrategy;\n\n /**\n * Close the overlay as soon as the user scrolls.\n * @param config Configuration to be used inside the scroll strategy.\n */\n closeScrollStrategy: ScrollStrategy;\n\n /** Block scrolling. */\n blockScrollStrategy: ScrollStrategy;\n\n /** Whether to close the overlay once the user has scrolled away completely. */\n autoClose = false;\n\n /** Time in milliseconds to throttle the scroll events. Use to increase performance. */\n scrollThrottle = 0;\n\n /**\n * Update the overlay's position on scroll.\n * @param config Configuration to be used inside the scroll strategy.\n * Allows debouncing the reposition calls.\n */\n repositionScrollStrategy: ScrollStrategy;\n\n private readonly _overlay = inject(Overlay);\n\n constructor() {\n this.noopScrollStrategy = this._overlay.scrollStrategies.noop();\n this.closeScrollStrategy = this._overlay.scrollStrategies.close();\n this.blockScrollStrategy = this._overlay.scrollStrategies.block();\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n\n refreshRepositionScrollStrategy(): void {\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n}\n", + "html": "\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n Close the overlay once the user has scrolled away completely?\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n" } ] }, @@ -20341,18 +20353,18 @@ "typescript": "import { Component, ViewEncapsulation } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverBodyDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-closing-example',\n templateUrl: './popover-closing-example.component.html',\n styleUrls: ['./popover-closing-example.component.scss'],\n encapsulation: ViewEncapsulation.None,\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n ButtonComponent,\n PopoverBodyHeaderDirective,\n PopoverBodyDirective,\n AvatarComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective\n ]\n})\nexport class PopoverClosingExampleComponent {}\n", "html": "
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n \n \n \n \n \n \n
    \n

    This popover stays open during router navigation.

    \n
    \n
    \n
    \n
    \n" }, - { - "name": "popover-complex-example", - "description": "Popover Complex", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-popover-complex-example',\n templateUrl: './popover-complex-example.component.html',\n styleUrls: ['./popover-complex-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonComponent,\n PopoverBodyComponent,\n TitleComponent,\n AvatarComponent,\n PopoverBodyHeaderDirective,\n ContentDensityDirective,\n PopoverBodyFooterDirective\n ]\n})\nexport class PopoverComplexExampleComponent {}\n", - "html": "
    \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n
    \n SubHeader\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n" - }, { "name": "popover-container-example", "description": "Popover Container", "typescript": "import { Component } from '@angular/core';\nimport { FocusableItemDirective } from '@fundamental-ngx/cdk';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-container-example',\n templateUrl: './popover-container-example.component.html',\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, FocusableItemDirective]\n})\nexport class PopoverContainerExampleComponent {}\n", "html": "

    appendTo

    \n

    Position the popover relative to a different element (the dashed box below).

    \n
    \n \n \n \n \n \n
    This popover is positioned relative to the container below
    \n
    \n
    \n
    \n\n
    Container (appendTo target)
    \n\n

    \n\n

    placementContainer

    \n

    \n Appends the overlay DOM element inside a container instead of body. Useful for z-index stacking contexts (e.g.,\n inside modals/dialogs). The popover still appears at the trigger, but its DOM is inside the container.\n

    \n
    \n \n \n \n \n \n
    Overlay DOM is inside the blue container
    \n
    \n
    \n (Inspect DOM to see overlay inside this container)\n
    \n" }, + { + "name": "popover-complex-example", + "description": "Popover Complex", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-popover-complex-example',\n templateUrl: './popover-complex-example.component.html',\n styleUrls: ['./popover-complex-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonComponent,\n PopoverBodyComponent,\n TitleComponent,\n AvatarComponent,\n PopoverBodyHeaderDirective,\n ContentDensityDirective,\n PopoverBodyFooterDirective\n ]\n})\nexport class PopoverComplexExampleComponent {}\n", + "html": "
    \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n
    \n SubHeader\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, { "name": "popover-dialog-example", "description": "Popover Dialog", @@ -20376,12 +20388,6 @@ "typescript": "import { Component, signal } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverComponent,\n PopoverContainerDirective,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-dynamic-container-height-example',\n templateUrl: './popover-dynamic-container-height-example.component.html',\n styles: [\n `\n .fd-docs-flex-display-helper {\n display: flex;\n align-items: center;\n justify-content: space-around;\n flex-flow: row wrap;\n width: 100%;\n }\n `\n ],\n imports: [\n PopoverContainerDirective,\n ButtonComponent,\n PopoverComponent,\n PopoverControlComponent,\n AvatarComponent,\n PopoverBodyComponent\n ]\n})\nexport class PopoverDynamicContainerHeightExampleComponent {\n showOverflowContainer = signal(false);\n\n private _overflowContainerTimeout: ReturnType | null = null;\n\n resetOverflowContainer(): void {\n if (this._overflowContainerTimeout) {\n clearTimeout(this._overflowContainerTimeout);\n }\n this.showOverflowContainer.set(false);\n this._overflowContainerTimeout = setTimeout(() => {\n this.showOverflowContainer.set(true);\n }, 2000);\n }\n}\n", "html": "
    \n @if (showOverflowContainer()) {\n
    \n }\n \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" }, - { - "name": "popover-focus-example", - "description": "Popover Focus", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-focus-example',\n templateUrl: './popover-focus-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n PopoverBodyHeaderDirective,\n BarModule,\n AvatarComponent,\n PopoverBodyFooterDirective,\n ContentDensityDirective\n ]\n})\nexport class PopoverFocusExampleComponent {}\n", - "html": "

    Focus Trapped & Auto Capture (default behavior)

    \n\n \n \n \n \n
    \n
    \n
    \n \n Header\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n

    \n\n

    Focus NOT Auto Captured

    \n\n \n \n \n \n
    \n

    Focus is not automatically moved to this popover when opened.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Restore Focus On Close (default: true)

    \n\n \n \n \n \n
    \n

    When closed, focus returns to the trigger button.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Do NOT Restore Focus On Close

    \n\n \n \n \n \n
    \n

    When closed, focus does NOT return to the trigger.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Prevent Space Key Scroll (default: true)

    \n

    \n By default, pressing Space on the trigger prevents page scrolling. Set\n [preventSpaceKeyScroll]=\"false\" to allow normal scroll behavior.\n

    \n\n \n \n \n \n
    \n

    When this popover's trigger is focused, pressing Space allows page scroll.

    \n
    \n
    \n
    \n" - }, { "name": "popover-inside-popover-example", "description": "Popover Inside Popover", @@ -20393,6 +20399,12 @@ "description": "Popover Lazy Init Of Body", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyDirective,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { PopoverLazyLoadedBodyComponent } from './popover-lazy-loaded-body.component';\n\n@Component({\n selector: 'fd-popover-lazy-init-of-body-example',\n template: `\n \n \n \n \n \n

    Header

    \n \n
    Footer
    \n
    \n
    \n `,\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyDirective,\n PopoverBodyHeaderDirective,\n PopoverBodyFooterDirective,\n ButtonComponent,\n PopoverLazyLoadedBodyComponent\n ]\n})\nexport class PopoverLazyInitOfBodyExampleComponent {}\n" }, + { + "name": "popover-focus-example", + "description": "Popover Focus", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-focus-example',\n templateUrl: './popover-focus-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n PopoverBodyHeaderDirective,\n BarModule,\n AvatarComponent,\n PopoverBodyFooterDirective,\n ContentDensityDirective\n ]\n})\nexport class PopoverFocusExampleComponent {}\n", + "html": "

    Focus Trapped & Auto Capture (default behavior)

    \n\n \n \n \n \n
    \n
    \n
    \n \n Header\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n

    \n\n

    Focus NOT Auto Captured

    \n\n \n \n \n \n
    \n

    Focus is not automatically moved to this popover when opened.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Restore Focus On Close (default: true)

    \n\n \n \n \n \n
    \n

    When closed, focus returns to the trigger button.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Do NOT Restore Focus On Close

    \n\n \n \n \n \n
    \n

    When closed, focus does NOT return to the trigger.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Prevent Space Key Scroll (default: true)

    \n

    \n By default, pressing Space on the trigger prevents page scrolling. Set\n [preventSpaceKeyScroll]=\"false\" to allow normal scroll behavior.\n

    \n\n \n \n \n \n
    \n

    When this popover's trigger is focused, pressing Space allows page scroll.

    \n
    \n
    \n
    \n" + }, { "name": "popover-mobile-example", "description": "Popover Mobile", @@ -20405,30 +20417,30 @@ "typescript": "import { ConnectionPositionPair } from '@angular/cdk/overlay';\nimport { Component, signal, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport { XPositions, YPositions } from '@fundamental-ngx/core/shared';\n\n@Component({\n selector: 'fd-popover-cdk-placement-example',\n templateUrl: './popover-cdk-placement-example.component.html',\n imports: [\n FormLabelComponent,\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent\n ]\n})\nexport class PopoverCdkPlacementExampleComponent {\n readonly popover = viewChild(PopoverComponent);\n\n readonly yPositions: YPositions[] = ['bottom', 'center', 'top'];\n readonly xPositions: XPositions[] = ['start', 'center', 'end'];\n\n originX = signal('center');\n originY = signal('center');\n overlayX = signal('center');\n overlayY = signal('center');\n\n cdkPosition = signal(this._buildCdkPositionObject());\n\n refresh(): void {\n this.cdkPosition.set(this._buildCdkPositionObject());\n this.popover()?.applyNewPosition(this.cdkPosition());\n }\n\n private _buildCdkPositionObject(): ConnectionPositionPair[] {\n return [\n {\n originX: this.originX(),\n originY: this.originY(),\n overlayX: this.overlayX(),\n overlayY: this.overlayY()\n }\n ];\n }\n}\n", "html": "
    \n \n \n @for (option of xPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of yPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of xPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of yPositions; track option) {\n \n }\n \n
    \n

    \n\n \n \n \n \n \n \n \n \n\n" }, - { - "name": "popover-placement-example", - "description": "Popover Placement", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-placement-example',\n templateUrl: './popover-placement-example.component.html',\n styleUrls: ['popover-placement-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, AvatarComponent]\n})\nexport class PopoverPlacementExampleComponent {}\n", - "html": "
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" - }, { "name": "popover-programmatic-open-example", "description": "Popover Programmatic Open", "typescript": "import { JsonPipe } from '@angular/common';\nimport { Component, signal } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverComponent,\n PopoverConfig,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-programmatic-open-example',\n templateUrl: './popover-programmatic-open-example.component.html',\n styleUrls: ['popover-programmatic-open-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n AvatarComponent,\n PopoverBodyComponent,\n ButtonComponent,\n JsonPipe\n ]\n})\nexport class PopoverProgrammaticOpenExampleComponent {\n /** Signal-based open state for two-way binding */\n isOpen = signal(false);\n\n /** Disabled state for the popover */\n isDisabled = signal(false);\n\n /** Config object example - can be used instead of individual inputs */\n popoverConfig: PopoverConfig = {\n placement: 'bottom-start',\n noArrow: false,\n closeOnEscapeKey: true,\n focusTrapped: true\n };\n\n /** Track open/close events */\n eventLog = signal([]);\n\n /** Called before popover opens */\n onBeforeOpen(): void {\n this.addToLog('beforeOpen event fired');\n }\n\n /** Called when open state changes */\n onOpenChange(isOpen: boolean): void {\n this.addToLog(`isOpenChange: ${isOpen}`);\n }\n\n /** Toggle disabled state */\n toggleDisabled(): void {\n this.isDisabled.update((v) => !v);\n this.addToLog(`Popover ${this.isDisabled() ? 'disabled' : 'enabled'}`);\n }\n\n /** Clear event log */\n clearLog(): void {\n this.eventLog.set([]);\n }\n\n private addToLog(message: string): void {\n this.eventLog.update((log) => [...log, `${new Date().toLocaleTimeString()}: ${message}`]);\n }\n}\n", "html": "\n

    Signal-based Programmatic Control

    \n
    \n \n \n \n \n \n \n \n \n \n \n \n
    \n\n\n

    Using Config Object

    \n\n \n \n \n \n
    \n

    This popover uses the [config] input:

    \n
    {{ popoverConfig | json }}
    \n
    \n
    \n
    \n\n\n

    Event Log

    \n
    \n @if (eventLog().length === 0) {\n

    No events yet. Open the popover to see events.

    \n } @else {\n
      \n @for (event of eventLog(); track event) {\n
    • {{ event }}
    • \n }\n
    \n \n }\n
    \n" }, + { + "name": "popover-non-dialog-example", + "description": "Popover Non Dialog", + "typescript": "import { Component } from '@angular/core';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-non-dialog-example',\n templateUrl: './popover-non-dialog-example.component.html',\n imports: [PopoverModule]\n})\nexport class PopoverNonDialogExampleComponent {}\n", + "html": "

    \n Use [bodyRole]=\"region\" (or null) when the popover is a non-modal disclosure rather than a\n dialog. Match the role to the popover's actual ARIA semantics.\n

    \n\n\n \n \n \n \n
    \n

    Quick Filters

    \n \n \n
    \n
    \n
    \n" + }, + { + "name": "popover-placement-example", + "description": "Popover Placement", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-placement-example',\n templateUrl: './popover-placement-example.component.html',\n styleUrls: ['popover-placement-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, AvatarComponent]\n})\nexport class PopoverPlacementExampleComponent {}\n", + "html": "
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" + }, { "name": "popover-resizable-example", "description": "Popover Resizable", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-resizable-example',\n templateUrl: './popover-resizable-example.component.html',\n styleUrls: ['popover-resizable-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent]\n})\nexport class PopoverResizableExampleComponent {}\n", "html": "
    \n \n \n \n \n\n \n
    \n

    Resizable content area

    \n

    \n Drag the resize handle to make room for longer content, tables, previews, or forms while keeping the\n popover within its configured limits.\n

    \n \n
    \n
    \n
    \n
    \n" }, - { - "name": "popover-scroll-example", - "description": "Popover Scroll", - "typescript": "import { Overlay, ScrollStrategy } from '@angular/cdk/overlay';\nimport { Component, inject } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-scroll-example',\n templateUrl: './popover-scroll-example.component.html',\n styleUrls: ['./popover-scroll-example.component.scss'],\n imports: [\n FormLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class PopoverScrollExampleComponent {\n /** Do nothing on scroll. */\n noopScrollStrategy: ScrollStrategy;\n\n /**\n * Close the overlay as soon as the user scrolls.\n * @param config Configuration to be used inside the scroll strategy.\n */\n closeScrollStrategy: ScrollStrategy;\n\n /** Block scrolling. */\n blockScrollStrategy: ScrollStrategy;\n\n /** Whether to close the overlay once the user has scrolled away completely. */\n autoClose = false;\n\n /** Time in milliseconds to throttle the scroll events. Use to increase performance. */\n scrollThrottle = 0;\n\n /**\n * Update the overlay's position on scroll.\n * @param config Configuration to be used inside the scroll strategy.\n * Allows debouncing the reposition calls.\n */\n repositionScrollStrategy: ScrollStrategy;\n\n private readonly _overlay = inject(Overlay);\n\n constructor() {\n this.noopScrollStrategy = this._overlay.scrollStrategies.noop();\n this.closeScrollStrategy = this._overlay.scrollStrategies.close();\n this.blockScrollStrategy = this._overlay.scrollStrategies.block();\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n\n refreshRepositionScrollStrategy(): void {\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n}\n", - "html": "\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n Close the overlay once the user has scrolled away completely?\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n" - }, { "name": "popover-example", "description": "Popover", @@ -20440,6 +20452,12 @@ "description": "Popover Trigger", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverComponent, PopoverTriggerDirective } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-trigger-example',\n templateUrl: './popover-trigger-example.component.html',\n imports: [ButtonComponent, PopoverTriggerDirective, PopoverComponent]\n})\nexport class PopoverTriggerExampleComponent {}\n", "html": "\n\n\n
    This popover is connected to trigger element
    \n
    \n" + }, + { + "name": "popover-scroll-example", + "description": "Popover Scroll", + "typescript": "import { Overlay, ScrollStrategy } from '@angular/cdk/overlay';\nimport { Component, inject } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-scroll-example',\n templateUrl: './popover-scroll-example.component.html',\n styleUrls: ['./popover-scroll-example.component.scss'],\n imports: [\n FormLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class PopoverScrollExampleComponent {\n /** Do nothing on scroll. */\n noopScrollStrategy: ScrollStrategy;\n\n /**\n * Close the overlay as soon as the user scrolls.\n * @param config Configuration to be used inside the scroll strategy.\n */\n closeScrollStrategy: ScrollStrategy;\n\n /** Block scrolling. */\n blockScrollStrategy: ScrollStrategy;\n\n /** Whether to close the overlay once the user has scrolled away completely. */\n autoClose = false;\n\n /** Time in milliseconds to throttle the scroll events. Use to increase performance. */\n scrollThrottle = 0;\n\n /**\n * Update the overlay's position on scroll.\n * @param config Configuration to be used inside the scroll strategy.\n * Allows debouncing the reposition calls.\n */\n repositionScrollStrategy: ScrollStrategy;\n\n private readonly _overlay = inject(Overlay);\n\n constructor() {\n this.noopScrollStrategy = this._overlay.scrollStrategies.noop();\n this.closeScrollStrategy = this._overlay.scrollStrategies.close();\n this.blockScrollStrategy = this._overlay.scrollStrategies.block();\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n\n refreshRepositionScrollStrategy(): void {\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n}\n", + "html": "\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n Close the overlay once the user has scrolled away completely?\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n" } ] }, @@ -20463,18 +20481,18 @@ "typescript": "import { Component, ViewEncapsulation } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverBodyDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-closing-example',\n templateUrl: './popover-closing-example.component.html',\n styleUrls: ['./popover-closing-example.component.scss'],\n encapsulation: ViewEncapsulation.None,\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n ButtonComponent,\n PopoverBodyHeaderDirective,\n PopoverBodyDirective,\n AvatarComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective\n ]\n})\nexport class PopoverClosingExampleComponent {}\n", "html": "
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n \n \n \n \n \n \n
    \n

    This popover stays open during router navigation.

    \n
    \n
    \n
    \n
    \n" }, - { - "name": "popover-complex-example", - "description": "Popover Complex", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-popover-complex-example',\n templateUrl: './popover-complex-example.component.html',\n styleUrls: ['./popover-complex-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonComponent,\n PopoverBodyComponent,\n TitleComponent,\n AvatarComponent,\n PopoverBodyHeaderDirective,\n ContentDensityDirective,\n PopoverBodyFooterDirective\n ]\n})\nexport class PopoverComplexExampleComponent {}\n", - "html": "
    \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n
    \n SubHeader\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n" - }, { "name": "popover-container-example", "description": "Popover Container", "typescript": "import { Component } from '@angular/core';\nimport { FocusableItemDirective } from '@fundamental-ngx/cdk';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-container-example',\n templateUrl: './popover-container-example.component.html',\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, FocusableItemDirective]\n})\nexport class PopoverContainerExampleComponent {}\n", "html": "

    appendTo

    \n

    Position the popover relative to a different element (the dashed box below).

    \n
    \n \n \n \n \n \n
    This popover is positioned relative to the container below
    \n
    \n
    \n
    \n\n
    Container (appendTo target)
    \n\n

    \n\n

    placementContainer

    \n

    \n Appends the overlay DOM element inside a container instead of body. Useful for z-index stacking contexts (e.g.,\n inside modals/dialogs). The popover still appears at the trigger, but its DOM is inside the container.\n

    \n
    \n \n \n \n \n \n
    Overlay DOM is inside the blue container
    \n
    \n
    \n (Inspect DOM to see overlay inside this container)\n
    \n" }, + { + "name": "popover-complex-example", + "description": "Popover Complex", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-popover-complex-example',\n templateUrl: './popover-complex-example.component.html',\n styleUrls: ['./popover-complex-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonComponent,\n PopoverBodyComponent,\n TitleComponent,\n AvatarComponent,\n PopoverBodyHeaderDirective,\n ContentDensityDirective,\n PopoverBodyFooterDirective\n ]\n})\nexport class PopoverComplexExampleComponent {}\n", + "html": "
    \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n
    \n SubHeader\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, { "name": "popover-dialog-example", "description": "Popover Dialog", @@ -20498,12 +20516,6 @@ "typescript": "import { Component, signal } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverComponent,\n PopoverContainerDirective,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-dynamic-container-height-example',\n templateUrl: './popover-dynamic-container-height-example.component.html',\n styles: [\n `\n .fd-docs-flex-display-helper {\n display: flex;\n align-items: center;\n justify-content: space-around;\n flex-flow: row wrap;\n width: 100%;\n }\n `\n ],\n imports: [\n PopoverContainerDirective,\n ButtonComponent,\n PopoverComponent,\n PopoverControlComponent,\n AvatarComponent,\n PopoverBodyComponent\n ]\n})\nexport class PopoverDynamicContainerHeightExampleComponent {\n showOverflowContainer = signal(false);\n\n private _overflowContainerTimeout: ReturnType | null = null;\n\n resetOverflowContainer(): void {\n if (this._overflowContainerTimeout) {\n clearTimeout(this._overflowContainerTimeout);\n }\n this.showOverflowContainer.set(false);\n this._overflowContainerTimeout = setTimeout(() => {\n this.showOverflowContainer.set(true);\n }, 2000);\n }\n}\n", "html": "
    \n @if (showOverflowContainer()) {\n
    \n }\n \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" }, - { - "name": "popover-focus-example", - "description": "Popover Focus", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-focus-example',\n templateUrl: './popover-focus-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n PopoverBodyHeaderDirective,\n BarModule,\n AvatarComponent,\n PopoverBodyFooterDirective,\n ContentDensityDirective\n ]\n})\nexport class PopoverFocusExampleComponent {}\n", - "html": "

    Focus Trapped & Auto Capture (default behavior)

    \n\n \n \n \n \n
    \n
    \n
    \n \n Header\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n

    \n\n

    Focus NOT Auto Captured

    \n\n \n \n \n \n
    \n

    Focus is not automatically moved to this popover when opened.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Restore Focus On Close (default: true)

    \n\n \n \n \n \n
    \n

    When closed, focus returns to the trigger button.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Do NOT Restore Focus On Close

    \n\n \n \n \n \n
    \n

    When closed, focus does NOT return to the trigger.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Prevent Space Key Scroll (default: true)

    \n

    \n By default, pressing Space on the trigger prevents page scrolling. Set\n [preventSpaceKeyScroll]=\"false\" to allow normal scroll behavior.\n

    \n\n \n \n \n \n
    \n

    When this popover's trigger is focused, pressing Space allows page scroll.

    \n
    \n
    \n
    \n" - }, { "name": "popover-inside-popover-example", "description": "Popover Inside Popover", @@ -20515,6 +20527,12 @@ "description": "Popover Lazy Init Of Body", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyDirective,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { PopoverLazyLoadedBodyComponent } from './popover-lazy-loaded-body.component';\n\n@Component({\n selector: 'fd-popover-lazy-init-of-body-example',\n template: `\n \n \n \n \n \n

    Header

    \n \n
    Footer
    \n
    \n
    \n `,\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyDirective,\n PopoverBodyHeaderDirective,\n PopoverBodyFooterDirective,\n ButtonComponent,\n PopoverLazyLoadedBodyComponent\n ]\n})\nexport class PopoverLazyInitOfBodyExampleComponent {}\n" }, + { + "name": "popover-focus-example", + "description": "Popover Focus", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-focus-example',\n templateUrl: './popover-focus-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n PopoverBodyHeaderDirective,\n BarModule,\n AvatarComponent,\n PopoverBodyFooterDirective,\n ContentDensityDirective\n ]\n})\nexport class PopoverFocusExampleComponent {}\n", + "html": "

    Focus Trapped & Auto Capture (default behavior)

    \n\n \n \n \n \n
    \n
    \n
    \n \n Header\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n

    \n\n

    Focus NOT Auto Captured

    \n\n \n \n \n \n
    \n

    Focus is not automatically moved to this popover when opened.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Restore Focus On Close (default: true)

    \n\n \n \n \n \n
    \n

    When closed, focus returns to the trigger button.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Do NOT Restore Focus On Close

    \n\n \n \n \n \n
    \n

    When closed, focus does NOT return to the trigger.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Prevent Space Key Scroll (default: true)

    \n

    \n By default, pressing Space on the trigger prevents page scrolling. Set\n [preventSpaceKeyScroll]=\"false\" to allow normal scroll behavior.\n

    \n\n \n \n \n \n
    \n

    When this popover's trigger is focused, pressing Space allows page scroll.

    \n
    \n
    \n
    \n" + }, { "name": "popover-mobile-example", "description": "Popover Mobile", @@ -20527,30 +20545,30 @@ "typescript": "import { ConnectionPositionPair } from '@angular/cdk/overlay';\nimport { Component, signal, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport { XPositions, YPositions } from '@fundamental-ngx/core/shared';\n\n@Component({\n selector: 'fd-popover-cdk-placement-example',\n templateUrl: './popover-cdk-placement-example.component.html',\n imports: [\n FormLabelComponent,\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent\n ]\n})\nexport class PopoverCdkPlacementExampleComponent {\n readonly popover = viewChild(PopoverComponent);\n\n readonly yPositions: YPositions[] = ['bottom', 'center', 'top'];\n readonly xPositions: XPositions[] = ['start', 'center', 'end'];\n\n originX = signal('center');\n originY = signal('center');\n overlayX = signal('center');\n overlayY = signal('center');\n\n cdkPosition = signal(this._buildCdkPositionObject());\n\n refresh(): void {\n this.cdkPosition.set(this._buildCdkPositionObject());\n this.popover()?.applyNewPosition(this.cdkPosition());\n }\n\n private _buildCdkPositionObject(): ConnectionPositionPair[] {\n return [\n {\n originX: this.originX(),\n originY: this.originY(),\n overlayX: this.overlayX(),\n overlayY: this.overlayY()\n }\n ];\n }\n}\n", "html": "
    \n \n \n @for (option of xPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of yPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of xPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of yPositions; track option) {\n \n }\n \n
    \n

    \n\n \n \n \n \n \n \n \n \n\n" }, - { - "name": "popover-placement-example", - "description": "Popover Placement", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-placement-example',\n templateUrl: './popover-placement-example.component.html',\n styleUrls: ['popover-placement-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, AvatarComponent]\n})\nexport class PopoverPlacementExampleComponent {}\n", - "html": "
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" - }, { "name": "popover-programmatic-open-example", "description": "Popover Programmatic Open", "typescript": "import { JsonPipe } from '@angular/common';\nimport { Component, signal } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverComponent,\n PopoverConfig,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-programmatic-open-example',\n templateUrl: './popover-programmatic-open-example.component.html',\n styleUrls: ['popover-programmatic-open-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n AvatarComponent,\n PopoverBodyComponent,\n ButtonComponent,\n JsonPipe\n ]\n})\nexport class PopoverProgrammaticOpenExampleComponent {\n /** Signal-based open state for two-way binding */\n isOpen = signal(false);\n\n /** Disabled state for the popover */\n isDisabled = signal(false);\n\n /** Config object example - can be used instead of individual inputs */\n popoverConfig: PopoverConfig = {\n placement: 'bottom-start',\n noArrow: false,\n closeOnEscapeKey: true,\n focusTrapped: true\n };\n\n /** Track open/close events */\n eventLog = signal([]);\n\n /** Called before popover opens */\n onBeforeOpen(): void {\n this.addToLog('beforeOpen event fired');\n }\n\n /** Called when open state changes */\n onOpenChange(isOpen: boolean): void {\n this.addToLog(`isOpenChange: ${isOpen}`);\n }\n\n /** Toggle disabled state */\n toggleDisabled(): void {\n this.isDisabled.update((v) => !v);\n this.addToLog(`Popover ${this.isDisabled() ? 'disabled' : 'enabled'}`);\n }\n\n /** Clear event log */\n clearLog(): void {\n this.eventLog.set([]);\n }\n\n private addToLog(message: string): void {\n this.eventLog.update((log) => [...log, `${new Date().toLocaleTimeString()}: ${message}`]);\n }\n}\n", "html": "\n

    Signal-based Programmatic Control

    \n
    \n \n \n \n \n \n \n \n \n \n \n \n
    \n\n\n

    Using Config Object

    \n\n \n \n \n \n
    \n

    This popover uses the [config] input:

    \n
    {{ popoverConfig | json }}
    \n
    \n
    \n
    \n\n\n

    Event Log

    \n
    \n @if (eventLog().length === 0) {\n

    No events yet. Open the popover to see events.

    \n } @else {\n
      \n @for (event of eventLog(); track event) {\n
    • {{ event }}
    • \n }\n
    \n \n }\n
    \n" }, + { + "name": "popover-non-dialog-example", + "description": "Popover Non Dialog", + "typescript": "import { Component } from '@angular/core';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-non-dialog-example',\n templateUrl: './popover-non-dialog-example.component.html',\n imports: [PopoverModule]\n})\nexport class PopoverNonDialogExampleComponent {}\n", + "html": "

    \n Use [bodyRole]=\"region\" (or null) when the popover is a non-modal disclosure rather than a\n dialog. Match the role to the popover's actual ARIA semantics.\n

    \n\n\n \n \n \n \n
    \n

    Quick Filters

    \n \n \n
    \n
    \n
    \n" + }, + { + "name": "popover-placement-example", + "description": "Popover Placement", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-placement-example',\n templateUrl: './popover-placement-example.component.html',\n styleUrls: ['popover-placement-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, AvatarComponent]\n})\nexport class PopoverPlacementExampleComponent {}\n", + "html": "
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" + }, { "name": "popover-resizable-example", "description": "Popover Resizable", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-resizable-example',\n templateUrl: './popover-resizable-example.component.html',\n styleUrls: ['popover-resizable-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent]\n})\nexport class PopoverResizableExampleComponent {}\n", "html": "
    \n \n \n \n \n\n \n
    \n

    Resizable content area

    \n

    \n Drag the resize handle to make room for longer content, tables, previews, or forms while keeping the\n popover within its configured limits.\n

    \n \n
    \n
    \n
    \n
    \n" }, - { - "name": "popover-scroll-example", - "description": "Popover Scroll", - "typescript": "import { Overlay, ScrollStrategy } from '@angular/cdk/overlay';\nimport { Component, inject } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-scroll-example',\n templateUrl: './popover-scroll-example.component.html',\n styleUrls: ['./popover-scroll-example.component.scss'],\n imports: [\n FormLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class PopoverScrollExampleComponent {\n /** Do nothing on scroll. */\n noopScrollStrategy: ScrollStrategy;\n\n /**\n * Close the overlay as soon as the user scrolls.\n * @param config Configuration to be used inside the scroll strategy.\n */\n closeScrollStrategy: ScrollStrategy;\n\n /** Block scrolling. */\n blockScrollStrategy: ScrollStrategy;\n\n /** Whether to close the overlay once the user has scrolled away completely. */\n autoClose = false;\n\n /** Time in milliseconds to throttle the scroll events. Use to increase performance. */\n scrollThrottle = 0;\n\n /**\n * Update the overlay's position on scroll.\n * @param config Configuration to be used inside the scroll strategy.\n * Allows debouncing the reposition calls.\n */\n repositionScrollStrategy: ScrollStrategy;\n\n private readonly _overlay = inject(Overlay);\n\n constructor() {\n this.noopScrollStrategy = this._overlay.scrollStrategies.noop();\n this.closeScrollStrategy = this._overlay.scrollStrategies.close();\n this.blockScrollStrategy = this._overlay.scrollStrategies.block();\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n\n refreshRepositionScrollStrategy(): void {\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n}\n", - "html": "\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n Close the overlay once the user has scrolled away completely?\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n" - }, { "name": "popover-example", "description": "Popover", @@ -20562,6 +20580,12 @@ "description": "Popover Trigger", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverComponent, PopoverTriggerDirective } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-trigger-example',\n templateUrl: './popover-trigger-example.component.html',\n imports: [ButtonComponent, PopoverTriggerDirective, PopoverComponent]\n})\nexport class PopoverTriggerExampleComponent {}\n", "html": "\n\n\n
    This popover is connected to trigger element
    \n
    \n" + }, + { + "name": "popover-scroll-example", + "description": "Popover Scroll", + "typescript": "import { Overlay, ScrollStrategy } from '@angular/cdk/overlay';\nimport { Component, inject } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-scroll-example',\n templateUrl: './popover-scroll-example.component.html',\n styleUrls: ['./popover-scroll-example.component.scss'],\n imports: [\n FormLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class PopoverScrollExampleComponent {\n /** Do nothing on scroll. */\n noopScrollStrategy: ScrollStrategy;\n\n /**\n * Close the overlay as soon as the user scrolls.\n * @param config Configuration to be used inside the scroll strategy.\n */\n closeScrollStrategy: ScrollStrategy;\n\n /** Block scrolling. */\n blockScrollStrategy: ScrollStrategy;\n\n /** Whether to close the overlay once the user has scrolled away completely. */\n autoClose = false;\n\n /** Time in milliseconds to throttle the scroll events. Use to increase performance. */\n scrollThrottle = 0;\n\n /**\n * Update the overlay's position on scroll.\n * @param config Configuration to be used inside the scroll strategy.\n * Allows debouncing the reposition calls.\n */\n repositionScrollStrategy: ScrollStrategy;\n\n private readonly _overlay = inject(Overlay);\n\n constructor() {\n this.noopScrollStrategy = this._overlay.scrollStrategies.noop();\n this.closeScrollStrategy = this._overlay.scrollStrategies.close();\n this.blockScrollStrategy = this._overlay.scrollStrategies.block();\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n\n refreshRepositionScrollStrategy(): void {\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n}\n", + "html": "\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n Close the overlay once the user has scrolled away completely?\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n" } ] }, @@ -20585,18 +20609,18 @@ "typescript": "import { Component, ViewEncapsulation } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverBodyDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-closing-example',\n templateUrl: './popover-closing-example.component.html',\n styleUrls: ['./popover-closing-example.component.scss'],\n encapsulation: ViewEncapsulation.None,\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n ButtonComponent,\n PopoverBodyHeaderDirective,\n PopoverBodyDirective,\n AvatarComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective\n ]\n})\nexport class PopoverClosingExampleComponent {}\n", "html": "
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n \n \n \n \n \n \n
    \n

    This popover stays open during router navigation.

    \n
    \n
    \n
    \n
    \n" }, - { - "name": "popover-complex-example", - "description": "Popover Complex", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-popover-complex-example',\n templateUrl: './popover-complex-example.component.html',\n styleUrls: ['./popover-complex-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonComponent,\n PopoverBodyComponent,\n TitleComponent,\n AvatarComponent,\n PopoverBodyHeaderDirective,\n ContentDensityDirective,\n PopoverBodyFooterDirective\n ]\n})\nexport class PopoverComplexExampleComponent {}\n", - "html": "
    \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n
    \n SubHeader\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n" - }, { "name": "popover-container-example", "description": "Popover Container", "typescript": "import { Component } from '@angular/core';\nimport { FocusableItemDirective } from '@fundamental-ngx/cdk';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-container-example',\n templateUrl: './popover-container-example.component.html',\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, FocusableItemDirective]\n})\nexport class PopoverContainerExampleComponent {}\n", "html": "

    appendTo

    \n

    Position the popover relative to a different element (the dashed box below).

    \n
    \n \n \n \n \n \n
    This popover is positioned relative to the container below
    \n
    \n
    \n
    \n\n
    Container (appendTo target)
    \n\n

    \n\n

    placementContainer

    \n

    \n Appends the overlay DOM element inside a container instead of body. Useful for z-index stacking contexts (e.g.,\n inside modals/dialogs). The popover still appears at the trigger, but its DOM is inside the container.\n

    \n
    \n \n \n \n \n \n
    Overlay DOM is inside the blue container
    \n
    \n
    \n (Inspect DOM to see overlay inside this container)\n
    \n" }, + { + "name": "popover-complex-example", + "description": "Popover Complex", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-popover-complex-example',\n templateUrl: './popover-complex-example.component.html',\n styleUrls: ['./popover-complex-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonComponent,\n PopoverBodyComponent,\n TitleComponent,\n AvatarComponent,\n PopoverBodyHeaderDirective,\n ContentDensityDirective,\n PopoverBodyFooterDirective\n ]\n})\nexport class PopoverComplexExampleComponent {}\n", + "html": "
    \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n
    \n SubHeader\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, { "name": "popover-dialog-example", "description": "Popover Dialog", @@ -20620,12 +20644,6 @@ "typescript": "import { Component, signal } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverComponent,\n PopoverContainerDirective,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-dynamic-container-height-example',\n templateUrl: './popover-dynamic-container-height-example.component.html',\n styles: [\n `\n .fd-docs-flex-display-helper {\n display: flex;\n align-items: center;\n justify-content: space-around;\n flex-flow: row wrap;\n width: 100%;\n }\n `\n ],\n imports: [\n PopoverContainerDirective,\n ButtonComponent,\n PopoverComponent,\n PopoverControlComponent,\n AvatarComponent,\n PopoverBodyComponent\n ]\n})\nexport class PopoverDynamicContainerHeightExampleComponent {\n showOverflowContainer = signal(false);\n\n private _overflowContainerTimeout: ReturnType | null = null;\n\n resetOverflowContainer(): void {\n if (this._overflowContainerTimeout) {\n clearTimeout(this._overflowContainerTimeout);\n }\n this.showOverflowContainer.set(false);\n this._overflowContainerTimeout = setTimeout(() => {\n this.showOverflowContainer.set(true);\n }, 2000);\n }\n}\n", "html": "
    \n @if (showOverflowContainer()) {\n
    \n }\n \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" }, - { - "name": "popover-focus-example", - "description": "Popover Focus", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-focus-example',\n templateUrl: './popover-focus-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n PopoverBodyHeaderDirective,\n BarModule,\n AvatarComponent,\n PopoverBodyFooterDirective,\n ContentDensityDirective\n ]\n})\nexport class PopoverFocusExampleComponent {}\n", - "html": "

    Focus Trapped & Auto Capture (default behavior)

    \n\n \n \n \n \n
    \n
    \n
    \n \n Header\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n

    \n\n

    Focus NOT Auto Captured

    \n\n \n \n \n \n
    \n

    Focus is not automatically moved to this popover when opened.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Restore Focus On Close (default: true)

    \n\n \n \n \n \n
    \n

    When closed, focus returns to the trigger button.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Do NOT Restore Focus On Close

    \n\n \n \n \n \n
    \n

    When closed, focus does NOT return to the trigger.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Prevent Space Key Scroll (default: true)

    \n

    \n By default, pressing Space on the trigger prevents page scrolling. Set\n [preventSpaceKeyScroll]=\"false\" to allow normal scroll behavior.\n

    \n\n \n \n \n \n
    \n

    When this popover's trigger is focused, pressing Space allows page scroll.

    \n
    \n
    \n
    \n" - }, { "name": "popover-inside-popover-example", "description": "Popover Inside Popover", @@ -20637,6 +20655,12 @@ "description": "Popover Lazy Init Of Body", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyDirective,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { PopoverLazyLoadedBodyComponent } from './popover-lazy-loaded-body.component';\n\n@Component({\n selector: 'fd-popover-lazy-init-of-body-example',\n template: `\n \n \n \n \n \n

    Header

    \n \n
    Footer
    \n
    \n
    \n `,\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyDirective,\n PopoverBodyHeaderDirective,\n PopoverBodyFooterDirective,\n ButtonComponent,\n PopoverLazyLoadedBodyComponent\n ]\n})\nexport class PopoverLazyInitOfBodyExampleComponent {}\n" }, + { + "name": "popover-focus-example", + "description": "Popover Focus", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-focus-example',\n templateUrl: './popover-focus-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n PopoverBodyHeaderDirective,\n BarModule,\n AvatarComponent,\n PopoverBodyFooterDirective,\n ContentDensityDirective\n ]\n})\nexport class PopoverFocusExampleComponent {}\n", + "html": "

    Focus Trapped & Auto Capture (default behavior)

    \n\n \n \n \n \n
    \n
    \n
    \n \n Header\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n

    \n\n

    Focus NOT Auto Captured

    \n\n \n \n \n \n
    \n

    Focus is not automatically moved to this popover when opened.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Restore Focus On Close (default: true)

    \n\n \n \n \n \n
    \n

    When closed, focus returns to the trigger button.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Do NOT Restore Focus On Close

    \n\n \n \n \n \n
    \n

    When closed, focus does NOT return to the trigger.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Prevent Space Key Scroll (default: true)

    \n

    \n By default, pressing Space on the trigger prevents page scrolling. Set\n [preventSpaceKeyScroll]=\"false\" to allow normal scroll behavior.\n

    \n\n \n \n \n \n
    \n

    When this popover's trigger is focused, pressing Space allows page scroll.

    \n
    \n
    \n
    \n" + }, { "name": "popover-mobile-example", "description": "Popover Mobile", @@ -20649,30 +20673,30 @@ "typescript": "import { ConnectionPositionPair } from '@angular/cdk/overlay';\nimport { Component, signal, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport { XPositions, YPositions } from '@fundamental-ngx/core/shared';\n\n@Component({\n selector: 'fd-popover-cdk-placement-example',\n templateUrl: './popover-cdk-placement-example.component.html',\n imports: [\n FormLabelComponent,\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent\n ]\n})\nexport class PopoverCdkPlacementExampleComponent {\n readonly popover = viewChild(PopoverComponent);\n\n readonly yPositions: YPositions[] = ['bottom', 'center', 'top'];\n readonly xPositions: XPositions[] = ['start', 'center', 'end'];\n\n originX = signal('center');\n originY = signal('center');\n overlayX = signal('center');\n overlayY = signal('center');\n\n cdkPosition = signal(this._buildCdkPositionObject());\n\n refresh(): void {\n this.cdkPosition.set(this._buildCdkPositionObject());\n this.popover()?.applyNewPosition(this.cdkPosition());\n }\n\n private _buildCdkPositionObject(): ConnectionPositionPair[] {\n return [\n {\n originX: this.originX(),\n originY: this.originY(),\n overlayX: this.overlayX(),\n overlayY: this.overlayY()\n }\n ];\n }\n}\n", "html": "
    \n \n \n @for (option of xPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of yPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of xPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of yPositions; track option) {\n \n }\n \n
    \n

    \n\n \n \n \n \n \n \n \n \n\n" }, - { - "name": "popover-placement-example", - "description": "Popover Placement", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-placement-example',\n templateUrl: './popover-placement-example.component.html',\n styleUrls: ['popover-placement-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, AvatarComponent]\n})\nexport class PopoverPlacementExampleComponent {}\n", - "html": "
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" - }, { "name": "popover-programmatic-open-example", "description": "Popover Programmatic Open", "typescript": "import { JsonPipe } from '@angular/common';\nimport { Component, signal } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverComponent,\n PopoverConfig,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-programmatic-open-example',\n templateUrl: './popover-programmatic-open-example.component.html',\n styleUrls: ['popover-programmatic-open-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n AvatarComponent,\n PopoverBodyComponent,\n ButtonComponent,\n JsonPipe\n ]\n})\nexport class PopoverProgrammaticOpenExampleComponent {\n /** Signal-based open state for two-way binding */\n isOpen = signal(false);\n\n /** Disabled state for the popover */\n isDisabled = signal(false);\n\n /** Config object example - can be used instead of individual inputs */\n popoverConfig: PopoverConfig = {\n placement: 'bottom-start',\n noArrow: false,\n closeOnEscapeKey: true,\n focusTrapped: true\n };\n\n /** Track open/close events */\n eventLog = signal([]);\n\n /** Called before popover opens */\n onBeforeOpen(): void {\n this.addToLog('beforeOpen event fired');\n }\n\n /** Called when open state changes */\n onOpenChange(isOpen: boolean): void {\n this.addToLog(`isOpenChange: ${isOpen}`);\n }\n\n /** Toggle disabled state */\n toggleDisabled(): void {\n this.isDisabled.update((v) => !v);\n this.addToLog(`Popover ${this.isDisabled() ? 'disabled' : 'enabled'}`);\n }\n\n /** Clear event log */\n clearLog(): void {\n this.eventLog.set([]);\n }\n\n private addToLog(message: string): void {\n this.eventLog.update((log) => [...log, `${new Date().toLocaleTimeString()}: ${message}`]);\n }\n}\n", "html": "\n

    Signal-based Programmatic Control

    \n
    \n \n \n \n \n \n \n \n \n \n \n \n
    \n\n\n

    Using Config Object

    \n\n \n \n \n \n
    \n

    This popover uses the [config] input:

    \n
    {{ popoverConfig | json }}
    \n
    \n
    \n
    \n\n\n

    Event Log

    \n
    \n @if (eventLog().length === 0) {\n

    No events yet. Open the popover to see events.

    \n } @else {\n
      \n @for (event of eventLog(); track event) {\n
    • {{ event }}
    • \n }\n
    \n \n }\n
    \n" }, + { + "name": "popover-non-dialog-example", + "description": "Popover Non Dialog", + "typescript": "import { Component } from '@angular/core';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-non-dialog-example',\n templateUrl: './popover-non-dialog-example.component.html',\n imports: [PopoverModule]\n})\nexport class PopoverNonDialogExampleComponent {}\n", + "html": "

    \n Use [bodyRole]=\"region\" (or null) when the popover is a non-modal disclosure rather than a\n dialog. Match the role to the popover's actual ARIA semantics.\n

    \n\n\n \n \n \n \n
    \n

    Quick Filters

    \n \n \n
    \n
    \n
    \n" + }, + { + "name": "popover-placement-example", + "description": "Popover Placement", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-placement-example',\n templateUrl: './popover-placement-example.component.html',\n styleUrls: ['popover-placement-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, AvatarComponent]\n})\nexport class PopoverPlacementExampleComponent {}\n", + "html": "
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" + }, { "name": "popover-resizable-example", "description": "Popover Resizable", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-resizable-example',\n templateUrl: './popover-resizable-example.component.html',\n styleUrls: ['popover-resizable-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent]\n})\nexport class PopoverResizableExampleComponent {}\n", "html": "
    \n \n \n \n \n\n \n
    \n

    Resizable content area

    \n

    \n Drag the resize handle to make room for longer content, tables, previews, or forms while keeping the\n popover within its configured limits.\n

    \n \n
    \n
    \n
    \n
    \n" }, - { - "name": "popover-scroll-example", - "description": "Popover Scroll", - "typescript": "import { Overlay, ScrollStrategy } from '@angular/cdk/overlay';\nimport { Component, inject } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-scroll-example',\n templateUrl: './popover-scroll-example.component.html',\n styleUrls: ['./popover-scroll-example.component.scss'],\n imports: [\n FormLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class PopoverScrollExampleComponent {\n /** Do nothing on scroll. */\n noopScrollStrategy: ScrollStrategy;\n\n /**\n * Close the overlay as soon as the user scrolls.\n * @param config Configuration to be used inside the scroll strategy.\n */\n closeScrollStrategy: ScrollStrategy;\n\n /** Block scrolling. */\n blockScrollStrategy: ScrollStrategy;\n\n /** Whether to close the overlay once the user has scrolled away completely. */\n autoClose = false;\n\n /** Time in milliseconds to throttle the scroll events. Use to increase performance. */\n scrollThrottle = 0;\n\n /**\n * Update the overlay's position on scroll.\n * @param config Configuration to be used inside the scroll strategy.\n * Allows debouncing the reposition calls.\n */\n repositionScrollStrategy: ScrollStrategy;\n\n private readonly _overlay = inject(Overlay);\n\n constructor() {\n this.noopScrollStrategy = this._overlay.scrollStrategies.noop();\n this.closeScrollStrategy = this._overlay.scrollStrategies.close();\n this.blockScrollStrategy = this._overlay.scrollStrategies.block();\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n\n refreshRepositionScrollStrategy(): void {\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n}\n", - "html": "\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n Close the overlay once the user has scrolled away completely?\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n" - }, { "name": "popover-example", "description": "Popover", @@ -20684,6 +20708,12 @@ "description": "Popover Trigger", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverComponent, PopoverTriggerDirective } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-trigger-example',\n templateUrl: './popover-trigger-example.component.html',\n imports: [ButtonComponent, PopoverTriggerDirective, PopoverComponent]\n})\nexport class PopoverTriggerExampleComponent {}\n", "html": "\n\n\n
    This popover is connected to trigger element
    \n
    \n" + }, + { + "name": "popover-scroll-example", + "description": "Popover Scroll", + "typescript": "import { Overlay, ScrollStrategy } from '@angular/cdk/overlay';\nimport { Component, inject } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-scroll-example',\n templateUrl: './popover-scroll-example.component.html',\n styleUrls: ['./popover-scroll-example.component.scss'],\n imports: [\n FormLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class PopoverScrollExampleComponent {\n /** Do nothing on scroll. */\n noopScrollStrategy: ScrollStrategy;\n\n /**\n * Close the overlay as soon as the user scrolls.\n * @param config Configuration to be used inside the scroll strategy.\n */\n closeScrollStrategy: ScrollStrategy;\n\n /** Block scrolling. */\n blockScrollStrategy: ScrollStrategy;\n\n /** Whether to close the overlay once the user has scrolled away completely. */\n autoClose = false;\n\n /** Time in milliseconds to throttle the scroll events. Use to increase performance. */\n scrollThrottle = 0;\n\n /**\n * Update the overlay's position on scroll.\n * @param config Configuration to be used inside the scroll strategy.\n * Allows debouncing the reposition calls.\n */\n repositionScrollStrategy: ScrollStrategy;\n\n private readonly _overlay = inject(Overlay);\n\n constructor() {\n this.noopScrollStrategy = this._overlay.scrollStrategies.noop();\n this.closeScrollStrategy = this._overlay.scrollStrategies.close();\n this.blockScrollStrategy = this._overlay.scrollStrategies.block();\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n\n refreshRepositionScrollStrategy(): void {\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n}\n", + "html": "\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n Close the overlay once the user has scrolled away completely?\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n" } ] }, @@ -22081,18 +22111,18 @@ "typescript": "import { Component, inject, OnInit, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { IllustratedMessageModule, SvgConfig } from '@fundamental-ngx/core/illustrated-message';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { SegmentedButtonComponent } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\nimport { DataProvider, SearchFieldDataSource } from '@fundamental-ngx/platform/shared';\nimport { Observable, of } from 'rxjs';\n\n@Component({\n selector: 'fd-shellbar-complex-search-results-example',\n templateUrl: './shellbar-complex-search-results-example.component.html',\n imports: [\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarModule,\n BarRightDirective,\n MessageToastModule,\n SearchFieldComponent,\n ShellbarActionComponent,\n FormsModule,\n SegmentedButtonComponent,\n CheckboxComponent,\n IllustratedMessageModule\n ]\n})\nexport class ShellbarComplexSearchResultsExampleComponent implements OnInit {\n shellSearchField = viewChild('shellSearchField');\n\n dataSource: SearchFieldDataSource;\n\n expanded = true;\n\n exampleType: 'default' | 'advancedFilter' | 'mobile' = 'default';\n\n emptyResultsType: 'illustratedMessage' | 'customSuggestions' = 'illustratedMessage';\n\n emptyDefaultSuggestions: SuggestionItem[] = [\n {\n value: 'Peach',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Pear',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Plum',\n data: {\n type: 'fruit'\n }\n }\n ];\n\n categories: ValueLabelItem[] = [\n {\n value: 'fruit',\n label: 'Fruits'\n },\n {\n value: 'vegetable',\n label: 'Vegetables'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n label: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n label: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n smallConfig: SvgConfig = {\n small: { url: 'assets/images/sapIllus-Ice-Cream-Demo-Small.svg', id: 'sapIllus-Ice-Cream-Demo-Small' }\n };\n\n showCategories = true;\n\n suggestionsLoading = false;\n\n private _messageToastService = inject(MessageToastService);\n\n ngOnInit(): void {\n this.dataSource = new SearchFieldDataSource(new ShellSearchFieldDataProvider());\n SUGGESTIONS[0].children?.forEach((child) => {\n this.emptyDefaultSuggestions.push(child);\n });\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n showAllSearchResultsClicked(): void {\n this.suggestionsLoading = true;\n setTimeout(() => {\n this.suggestionsLoading = false;\n this.shellSearchField()?.resetCategory();\n this.shellSearchField()?.clearTextInput();\n }, 500);\n }\n\n submit(event: SearchInput): void {\n alert('Search submitted. See developer console for event');\n console.log(event);\n }\n}\n\nexport class ShellSearchFieldDataProvider extends DataProvider {\n constructor() {\n super();\n }\n\n fetch(params: Map): Observable {\n const data = SUGGESTIONS;\n const name = params.get('keyword');\n const category = params.get('category');\n if ((!name || name.trim() === '') && !category) {\n return of(data);\n } else {\n const filteredData = data.filter((suggestion) => {\n let foundMatchingChild = false;\n if (suggestion.children) {\n for (let i = 0; i < suggestion.children.length && !foundMatchingChild; i++) {\n foundMatchingChild = this._checkForMatches(suggestion.children[i], name, category);\n }\n } else {\n foundMatchingChild = this._checkForMatches(suggestion, name, category);\n }\n return foundMatchingChild;\n });\n return of(filteredData);\n }\n }\n\n private _checkForMatches(item: any, name: string | undefined, category: string | undefined): boolean {\n let foundMatchingItem = false;\n if (name && category) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1 && item.data?.type === category) {\n foundMatchingItem = true;\n }\n } else if (name) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1) {\n foundMatchingItem = true;\n }\n } else if (category) {\n if (item.data?.type === category) {\n foundMatchingItem = true;\n }\n }\n return foundMatchingItem;\n }\n}\n\nconst SUGGESTIONS: SuggestionItem[] = [\n {\n value: 'Fruits',\n isGroupHeader: true,\n children: [\n {\n value: 'Apple',\n data: {\n type: 'fruit',\n listIconGlyph: 'globe'\n }\n },\n {\n value: 'Banana',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Blueberry',\n data: {\n type: 'fruit',\n prefix: 'Prefix text:',\n actionButtons: [\n {\n actionButtonGlyph: 'refresh',\n actionButtonCallback: () => {\n alert('Blueberry refresh button clicked');\n },\n actionButtonId: 'refresh-button-1',\n actionButtonLabel: 'Refresh Item'\n },\n {\n actionButtonGlyph: 'settings',\n actionButtonCallback: () => {\n alert('Blueberry settings button clicked');\n },\n actionButtonLabel: 'Settings'\n }\n ],\n showDeleteButton: true,\n deleteCallback: () => {\n alert('Blueberry delete button clicked');\n }\n }\n },\n {\n value: 'Cherry',\n data: {\n type: 'fruit'\n }\n }\n ],\n searchInScopeText: 'Search in [Fruits]',\n searchInScopeCounter: 1234,\n searchInScopeCallback: () => {\n alert('Search in scope callback clicked');\n }\n },\n {\n value: 'Vegetables',\n isGroupHeader: true,\n children: [\n {\n value: 'Broccoli',\n data: {\n type: 'vegetable',\n subline: 'Flower vegetable',\n avatarLabel: 'John Doe'\n }\n },\n {\n value: 'Carrot',\n data: {\n type: 'vegetable',\n subline: 'Root vegetable',\n listIconGlyph: 'cart'\n }\n },\n {\n value: 'Corn',\n data: {\n type: 'vegetable'\n }\n },\n {\n value: 'Radish',\n data: {\n type: 'vegetable'\n }\n }\n ],\n showMoreText: 'Show More',\n showMoreCounter: 1234,\n showMoreCallback: () => {\n alert('Show more callback clicked');\n }\n }\n];\n", "html": "Shell search field example type:\n
    \n\n \n \n \n\n
    \nEmpty search results example type:\n
    \n\n \n \n\n
    \n\n\n
    \n \n \n \n \n \n Product Identifier\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n
    \n\n\n
    \n \n
    \n
    \n\n\n @if (emptyResultsType === 'illustratedMessage') {\n
    \n
    \n

    No Results

    \n

    Start by proiding your search criteria.

    \n
    \n
    \n }\n
    \n" }, + { + "name": "shellbar-responsive-example", + "description": "Shellbar Responsive", + "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", + "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, { "name": "shellbar-branding-context-area-example", "description": "Shellbar Branding Context Area", "typescript": "import { Component, ElementRef, signal, ViewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ClickedDirective } from '@fundamental-ngx/cdk';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport {\n ShellbarComponent,\n ShellbarMenuItem,\n ShellbarModule,\n ShellbarUser,\n ShellbarUserMenu\n} from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\n@Component({\n selector: 'fd-shellbar-branding-context-area-example',\n templateUrl: './shellbar-branding-context-area-example.component.html',\n imports: [\n ShellbarModule,\n MenuModule,\n AvatarComponent,\n ClickedDirective,\n ButtonComponent,\n FormsModule,\n ProductSwitchModule,\n SearchFieldComponent,\n ObjectStatusComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n PopoverModule,\n ListModule,\n PanelModule,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarBrandingContextAreaExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n @ViewChild(ShellbarComponent, { read: ElementRef })\n shellbar: ElementRef;\n\n expanded = true;\n\n isOpen = false;\n\n searchTerm = '';\n\n inputText = '';\n\n showButtonWithPriority3 = true;\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n productMenuItems: ShellbarMenuItem[] = [\n {\n name: 'Application A',\n callback: () => {\n alert('Application A Clicked');\n }\n },\n {\n name: 'Application B',\n callback: () => {\n alert('Application B Clicked');\n }\n },\n {\n name: 'Application C',\n callback: () => {\n alert('Application C Clicked');\n }\n },\n {\n name: 'Application D',\n callback: () => {\n alert('Application D Clicked');\n }\n }\n ];\n\n accountToggledState = signal(true);\n filterToggledState = signal(false);\n cartToggledState = signal(false);\n\n actions = [\n {\n glyph: 'account',\n callback: () => this.actionAccountCallback(),\n label: 'Account',\n ariaLabel: 'Account Action',\n title: 'Account',\n type: 'transparent' as ButtonType,\n toggled: this.accountToggledState\n },\n {\n glyph: 'filter',\n callback: () => this.actionFilterCallback(),\n label: 'Filter',\n ariaLabel: 'Filter Action',\n title: 'Filter',\n type: 'attention' as ButtonType,\n toggled: this.filterToggledState\n },\n {\n glyph: 'cart',\n callback: () => this.actionCartCallback(),\n label: 'Cart',\n ariaLabel: 'Cart Action',\n type: 'positive' as ButtonType,\n title: 'Cart',\n toggled: this.cartToggledState\n },\n {\n glyph: 'bell',\n callback: (event: MouseEvent) => this.actionNotificationCallback(event),\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home'),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n user: ShellbarUser = {\n fullName: 'William Willson',\n colorAccent: 6\n };\n\n userMenu: ShellbarUserMenu[] = [\n { text: 'Settings', callback: this.settingsCallback },\n { text: 'Sign Out', callback: this.signOutCallback }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n brandingClicked($event: Event): void {\n console.log($event);\n alert('Branding clicked');\n }\n\n settingsCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Settings Clicked');\n }\n\n signOutCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionAccountCallback(): void {\n this.accountToggledState.set(!this.accountToggledState());\n }\n\n actionFilterCallback(): void {\n this.filterToggledState.set(!this.filterToggledState());\n }\n\n actionCartCallback(): void {\n this.cartToggledState.set(!this.cartToggledState());\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n assistiveToolsCallback(): void {\n alert('Assistive Tools Clicked');\n }\n\n navClicked(event): void {\n console.log(event);\n alert('Navigation Button Clicked');\n }\n\n backClicked(event): void {\n console.log(event);\n alert('Back Button Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n toggleButton3(): void {\n this.showButtonWithPriority3 = !this.showButtonWithPriority3;\n }\n\n itemVisibilityChanged(event: any): void {\n console.log(event);\n }\n}\n", "html": "\n \n \n \n \n Product Identifier\n \n\n \n \n \n \n \n \n @if (showButtonWithPriority3) {\n \n }\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n\n\n
    \n\n\n" }, - { - "name": "shellbar-context-area-overflow-example", - "description": "Shellbar Context Area Overflow", - "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", - "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" - }, { "name": "shellbar-growing-group-example", "description": "Shellbar Growing Group", @@ -22100,10 +22130,10 @@ "html": "

    This example shows Shellbar groups taking only space needed for the content inside.

    \n\n \n \n \n \n Product Identifier\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n" }, { - "name": "shellbar-responsive-example", - "description": "Shellbar Responsive", - "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", - "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + "name": "shellbar-context-area-overflow-example", + "description": "Shellbar Context Area Overflow", + "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", + "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" } ] }, @@ -22139,18 +22169,18 @@ "typescript": "import { Component, inject, OnInit, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { IllustratedMessageModule, SvgConfig } from '@fundamental-ngx/core/illustrated-message';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { SegmentedButtonComponent } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\nimport { DataProvider, SearchFieldDataSource } from '@fundamental-ngx/platform/shared';\nimport { Observable, of } from 'rxjs';\n\n@Component({\n selector: 'fd-shellbar-complex-search-results-example',\n templateUrl: './shellbar-complex-search-results-example.component.html',\n imports: [\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarModule,\n BarRightDirective,\n MessageToastModule,\n SearchFieldComponent,\n ShellbarActionComponent,\n FormsModule,\n SegmentedButtonComponent,\n CheckboxComponent,\n IllustratedMessageModule\n ]\n})\nexport class ShellbarComplexSearchResultsExampleComponent implements OnInit {\n shellSearchField = viewChild('shellSearchField');\n\n dataSource: SearchFieldDataSource;\n\n expanded = true;\n\n exampleType: 'default' | 'advancedFilter' | 'mobile' = 'default';\n\n emptyResultsType: 'illustratedMessage' | 'customSuggestions' = 'illustratedMessage';\n\n emptyDefaultSuggestions: SuggestionItem[] = [\n {\n value: 'Peach',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Pear',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Plum',\n data: {\n type: 'fruit'\n }\n }\n ];\n\n categories: ValueLabelItem[] = [\n {\n value: 'fruit',\n label: 'Fruits'\n },\n {\n value: 'vegetable',\n label: 'Vegetables'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n label: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n label: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n smallConfig: SvgConfig = {\n small: { url: 'assets/images/sapIllus-Ice-Cream-Demo-Small.svg', id: 'sapIllus-Ice-Cream-Demo-Small' }\n };\n\n showCategories = true;\n\n suggestionsLoading = false;\n\n private _messageToastService = inject(MessageToastService);\n\n ngOnInit(): void {\n this.dataSource = new SearchFieldDataSource(new ShellSearchFieldDataProvider());\n SUGGESTIONS[0].children?.forEach((child) => {\n this.emptyDefaultSuggestions.push(child);\n });\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n showAllSearchResultsClicked(): void {\n this.suggestionsLoading = true;\n setTimeout(() => {\n this.suggestionsLoading = false;\n this.shellSearchField()?.resetCategory();\n this.shellSearchField()?.clearTextInput();\n }, 500);\n }\n\n submit(event: SearchInput): void {\n alert('Search submitted. See developer console for event');\n console.log(event);\n }\n}\n\nexport class ShellSearchFieldDataProvider extends DataProvider {\n constructor() {\n super();\n }\n\n fetch(params: Map): Observable {\n const data = SUGGESTIONS;\n const name = params.get('keyword');\n const category = params.get('category');\n if ((!name || name.trim() === '') && !category) {\n return of(data);\n } else {\n const filteredData = data.filter((suggestion) => {\n let foundMatchingChild = false;\n if (suggestion.children) {\n for (let i = 0; i < suggestion.children.length && !foundMatchingChild; i++) {\n foundMatchingChild = this._checkForMatches(suggestion.children[i], name, category);\n }\n } else {\n foundMatchingChild = this._checkForMatches(suggestion, name, category);\n }\n return foundMatchingChild;\n });\n return of(filteredData);\n }\n }\n\n private _checkForMatches(item: any, name: string | undefined, category: string | undefined): boolean {\n let foundMatchingItem = false;\n if (name && category) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1 && item.data?.type === category) {\n foundMatchingItem = true;\n }\n } else if (name) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1) {\n foundMatchingItem = true;\n }\n } else if (category) {\n if (item.data?.type === category) {\n foundMatchingItem = true;\n }\n }\n return foundMatchingItem;\n }\n}\n\nconst SUGGESTIONS: SuggestionItem[] = [\n {\n value: 'Fruits',\n isGroupHeader: true,\n children: [\n {\n value: 'Apple',\n data: {\n type: 'fruit',\n listIconGlyph: 'globe'\n }\n },\n {\n value: 'Banana',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Blueberry',\n data: {\n type: 'fruit',\n prefix: 'Prefix text:',\n actionButtons: [\n {\n actionButtonGlyph: 'refresh',\n actionButtonCallback: () => {\n alert('Blueberry refresh button clicked');\n },\n actionButtonId: 'refresh-button-1',\n actionButtonLabel: 'Refresh Item'\n },\n {\n actionButtonGlyph: 'settings',\n actionButtonCallback: () => {\n alert('Blueberry settings button clicked');\n },\n actionButtonLabel: 'Settings'\n }\n ],\n showDeleteButton: true,\n deleteCallback: () => {\n alert('Blueberry delete button clicked');\n }\n }\n },\n {\n value: 'Cherry',\n data: {\n type: 'fruit'\n }\n }\n ],\n searchInScopeText: 'Search in [Fruits]',\n searchInScopeCounter: 1234,\n searchInScopeCallback: () => {\n alert('Search in scope callback clicked');\n }\n },\n {\n value: 'Vegetables',\n isGroupHeader: true,\n children: [\n {\n value: 'Broccoli',\n data: {\n type: 'vegetable',\n subline: 'Flower vegetable',\n avatarLabel: 'John Doe'\n }\n },\n {\n value: 'Carrot',\n data: {\n type: 'vegetable',\n subline: 'Root vegetable',\n listIconGlyph: 'cart'\n }\n },\n {\n value: 'Corn',\n data: {\n type: 'vegetable'\n }\n },\n {\n value: 'Radish',\n data: {\n type: 'vegetable'\n }\n }\n ],\n showMoreText: 'Show More',\n showMoreCounter: 1234,\n showMoreCallback: () => {\n alert('Show more callback clicked');\n }\n }\n];\n", "html": "Shell search field example type:\n
    \n\n \n \n \n\n
    \nEmpty search results example type:\n
    \n\n \n \n\n
    \n\n\n
    \n \n \n \n \n \n Product Identifier\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n
    \n\n\n
    \n \n
    \n
    \n\n\n @if (emptyResultsType === 'illustratedMessage') {\n
    \n
    \n

    No Results

    \n

    Start by proiding your search criteria.

    \n
    \n
    \n }\n
    \n" }, + { + "name": "shellbar-responsive-example", + "description": "Shellbar Responsive", + "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", + "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, { "name": "shellbar-branding-context-area-example", "description": "Shellbar Branding Context Area", "typescript": "import { Component, ElementRef, signal, ViewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ClickedDirective } from '@fundamental-ngx/cdk';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport {\n ShellbarComponent,\n ShellbarMenuItem,\n ShellbarModule,\n ShellbarUser,\n ShellbarUserMenu\n} from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\n@Component({\n selector: 'fd-shellbar-branding-context-area-example',\n templateUrl: './shellbar-branding-context-area-example.component.html',\n imports: [\n ShellbarModule,\n MenuModule,\n AvatarComponent,\n ClickedDirective,\n ButtonComponent,\n FormsModule,\n ProductSwitchModule,\n SearchFieldComponent,\n ObjectStatusComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n PopoverModule,\n ListModule,\n PanelModule,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarBrandingContextAreaExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n @ViewChild(ShellbarComponent, { read: ElementRef })\n shellbar: ElementRef;\n\n expanded = true;\n\n isOpen = false;\n\n searchTerm = '';\n\n inputText = '';\n\n showButtonWithPriority3 = true;\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n productMenuItems: ShellbarMenuItem[] = [\n {\n name: 'Application A',\n callback: () => {\n alert('Application A Clicked');\n }\n },\n {\n name: 'Application B',\n callback: () => {\n alert('Application B Clicked');\n }\n },\n {\n name: 'Application C',\n callback: () => {\n alert('Application C Clicked');\n }\n },\n {\n name: 'Application D',\n callback: () => {\n alert('Application D Clicked');\n }\n }\n ];\n\n accountToggledState = signal(true);\n filterToggledState = signal(false);\n cartToggledState = signal(false);\n\n actions = [\n {\n glyph: 'account',\n callback: () => this.actionAccountCallback(),\n label: 'Account',\n ariaLabel: 'Account Action',\n title: 'Account',\n type: 'transparent' as ButtonType,\n toggled: this.accountToggledState\n },\n {\n glyph: 'filter',\n callback: () => this.actionFilterCallback(),\n label: 'Filter',\n ariaLabel: 'Filter Action',\n title: 'Filter',\n type: 'attention' as ButtonType,\n toggled: this.filterToggledState\n },\n {\n glyph: 'cart',\n callback: () => this.actionCartCallback(),\n label: 'Cart',\n ariaLabel: 'Cart Action',\n type: 'positive' as ButtonType,\n title: 'Cart',\n toggled: this.cartToggledState\n },\n {\n glyph: 'bell',\n callback: (event: MouseEvent) => this.actionNotificationCallback(event),\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home'),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n user: ShellbarUser = {\n fullName: 'William Willson',\n colorAccent: 6\n };\n\n userMenu: ShellbarUserMenu[] = [\n { text: 'Settings', callback: this.settingsCallback },\n { text: 'Sign Out', callback: this.signOutCallback }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n brandingClicked($event: Event): void {\n console.log($event);\n alert('Branding clicked');\n }\n\n settingsCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Settings Clicked');\n }\n\n signOutCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionAccountCallback(): void {\n this.accountToggledState.set(!this.accountToggledState());\n }\n\n actionFilterCallback(): void {\n this.filterToggledState.set(!this.filterToggledState());\n }\n\n actionCartCallback(): void {\n this.cartToggledState.set(!this.cartToggledState());\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n assistiveToolsCallback(): void {\n alert('Assistive Tools Clicked');\n }\n\n navClicked(event): void {\n console.log(event);\n alert('Navigation Button Clicked');\n }\n\n backClicked(event): void {\n console.log(event);\n alert('Back Button Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n toggleButton3(): void {\n this.showButtonWithPriority3 = !this.showButtonWithPriority3;\n }\n\n itemVisibilityChanged(event: any): void {\n console.log(event);\n }\n}\n", "html": "\n \n \n \n \n Product Identifier\n \n\n \n \n \n \n \n \n @if (showButtonWithPriority3) {\n \n }\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n\n\n
    \n\n\n" }, - { - "name": "shellbar-context-area-overflow-example", - "description": "Shellbar Context Area Overflow", - "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", - "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" - }, { "name": "shellbar-growing-group-example", "description": "Shellbar Growing Group", @@ -22158,10 +22188,10 @@ "html": "

    This example shows Shellbar groups taking only space needed for the content inside.

    \n\n \n \n \n \n Product Identifier\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n" }, { - "name": "shellbar-responsive-example", - "description": "Shellbar Responsive", - "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", - "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + "name": "shellbar-context-area-overflow-example", + "description": "Shellbar Context Area Overflow", + "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", + "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" } ] }, @@ -22380,17 +22410,17 @@ "typescript": "import { UpperCasePipe } from '@angular/common';\nimport { Component, ViewChild } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { DialogRef, DialogService } from '@fundamental-ngx/core/dialog';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableComponent, TableModule } from '@fundamental-ngx/core/table';\nimport { TableCustomDialogComponent } from './table-custom-dialog.component';\n\nexport interface DisplayedColumn {\n key: string;\n checked: boolean;\n}\n\nexport interface CellData {\n column1: string;\n column2: string;\n column3: string;\n date: string;\n type: string;\n}\n\nconst CELL_DATA: CellData[] = [\n { column1: 'Row 111', column2: 'Row 221', column3: 'Row 1', date: '09-07-18', type: 'search' },\n { column1: 'Row 112', column2: 'Row 222', column3: 'Row 2', date: '09-08-18', type: 'cart' },\n { column1: 'Row 113', column2: 'Row 223', column3: 'Row 3', date: '02-14-18', type: 'calendar' },\n { column1: 'Row 114', column2: 'Row 224', column3: 'Row 4', date: '12-30-17', type: 'search' },\n { column1: 'Row 115', column2: 'Row 225', column3: 'Row 5', date: '11-12-18', type: 'search' }\n];\n\n@Component({\n selector: 'fd-table-custom-columns-example',\n templateUrl: './table-custom-columns-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, IconComponent, ButtonComponent, UpperCasePipe]\n})\nexport class TableCustomColumnsExampleComponent {\n @ViewChild(TableComponent)\n tableComponent: TableComponent;\n\n displayedColumns: string[];\n originalDisplayedColumns: DisplayedColumn[];\n dataSource = CELL_DATA;\n dialogRef: DialogRef;\n\n constructor(private _dialogService: DialogService) {\n this.displayedColumns = Object.keys(this.dataSource[0]);\n this.originalDisplayedColumns = [];\n\n Object.keys(this.dataSource[0]).forEach((key) => {\n this.originalDisplayedColumns.push({ key, checked: true });\n });\n }\n\n openDialog(): void {\n const dialogRef = this._dialogService.open(TableCustomDialogComponent, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n data: {\n columns: this.originalDisplayedColumns\n }\n });\n\n dialogRef.afterClosed.subscribe(\n (columns) => {\n this.originalDisplayedColumns = [...columns];\n this._propagateChangeToDisplayedValue();\n },\n () => {\n console.log('closed without changes');\n }\n );\n }\n\n private _propagateChangeToDisplayedValue(): void {\n this.displayedColumns = [\n ...this.originalDisplayedColumns.filter((_col) => _col.checked).map((_col) => _col.key)\n ];\n this.tableComponent.reset(this.displayedColumns);\n }\n}\n", "html": "\n \n \n @for (column of displayedColumns; track column) {\n \n }\n \n \n \n @for (row of dataSource; track row) {\n \n \n \n \n \n \n \n }\n \n
    {{ column | uppercase }}
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}
    \n
    \n
    \nChosen Columns: {{ displayedColumns }}\n
    \n
    \n\n" }, - { - "name": "table-focusable-example", - "description": "Table Focusable", - "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", - "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" - }, { "name": "table-popin-example", "description": "Table Popin", "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-popin-example',\n templateUrl: './table-popin-example.component.html',\n styles: [\n `\n .table-example-popin-title {\n margin: 0 0 10px 0;\n }\n `\n ],\n imports: [\n FocusableGridDirective,\n TableModule,\n FormLabelComponent,\n ObjectStatusComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class TablePopinExampleComponent {\n masterCheckbox: boolean | null = false;\n\n fruits: any[] = [\n {\n name: 'Banana',\n status: 'positive',\n statusName: 'Available',\n dateOfExpire: '12.06.2020',\n price: '5 EUR',\n country: 'India',\n description: `A banana is an elongated, edible fruit – botanically a berry – produced by several kinds of large herbaceous\n flowering plants in the genus Musa.`,\n checked: false\n },\n {\n name: 'Apple',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '10.06.2020',\n price: '5,5 EUR',\n country: 'USA',\n description: `An apple is an edible fruit produced by an apple tree (Malus domestica).\n Apple trees are cultivated worldwide and are the most widely grown species in the genus Malus.`,\n checked: false\n },\n {\n name: 'Pineapple',\n status: 'negative',\n statusName: 'Out of stock',\n dateOfExpire: '08.06.2020',\n price: '6 EUR',\n country: 'Mexico',\n description: `The pineapple (Ananas comosus) is a tropical plant with an edible fruit and the most\n economically significant plant in the family Bromeliaceae.`,\n checked: false\n },\n {\n name: 'Orange',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '18.06.2020',\n price: '10 EUR',\n country: 'Spain',\n description: `The orange is the fruit of various citrus species in the family Rutaceae\n (see list of plants known as orange); it primarily refers to Citrus × sinensis.`,\n checked: false\n }\n ];\n\n constructor() {}\n\n select(index: number, checked: boolean): void {\n this.fruits[index].checked = checked;\n\n this._handleMasterCheckboxState();\n }\n\n selectMaster(checked: boolean): void {\n checked ? this._selectAll() : this._deselectAll();\n\n this._handleMasterCheckboxState();\n }\n\n private _handleMasterCheckboxState(): void {\n this.masterCheckbox = this._allSelected() ? true : this._anySelected() ? null : false;\n }\n\n private _selectAll(): void {\n this.fruits.forEach((row) => (row.checked = true));\n }\n\n private _deselectAll(): void {\n this.fruits.forEach((row) => (row.checked = false));\n }\n\n private _anySelected(): boolean {\n return this.fruits.some((_row) => _row.checked);\n }\n\n private _allSelected(): boolean {\n return this.fruits.every((_row) => _row.checked);\n }\n}\n", "html": "
    \n

    Mobile Mode

    \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Tablet Mode

    \n \n \n \n Fruit Description\n Price\n Status\n Date Of Expire\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n {{ fruit.dateOfExpire }}\n \n \n \n \n \n \n \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Desktop Mode

    \n \n \n \n \n \n \n \n \n \n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n \n \n \n \n \n \n \n }\n \n
    NamePriceCountryStatusDate Of ExpireDescription
    \n {{ fruit.name }}\n \n {{ fruit.country }}\n \n {{ fruit.price }}\n \n \n \n {{ fruit.dateOfExpire }}\n \n {{ fruit.description }}\n \n \n
    \n
    \n
    \n

    Popin Mobile Mode with Checkboxes

    \n \n \n \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit; let ind = $index) {\n \n \n \n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n" + }, + { + "name": "table-focusable-example", + "description": "Table Focusable", + "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", + "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" } ] }, @@ -22617,17 +22647,17 @@ "typescript": "import { UpperCasePipe } from '@angular/common';\nimport { Component, ViewChild } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { DialogRef, DialogService } from '@fundamental-ngx/core/dialog';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableComponent, TableModule } from '@fundamental-ngx/core/table';\nimport { TableCustomDialogComponent } from './table-custom-dialog.component';\n\nexport interface DisplayedColumn {\n key: string;\n checked: boolean;\n}\n\nexport interface CellData {\n column1: string;\n column2: string;\n column3: string;\n date: string;\n type: string;\n}\n\nconst CELL_DATA: CellData[] = [\n { column1: 'Row 111', column2: 'Row 221', column3: 'Row 1', date: '09-07-18', type: 'search' },\n { column1: 'Row 112', column2: 'Row 222', column3: 'Row 2', date: '09-08-18', type: 'cart' },\n { column1: 'Row 113', column2: 'Row 223', column3: 'Row 3', date: '02-14-18', type: 'calendar' },\n { column1: 'Row 114', column2: 'Row 224', column3: 'Row 4', date: '12-30-17', type: 'search' },\n { column1: 'Row 115', column2: 'Row 225', column3: 'Row 5', date: '11-12-18', type: 'search' }\n];\n\n@Component({\n selector: 'fd-table-custom-columns-example',\n templateUrl: './table-custom-columns-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, IconComponent, ButtonComponent, UpperCasePipe]\n})\nexport class TableCustomColumnsExampleComponent {\n @ViewChild(TableComponent)\n tableComponent: TableComponent;\n\n displayedColumns: string[];\n originalDisplayedColumns: DisplayedColumn[];\n dataSource = CELL_DATA;\n dialogRef: DialogRef;\n\n constructor(private _dialogService: DialogService) {\n this.displayedColumns = Object.keys(this.dataSource[0]);\n this.originalDisplayedColumns = [];\n\n Object.keys(this.dataSource[0]).forEach((key) => {\n this.originalDisplayedColumns.push({ key, checked: true });\n });\n }\n\n openDialog(): void {\n const dialogRef = this._dialogService.open(TableCustomDialogComponent, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n data: {\n columns: this.originalDisplayedColumns\n }\n });\n\n dialogRef.afterClosed.subscribe(\n (columns) => {\n this.originalDisplayedColumns = [...columns];\n this._propagateChangeToDisplayedValue();\n },\n () => {\n console.log('closed without changes');\n }\n );\n }\n\n private _propagateChangeToDisplayedValue(): void {\n this.displayedColumns = [\n ...this.originalDisplayedColumns.filter((_col) => _col.checked).map((_col) => _col.key)\n ];\n this.tableComponent.reset(this.displayedColumns);\n }\n}\n", "html": "\n \n \n @for (column of displayedColumns; track column) {\n \n }\n \n \n \n @for (row of dataSource; track row) {\n \n \n \n \n \n \n \n }\n \n
    {{ column | uppercase }}
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}
    \n
    \n
    \nChosen Columns: {{ displayedColumns }}\n
    \n
    \n\n" }, - { - "name": "table-focusable-example", - "description": "Table Focusable", - "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", - "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" - }, { "name": "table-popin-example", "description": "Table Popin", "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-popin-example',\n templateUrl: './table-popin-example.component.html',\n styles: [\n `\n .table-example-popin-title {\n margin: 0 0 10px 0;\n }\n `\n ],\n imports: [\n FocusableGridDirective,\n TableModule,\n FormLabelComponent,\n ObjectStatusComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class TablePopinExampleComponent {\n masterCheckbox: boolean | null = false;\n\n fruits: any[] = [\n {\n name: 'Banana',\n status: 'positive',\n statusName: 'Available',\n dateOfExpire: '12.06.2020',\n price: '5 EUR',\n country: 'India',\n description: `A banana is an elongated, edible fruit – botanically a berry – produced by several kinds of large herbaceous\n flowering plants in the genus Musa.`,\n checked: false\n },\n {\n name: 'Apple',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '10.06.2020',\n price: '5,5 EUR',\n country: 'USA',\n description: `An apple is an edible fruit produced by an apple tree (Malus domestica).\n Apple trees are cultivated worldwide and are the most widely grown species in the genus Malus.`,\n checked: false\n },\n {\n name: 'Pineapple',\n status: 'negative',\n statusName: 'Out of stock',\n dateOfExpire: '08.06.2020',\n price: '6 EUR',\n country: 'Mexico',\n description: `The pineapple (Ananas comosus) is a tropical plant with an edible fruit and the most\n economically significant plant in the family Bromeliaceae.`,\n checked: false\n },\n {\n name: 'Orange',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '18.06.2020',\n price: '10 EUR',\n country: 'Spain',\n description: `The orange is the fruit of various citrus species in the family Rutaceae\n (see list of plants known as orange); it primarily refers to Citrus × sinensis.`,\n checked: false\n }\n ];\n\n constructor() {}\n\n select(index: number, checked: boolean): void {\n this.fruits[index].checked = checked;\n\n this._handleMasterCheckboxState();\n }\n\n selectMaster(checked: boolean): void {\n checked ? this._selectAll() : this._deselectAll();\n\n this._handleMasterCheckboxState();\n }\n\n private _handleMasterCheckboxState(): void {\n this.masterCheckbox = this._allSelected() ? true : this._anySelected() ? null : false;\n }\n\n private _selectAll(): void {\n this.fruits.forEach((row) => (row.checked = true));\n }\n\n private _deselectAll(): void {\n this.fruits.forEach((row) => (row.checked = false));\n }\n\n private _anySelected(): boolean {\n return this.fruits.some((_row) => _row.checked);\n }\n\n private _allSelected(): boolean {\n return this.fruits.every((_row) => _row.checked);\n }\n}\n", "html": "
    \n

    Mobile Mode

    \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Tablet Mode

    \n \n \n \n Fruit Description\n Price\n Status\n Date Of Expire\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n {{ fruit.dateOfExpire }}\n \n \n \n \n \n \n \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Desktop Mode

    \n \n \n \n \n \n \n \n \n \n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n \n \n \n \n \n \n \n }\n \n
    NamePriceCountryStatusDate Of ExpireDescription
    \n {{ fruit.name }}\n \n {{ fruit.country }}\n \n {{ fruit.price }}\n \n \n \n {{ fruit.dateOfExpire }}\n \n {{ fruit.description }}\n \n \n
    \n
    \n
    \n

    Popin Mobile Mode with Checkboxes

    \n \n \n \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit; let ind = $index) {\n \n \n \n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n" + }, + { + "name": "table-focusable-example", + "description": "Table Focusable", + "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", + "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" } ] }, @@ -22755,153 +22785,23 @@ "typescript": "import { UpperCasePipe } from '@angular/common';\nimport { Component, ViewChild } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { DialogRef, DialogService } from '@fundamental-ngx/core/dialog';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableComponent, TableModule } from '@fundamental-ngx/core/table';\nimport { TableCustomDialogComponent } from './table-custom-dialog.component';\n\nexport interface DisplayedColumn {\n key: string;\n checked: boolean;\n}\n\nexport interface CellData {\n column1: string;\n column2: string;\n column3: string;\n date: string;\n type: string;\n}\n\nconst CELL_DATA: CellData[] = [\n { column1: 'Row 111', column2: 'Row 221', column3: 'Row 1', date: '09-07-18', type: 'search' },\n { column1: 'Row 112', column2: 'Row 222', column3: 'Row 2', date: '09-08-18', type: 'cart' },\n { column1: 'Row 113', column2: 'Row 223', column3: 'Row 3', date: '02-14-18', type: 'calendar' },\n { column1: 'Row 114', column2: 'Row 224', column3: 'Row 4', date: '12-30-17', type: 'search' },\n { column1: 'Row 115', column2: 'Row 225', column3: 'Row 5', date: '11-12-18', type: 'search' }\n];\n\n@Component({\n selector: 'fd-table-custom-columns-example',\n templateUrl: './table-custom-columns-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, IconComponent, ButtonComponent, UpperCasePipe]\n})\nexport class TableCustomColumnsExampleComponent {\n @ViewChild(TableComponent)\n tableComponent: TableComponent;\n\n displayedColumns: string[];\n originalDisplayedColumns: DisplayedColumn[];\n dataSource = CELL_DATA;\n dialogRef: DialogRef;\n\n constructor(private _dialogService: DialogService) {\n this.displayedColumns = Object.keys(this.dataSource[0]);\n this.originalDisplayedColumns = [];\n\n Object.keys(this.dataSource[0]).forEach((key) => {\n this.originalDisplayedColumns.push({ key, checked: true });\n });\n }\n\n openDialog(): void {\n const dialogRef = this._dialogService.open(TableCustomDialogComponent, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n data: {\n columns: this.originalDisplayedColumns\n }\n });\n\n dialogRef.afterClosed.subscribe(\n (columns) => {\n this.originalDisplayedColumns = [...columns];\n this._propagateChangeToDisplayedValue();\n },\n () => {\n console.log('closed without changes');\n }\n );\n }\n\n private _propagateChangeToDisplayedValue(): void {\n this.displayedColumns = [\n ...this.originalDisplayedColumns.filter((_col) => _col.checked).map((_col) => _col.key)\n ];\n this.tableComponent.reset(this.displayedColumns);\n }\n}\n", "html": "\n \n \n @for (column of displayedColumns; track column) {\n \n }\n \n \n \n @for (row of dataSource; track row) {\n \n \n \n \n \n \n \n }\n \n
    {{ column | uppercase }}
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}
    \n
    \n
    \nChosen Columns: {{ displayedColumns }}\n
    \n
    \n\n" }, - { - "name": "table-focusable-example", - "description": "Table Focusable", - "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", - "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" - }, { "name": "table-popin-example", "description": "Table Popin", "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-popin-example',\n templateUrl: './table-popin-example.component.html',\n styles: [\n `\n .table-example-popin-title {\n margin: 0 0 10px 0;\n }\n `\n ],\n imports: [\n FocusableGridDirective,\n TableModule,\n FormLabelComponent,\n ObjectStatusComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class TablePopinExampleComponent {\n masterCheckbox: boolean | null = false;\n\n fruits: any[] = [\n {\n name: 'Banana',\n status: 'positive',\n statusName: 'Available',\n dateOfExpire: '12.06.2020',\n price: '5 EUR',\n country: 'India',\n description: `A banana is an elongated, edible fruit – botanically a berry – produced by several kinds of large herbaceous\n flowering plants in the genus Musa.`,\n checked: false\n },\n {\n name: 'Apple',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '10.06.2020',\n price: '5,5 EUR',\n country: 'USA',\n description: `An apple is an edible fruit produced by an apple tree (Malus domestica).\n Apple trees are cultivated worldwide and are the most widely grown species in the genus Malus.`,\n checked: false\n },\n {\n name: 'Pineapple',\n status: 'negative',\n statusName: 'Out of stock',\n dateOfExpire: '08.06.2020',\n price: '6 EUR',\n country: 'Mexico',\n description: `The pineapple (Ananas comosus) is a tropical plant with an edible fruit and the most\n economically significant plant in the family Bromeliaceae.`,\n checked: false\n },\n {\n name: 'Orange',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '18.06.2020',\n price: '10 EUR',\n country: 'Spain',\n description: `The orange is the fruit of various citrus species in the family Rutaceae\n (see list of plants known as orange); it primarily refers to Citrus × sinensis.`,\n checked: false\n }\n ];\n\n constructor() {}\n\n select(index: number, checked: boolean): void {\n this.fruits[index].checked = checked;\n\n this._handleMasterCheckboxState();\n }\n\n selectMaster(checked: boolean): void {\n checked ? this._selectAll() : this._deselectAll();\n\n this._handleMasterCheckboxState();\n }\n\n private _handleMasterCheckboxState(): void {\n this.masterCheckbox = this._allSelected() ? true : this._anySelected() ? null : false;\n }\n\n private _selectAll(): void {\n this.fruits.forEach((row) => (row.checked = true));\n }\n\n private _deselectAll(): void {\n this.fruits.forEach((row) => (row.checked = false));\n }\n\n private _anySelected(): boolean {\n return this.fruits.some((_row) => _row.checked);\n }\n\n private _allSelected(): boolean {\n return this.fruits.every((_row) => _row.checked);\n }\n}\n", "html": "
    \n

    Mobile Mode

    \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Tablet Mode

    \n \n \n \n Fruit Description\n Price\n Status\n Date Of Expire\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n {{ fruit.dateOfExpire }}\n \n \n \n \n \n \n \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Desktop Mode

    \n \n \n \n \n \n \n \n \n \n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n \n \n \n \n \n \n \n }\n \n
    NamePriceCountryStatusDate Of ExpireDescription
    \n {{ fruit.name }}\n \n {{ fruit.country }}\n \n {{ fruit.price }}\n \n \n \n {{ fruit.dateOfExpire }}\n \n {{ fruit.description }}\n \n \n
    \n
    \n
    \n

    Popin Mobile Mode with Checkboxes

    \n \n \n \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit; let ind = $index) {\n \n \n \n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n" - } - ] - }, - { - "name": "TableFixedDirective", - "selector": "[fdTableFixed], [fd-table-fixed]", - "library": "@fundamental-ngx/core", - "category": "table", - "description": "The Table directive is used to decorate a table element, displaying data that can be compared. Usually a set of item of the same type which data is divided on columns to facilitate the comparison between items.", - "inputs": [], - "outputs": [], - "slots": [], - "methods": [], - "cssProperties": [], - "sourceFile": "libs/core/table/directives/table-fixed.directive.ts", - "source": "typedoc", - "examples": [ - { - "name": "table-activable-example", - "description": "Table Activable", - "typescript": "import { Component, OnInit } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-activable-example',\n templateUrl: './table-activable-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent]\n})\nexport class TableActivableExampleComponent implements OnInit {\n tableRows: any[];\n\n ngOnInit(): void {\n this.tableRows = [\n {\n column1: {\n text: 'Clicking on any cell'\n },\n column2: {\n text: 'On This Row'\n },\n column3: {\n text: 'Will Cause'\n },\n column4: {\n text: 'Highlight of whole row'\n },\n date: {\n text: '09-07-18'\n },\n activable: true,\n hoverable: true\n },\n {\n column1: {\n text: 'Clicking on cell',\n activable: true\n },\n column2: {\n text: 'On This Row',\n activable: true\n },\n column3: {\n text: 'Will Cause',\n activable: true\n },\n column4: {\n text: 'Highlight of cell',\n activable: true\n },\n date: {\n text: '09-08-18',\n activable: true\n }\n },\n {\n column1: {\n text: 'Hovering On Any Cell',\n hoverable: true\n },\n column2: {\n text: 'Will Change',\n hoverable: true\n },\n column3: {\n text: 'Background',\n hoverable: true\n },\n column4: {\n text: 'Of that cell',\n hoverable: true\n },\n date: {\n text: '02-14-18',\n hoverable: true\n }\n },\n {\n column1: {\n text: 'Hovering on Any Cell'\n },\n column2: {\n text: 'On This Row'\n },\n column3: {\n text: 'Will Change'\n },\n column4: {\n text: 'Background of Whole Row'\n },\n date: {\n text: '12-30-17'\n },\n hoverable: true\n }\n ];\n }\n}\n", - "html": "\n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n }\n \n
    Hovering AndClickingOn Header's CellWill TriggerColor Change
    \n {{ row.column1.text }}\n \n {{ row.column2.text }}\n \n {{ row.column3.text }}\n \n {{ row.column4.text }}\n \n {{ row.date.text }}\n
    \n" - }, - { - "name": "table-cdk-example", - "description": "Table Cdk", - "typescript": "import { CdkDrag, CdkDragHandle, CdkDropList, moveItemInArray } from '@angular/cdk/drag-drop';\nimport { CdkTable, CdkTableModule } from '@angular/cdk/table';\nimport { Component, ViewChild } from '@angular/core';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\nexport interface CellData {\n column1: string;\n column2: string;\n column3: string;\n date: string;\n type: string;\n}\nconst CELL_DATA: CellData[] = [\n { column1: 'Row 1', column2: 'Row 1', column3: 'Row 1', date: '09-07-18', type: 'search' },\n { column1: 'Row 2', column2: 'Row 2', column3: 'Row 2', date: '09-08-18', type: 'cart' },\n { column1: 'Row 3', column2: 'Row 3', column3: 'Row 3', date: '02-14-18', type: 'calendar' },\n { column1: 'Row 4', column2: 'Row 4', column3: 'Row 4', date: '12-30-17', type: 'search' },\n { column1: 'Row 5', column2: 'Row 5', column3: 'Row 5', date: '11-12-18', type: 'search' }\n];\n\n@Component({\n selector: 'fd-table-cdk-example',\n templateUrl: './table-cdk-example.component.html',\n styleUrls: ['table-cdk-example.component.scss'],\n imports: [TableModule, CdkTableModule, CdkDropList, CdkDragHandle, LinkComponent, IconComponent, CdkDrag]\n})\nexport class TableCdkExampleComponent {\n @ViewChild('table') table: CdkTable[]>;\n\n displayedColumns: string[] = ['column1', 'column2', 'column3', 'date', 'type'];\n dataSource = CELL_DATA;\n\n dropRow(event): void {\n const previousIndex = this.dataSource.findIndex((d) => d === event.item.data);\n moveItemInArray(this.dataSource, previousIndex, event.currentIndex);\n this.table.renderRows();\n }\n}\n", - "html": "\n \n \n Column 1\n \n {{ cell.column1 }}\n \n \n\n \n Column 2\n {{ cell.column2 }}\n \n\n \n Column 3\n {{ cell.column3 }}\n \n\n \n Date\n {{ cell.date }}\n \n\n \n Type\n \n \n \n \n\n \n \n \n\n" - }, - { - "name": "table-checkboxes-example", - "description": "Table Checkboxes", - "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FocusableGridDirective, RangeSelector } from '@fundamental-ngx/cdk/utils';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-checkboxes-example',\n templateUrl: './table-checkboxes-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n ContentDensityDirective,\n CheckboxComponent,\n FormsModule,\n LinkComponent,\n IconComponent\n ]\n})\nexport class TableCheckboxesExampleComponent {\n checkboxValue: boolean | null = false;\n checkboxValueCompact: boolean | null = false;\n checkboxValueCondensed: boolean | null = false;\n\n tableRows: any[] = [\n {\n column1: 'user.name@email.com',\n column2: 'Row 1',\n column3: 'Row 1',\n date: '09-07-18',\n checked: false\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3: 'Row 2',\n date: '09-07-18',\n checked: false\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '09-07-18',\n checked: false\n }\n ];\n\n tableRowsCompact = [\n {\n column1: 'user.name@email.com',\n column2: 'Row 1',\n column3: 'Row 1',\n date: '09-07-18',\n type: 'search',\n checked: false\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'cart',\n checked: false\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '09-07-18',\n type: 'calendar',\n checked: false\n }\n ];\n\n tableRowsCondensed: Record[] = [\n {\n column1: 'user.name@email.com',\n column2: 'Row 1',\n column3: 'Row 1',\n date: '09-07-18',\n type: 'search',\n checked: false\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'cart',\n checked: false\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '09-07-18',\n type: 'calendar',\n checked: false\n }\n ];\n\n private readonly _rangeSelector = new RangeSelector();\n\n select(index: number, event: MouseEvent, size: string): void {\n // using rangeSelector utility to be able to select multiple rows while \"shift\" is pressed\n const checkedToggled = !this._getTable(size)[index].checked;\n this._rangeSelector.onRangeElementToggled(index, event);\n this._rangeSelector.applyValueToEachInRange((idx) => (this._getTable(size)[idx].checked = checkedToggled));\n this._setValue(size);\n }\n\n selectAll(checked: boolean, size: string): void {\n if (size === 'cozy') {\n this.checkboxValue = checked;\n } else if (size === 'compact') {\n this.checkboxValueCompact = checked;\n } else if (size === 'condensed') {\n this.checkboxValueCondensed = checked;\n }\n if (checked) {\n this._selectAll(size);\n } else {\n this._deselectAll(size);\n }\n }\n\n private _selectAll(size: string): void {\n this._getTable(size).forEach((row) => (row.checked = true));\n }\n\n private _deselectAll(size: string): void {\n this._getTable(size).forEach((row) => (row.checked = false));\n }\n\n private _getSelectAllValue(size: string): boolean | null {\n const table = this._getTable(size);\n const checked = table.filter((row) => row.checked);\n if (checked.length === table.length) {\n return true;\n } else if (!checked.length) {\n return false;\n }\n // returning null to set selection state to \"indeterminate\"\n return null;\n }\n\n private _getTable(size: string): any[] {\n let table = this.tableRows;\n if (size === 'compact') {\n table = this.tableRowsCompact;\n } else if (size === 'condensed') {\n table = this.tableRowsCondensed;\n }\n return table;\n }\n\n private _setValue(size: string): void {\n if (size === 'cozy') {\n this.checkboxValue = this._getSelectAllValue(size);\n } else if (size === 'compact') {\n this.checkboxValueCompact = this._getSelectAllValue(size);\n } else if (size === 'condensed') {\n this.checkboxValueCondensed = this._getSelectAllValue(size);\n }\n }\n}\n", - "html": "Table With Checkbox Cozy Mode\n\n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row; let i = $index) {\n \n \n \n \n \n \n \n }\n \n
    \n \n Column 1Column 2Column 3Date
    \n \n \n {{ row.column1 }}\n \n {{ row.column2 }}\n \n {{ row.column3 }}\n \n {{ row.date }}\n
    \n
    \nTable With Checkbox Compact Mode\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRowsCompact; track row; let i = $index) {\n \n \n \n \n \n \n \n \n }\n \n
    \n \n Column 1Column 2Column 3DateType
    \n \n \n {{ row.column1 }}\n \n {{ row.column2 }}\n \n {{ row.column3 }}\n \n {{ row.date }}\n
    \n
    \nTable With Checkbox Condensed Mode\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRowsCondensed; track row; let i = $index) {\n \n \n \n \n \n \n \n \n }\n \n
    \n \n Column 1Column 2Column 3DateType
    \n \n \n {{ row.column1 }}\n \n {{ row.column2 }}\n \n {{ row.column3 }}\n \n {{ row.date }}\n
    \n" - }, - { - "name": "table-column-sorting-example", - "description": "Table Column Sorting", - "typescript": "import { LiveAnnouncer } from '@angular/cdk/a11y';\n\nimport { ChangeDetectionStrategy, Component, OnInit, Pipe, PipeTransform } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { FormControlComponent, FormItemComponent, FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { TableModule } from '@fundamental-ngx/core/table';\nimport { ToolbarComponent, ToolbarSpacerDirective } from '@fundamental-ngx/core/toolbar';\n\nconst sort = (a, b, key?: string): number => {\n if (key) {\n return a[key] > b[key] ? 1 : -1;\n } else {\n return a > b ? 1 : -1;\n }\n};\n\n@Pipe({\n name: 'sortBy',\n pure: false,\n standalone: true\n})\nexport class SortByPipe implements PipeTransform {\n transform(tableRows: any[], ascending: boolean, sortKey?: string): any[] {\n const ascModifier: number = ascending ? 1 : -1;\n tableRows.sort((a, b) => sort(a, b, sortKey) * ascModifier);\n return tableRows;\n }\n}\n\n@Pipe({\n name: 'filter',\n standalone: true\n})\nexport class FilterPipe implements PipeTransform {\n transform(values: any[] = [], searchTerm: string = '', key: string = ''): any[] {\n if (!searchTerm) {\n return values;\n }\n if (key) {\n values = values.filter((item) => item[key].toLocaleLowerCase().includes(searchTerm.toLocaleLowerCase()));\n } else {\n values = values.filter((item) => item.toLocaleLowerCase().includes(searchTerm.toLocaleLowerCase()));\n }\n return values;\n }\n}\n\nconst rows = [\n {\n column1: 'Apple',\n column2: 'Row 1',\n column3: 'Row 1',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'Banana',\n column2: 'Row 2',\n column3: 'Row 2',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'Kiwi',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'Peach',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'Strawberry',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n];\n\ninterface ExampleRow {\n column1: any;\n column2?: any;\n column3?: any;\n date?: any;\n type?: any;\n}\n\n@Component({\n selector: 'fd-table-column-sorting-example',\n templateUrl: './table-column-sorting-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ToolbarComponent,\n ToolbarSpacerDirective,\n ContentDensityDirective,\n InputGroupModule,\n FormsModule,\n ButtonComponent,\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n IconComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n ListModule,\n FormItemComponent,\n FormLabelComponent,\n FormControlComponent,\n SortByPipe,\n FilterPipe\n ]\n})\nexport class TableColumnSortingExampleComponent implements OnInit {\n tableRows: ExampleRow[];\n displayedRows: ExampleRow[];\n tableRows2: ExampleRow[];\n displayedRows2: ExampleRow[];\n ascending = true;\n ascending2 = true;\n filterVal = '';\n filterVal2 = '';\n open = false;\n\n constructor(private liveAnnouncer: LiveAnnouncer) {}\n\n sortColumn1(asc: boolean): void {\n this.ascending2 = asc;\n this.open = false;\n }\n\n inputKeyup(event: KeyboardEvent): void {\n if (event.key === 'Enter' || event.key === 'Esc') {\n this.open = false;\n }\n }\n\n async changeSort(asc: boolean): Promise {\n this.ascending = asc;\n await this.liveAnnouncer.announce(`Set sort ${asc ? 'ascending' : 'descending'}`, 'assertive');\n }\n\n ngOnInit(): void {\n this.tableRows = [...rows];\n this.displayedRows = this.tableRows;\n this.tableRows2 = [...rows];\n this.displayedRows2 = this.tableRows2;\n }\n}\n", - "html": "

    Sorting and filtering with toolbar elements:

    \n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n @for (row of displayedRows | filter: filterVal : 'column1' | sortBy: ascending : 'column1'; track row) {\n \n \n \n \n \n \n \n }\n \n
    Column 1Column 2Column 3DateType
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}\n \n
    \n

    Sorting and filtering with inline popover:

    \n\n \n \n \n \n \n \n \n \n \n \n @for (row of displayedRows2 | filter: filterVal2 : 'column1' | sortBy: ascending2 : 'column1'; track row) {\n \n \n \n \n \n \n \n }\n \n
    \n \n \n
    \n Column 1\n \n
    \n
    \n \n
      \n
    • \n \n Sort Ascending\n
    • \n
    • \n \n Sort Descending\n
    • \n
    • \n \n
      \n \n \n
      \n
    • \n
    \n
    \n
    \n
    Column 2Column 3DateType
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}\n \n
    \n" - }, - { - "name": "table-example", - "description": "Table", - "typescript": "import { Component, OnInit } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-example',\n templateUrl: './table-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, IconComponent]\n})\nexport class TableExampleComponent implements OnInit {\n tableRows: any[];\n\n ngOnInit(): void {\n this.tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n }\n}\n", - "html": "\n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n {{ row.column2 }}\n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}
    \n\n

    \n

    individual non-interactive header cells

    \n\n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n }\n \n
    Non-interactive Column HeaderColumn HeaderColumn HeaderColumn HeaderNon-interactive Column Header
    \n {{ row.column1 }}\n \n

    \n {{ row.column2 }}\n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}
    \n\n

    \n

    non-interactive header cells

    \n\n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n {{ row.column2 }}\n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}
    \n" - }, - { - "name": "table-fixed-example", - "description": "Table Fixed", - "typescript": "import { Component, OnInit } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-fixed-example',\n templateUrl: './table-fixed-example.component.html',\n imports: [TableModule, FocusableGridDirective, LinkComponent, IconComponent]\n})\nexport class TableFixedExampleComponent implements OnInit {\n tableRows: any[];\n\n ngOnInit(): void {\n this.tableRows = [\n {\n column1: 'user.name@email.com',\n column2: 'Test',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3: 'Test',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 6',\n column3: 'Row 6',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 7',\n column3: 'Row 7',\n date: '11-12-18',\n type: 'search'\n }\n ];\n }\n}\n", - "html": "
    \n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n }\n \n \n \n \n \n \n \n \n \n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n {{ row.column2 }}\n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}
    Footer Cell
    \n
    \n" - }, - { - "name": "table-footer-example", - "description": "Table Footer", - "typescript": "import { Component, OnInit } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-footer-example',\n templateUrl: './table-footer-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, IconComponent]\n})\nexport class TableFooterExampleComponent implements OnInit {\n tableRows: any[];\n\n ngOnInit(): void {\n this.tableRows = [\n {\n column1: 'user.name@email.com',\n column2: 'Row 1',\n column3: 'Row 1',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3: 'Row 2',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n }\n}\n", - "html": "\n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n }\n \n \n \n \n \n \n \n \n \n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}
    Footer Cell
    \n" - }, - { - "name": "table-navigatable-row-example", - "description": "Table Navigatable Row", - "typescript": "import { Component, computed, inject } from '@angular/core';\n\nimport { RouterLink } from '@angular/router';\nimport { FocusableGridDirective, RtlService } from '@fundamental-ngx/cdk/utils';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ObjectStatus, ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\ninterface TableIem {\n column1: string;\n column2: string;\n column3: string;\n date: string;\n navigatable: boolean;\n active: boolean;\n}\n\ninterface TableMobileItem {\n name: string;\n status: ObjectStatus;\n statusName: string;\n dateOfExpire: string;\n price: string;\n country: string;\n description: string;\n navigatable: boolean;\n}\n\n@Component({\n selector: 'fd-table-navigatable-row-example',\n templateUrl: './table-navigatable-row-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, RouterLink, FormLabelComponent, ObjectStatusComponent]\n})\nexport class TableNavigatableRowExampleComponent {\n navigatableRows: TableIem[] = [\n {\n column1: 'user.name@email.com',\n column2: 'Row 1',\n column3: 'Row 1',\n date: '09-07-18',\n navigatable: true,\n active: false\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3: 'Row 2',\n date: '09-07-18',\n navigatable: false,\n active: false\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '09-07-18',\n navigatable: true,\n active: false\n }\n ];\n\n fruits: TableMobileItem[] = [\n {\n name: 'Banana',\n status: 'positive',\n statusName: 'Available',\n dateOfExpire: '12.06.2020',\n price: '5 EUR',\n country: 'India',\n description: `A banana is an elongated, edible fruit – botanically a berry – produced by several kinds of large herbaceous\n flowering plants in the genus Musa.`,\n navigatable: true\n },\n {\n name: 'Apple',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '10.06.2020',\n price: '5,5 EUR',\n country: 'USA',\n description: `An apple is an edible fruit produced by an apple tree (Malus domestica).\n Apple trees are cultivated worldwide and are the most widely grown species in the genus Malus.`,\n navigatable: false\n }\n ];\n\n protected readonly navigationArrow = computed(() =>\n this._rtlService?.rtl() ? 'sap-icon--navigation-left-arrow' : 'sap-icon--navigation-right-arrow'\n );\n\n private readonly _rtlService = inject(RtlService, { optional: true });\n\n alert(row: any): void {\n if (row.navigatable) {\n alert('Navigation event took place!');\n }\n }\n\n setActiveItem(index: number): void {\n this.navigatableRows.map((item, rowIndex) => {\n item.active = rowIndex === index;\n return item;\n });\n this.alert(this.navigatableRows[index]);\n }\n}\n", - "html": "

    \n Entire row is navigatable, used with icon and highlighted active item.\n

    \n\n \n \n \n \n \n \n \n \n \n \n @for (row of navigatableRows; track row; let i = $index) {\n \n \n \n \n \n \n \n }\n \n
    Column 1Column 2Column 3Date
    \n {{ row.column1 }}\n \n {{ row.column2 }}\n \n {{ row.column3 }}\n \n {{ row.date }}\n \n @if (row.navigatable) {\n \n }\n
    \n
    \n

    Row with navigation button

    \n\n \n \n \n \n \n \n \n \n \n \n @for (row of navigatableRows; track row) {\n \n \n \n \n \n \n \n }\n \n
    Column 1Column 2Column 3Column 4
    \n {{ row.column1 }}\n \n

    {{ row.column2 }}

    \n
    \n {{ row.column3 }}\n \n {{ row.date }}\n \n \n \n \n
    \n
    \n

    Mobile Mode

    \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n @if (fruit.navigatable) {\n \n }\n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n" - }, - { - "name": "table-page-scroll-example", - "description": "Table Page Scroll", - "typescript": "import { Component, OnInit } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableModule } from '@fundamental-ngx/core/table';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarLabelDirective } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-table-page-scroll-example',\n templateUrl: './table-page-scroll-example.component.html',\n imports: [\n TableModule,\n FocusableGridDirective,\n LinkComponent,\n IconComponent,\n ToolbarComponent,\n TitleComponent,\n ToolbarItemDirective,\n ToolbarLabelDirective\n ]\n})\nexport class TablePageScrollExampleComponent implements OnInit {\n tableRows: any[];\n\n ngOnInit(): void {\n this.tableRows = [\n {\n column1: 'user.name@email.com',\n column2: 'Row 1',\n column3: 'Row 1',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3: 'Row 2',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 6',\n column3: 'Row 6',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 7',\n column3: 'Row 7',\n date: '11-12-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 8',\n column3: 'Row 8',\n date: '11-12-19',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 9',\n column3: 'Row 9',\n date: '11-12-20',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 10',\n column3: 'Row 10',\n date: '11-12-21',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 11',\n column3: 'Row 11',\n date: '11-12-21',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 12',\n column3: 'Row 12',\n date: '11-12-21',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 13',\n column3: 'Row 13',\n date: '11-12-21',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 14',\n column3: 'Row 14',\n date: '11-12-21',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 15',\n column3: 'Row 15',\n date: '11-12-21',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 16',\n column3: 'Row 16',\n date: '11-12-21',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 17',\n column3: 'Row 17',\n date: '11-12-21',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 18',\n column3: 'Row 18',\n date: '11-12-21',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 19',\n column3: 'Row 19',\n date: '11-12-21',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 20',\n column3: 'Row 20',\n date: '11-12-21',\n type: 'search'\n }\n ];\n }\n}\n", - "html": "
    \n
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Commodi aut fugiat veritatis harum doloribus?\n Doloremque quo animi, illum ut officiis repellendus, dolorem, architecto quisquam placeat vel nihil ratione\n temporibus! Voluptas. Lorem ipsum dolor sit amet consectetur adipisicing elit. Commodi aut fugiat veritatis\n harum doloribus? Doloremque quo animi, illum ut officiis repellendus, dolorem, architecto quisquam placeat vel\n nihil ratione temporibus! Voluptas. Lorem ipsum dolor sit amet consectetur adipisicing elit. Commodi aut fugiat\n veritatis harum doloribus? Doloremque quo animi, illum ut officiis repellendus, dolorem, architecto quisquam\n placeat vel nihil ratione temporibus! Voluptas. Lorem ipsum dolor sit amet consectetur adipisicing elit. Commodi\n aut fugiat veritatis harum doloribus? Doloremque quo animi, illum ut officiis repellendus, dolorem, architecto\n quisquam placeat vel nihil ratione temporibus! Voluptas.


    \n
    \n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n }\n \n \n \n \n \n \n \n \n \n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n {{ row.column2 }}\n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}
    Footer Cell
    \n
    \n
    \n" - }, - { - "name": "table-pagination-example", - "description": "Table Pagination", - "typescript": "import { Component, OnInit, ViewChild } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuComponent } from '@fundamental-ngx/core/menu';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { TableModule } from '@fundamental-ngx/core/table';\nimport { ToolbarItemDirective } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-table-pagination-example',\n templateUrl: './table-pagination-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, IconComponent, PaginationModule, ToolbarItemDirective]\n})\nexport class TablePaginationExampleComponent implements OnInit {\n @ViewChild('itemsPerPageMenu')\n itemsPerPageMenu: MenuComponent;\n\n tableRows: any[];\n displayedRows: any[];\n totalItems = 30;\n itemsPerPage = 5;\n currentPage = 3;\n itemsPerPageOptions: number[] = [3, 5, 10];\n\n newPageClicked(pageNumber: number): void {\n this.currentPage = pageNumber;\n const firstDisplayedRow = (pageNumber - 1) * this.itemsPerPage;\n this.displayedRows = this.tableRows.slice(firstDisplayedRow, firstDisplayedRow + this.itemsPerPage);\n if (this.itemsPerPageMenu) {\n this.itemsPerPageMenu.close();\n }\n }\n\n itemsPerPageChange(value: number): void {\n this.itemsPerPage = value;\n this.newPageClicked(this.currentPage);\n }\n\n ngOnInit(): void {\n this.tableRows = [\n {\n column1: 'Row 1',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'Row 2',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'Row 5',\n date: '11-12-18',\n type: 'search'\n },\n {\n column1: 'Row 6',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'Row 7',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'Row 8',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'Row 9',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'Row 10',\n date: '11-12-18',\n type: 'search'\n },\n {\n column1: 'Row 11',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'Row 12',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'Row 13',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'Row 14',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'Row 15',\n date: '11-12-18',\n type: 'search'\n },\n {\n column1: 'Row 16',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'Row 17',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'Row 18',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'Row 19',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'Row 20',\n date: '11-12-18',\n type: 'search'\n },\n {\n column1: 'Row 21',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'Row 21',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'Row 23',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'Row 24',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'Row 25',\n date: '11-12-18',\n type: 'search'\n },\n {\n column1: 'Row 26',\n date: '11-12-18',\n type: 'search'\n },\n {\n column1: 'Row 27',\n date: '11-12-18',\n type: 'search'\n },\n {\n column1: 'Row 28',\n date: '11-12-20',\n type: 'search'\n },\n {\n column1: 'Row 29',\n date: '11-12-21',\n type: 'search'\n },\n {\n column1: 'Row 30',\n date: '11-12-22',\n type: 'search'\n }\n ];\n\n this.newPageClicked(3);\n }\n}\n", - "html": "\n \n \n \n \n \n \n \n \n @for (row of displayedRows; track row; let i = $index) {\n \n \n \n \n \n }\n \n
    \n \n \n \n \n \n
    Column HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n {{ row.date }}\n \n {{ row.column1 }}\n
    \n
    \n \n
    \n
    \n" - }, - { - "name": "table-responsive-example", - "description": "Table Responsive", - "typescript": "import { Component, OnInit } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-responsive-example',\n templateUrl: './table-responsive-example.component.html',\n styleUrls: ['table-responsive-example.component.scss'],\n imports: [TableModule, FocusableGridDirective, LinkComponent, IconComponent]\n})\nexport class TableResponsiveExampleComponent implements OnInit {\n tableRows: any[];\n\n ngOnInit(): void {\n this.tableRows = [\n {\n column1: 'Row 1',\n column2: 'Row 1',\n column3: 'Row 1',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'Row 2',\n column2: 'Row 2',\n column3: 'Row 2',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'Row 3',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'Row 4',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'Row 5',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n }\n}\n", - "html": "
    \n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n }\n \n
    Column 1Column 2Column 3DateType
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}
    \n
    \n" - }, - { - "name": "table-semantic-example", - "description": "Table Semantic", - "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FocusableGridDirective, RangeSelector } from '@fundamental-ngx/cdk/utils';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableModule, TableStatuses } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-semantic-example',\n templateUrl: './table-semantic-example.component.html',\n imports: [FocusableGridDirective, TableModule, CheckboxComponent, FormsModule, LinkComponent]\n})\nexport class TableSemanticExampleComponent {\n isAllSelected: boolean | null = false;\n\n tableRows: RowData[] = [\n {\n status: null,\n column1: 'user.name@email.com',\n column2: 'Row 1',\n column3: 'Row 1',\n date: '09-07-18',\n checked: false\n },\n {\n status: 'valid',\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3: 'Row 2',\n date: '09-07-18',\n checked: false\n },\n {\n status: null,\n column1: 'user.name@email.com',\n column2: 'Row 1',\n column3: 'Row 1',\n date: '09-07-18',\n checked: false\n },\n {\n status: 'warning',\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '09-07-18',\n checked: false\n },\n {\n status: null,\n column1: 'user.name@email.com',\n column2: 'Row 1',\n column3: 'Row 1',\n date: '09-07-18',\n checked: false\n },\n {\n status: 'information',\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3: 'Row 2',\n date: '09-07-18',\n checked: false\n },\n {\n status: null,\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '09-07-18',\n checked: false\n },\n {\n status: 'error',\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '09-07-18',\n checked: false\n }\n ];\n\n private readonly _rangeSelector = new RangeSelector();\n\n select(index: number, event: MouseEvent): void {\n // using rangeSelector utility to be able to select multiple rows while \"shift\" is pressed\n const checkedToggled = !this.tableRows[index].checked;\n this._rangeSelector.onRangeElementToggled(index, event);\n this._rangeSelector.applyValueToEachInRange((idx) => (this.tableRows[idx].checked = checkedToggled));\n this.isAllSelected = this._getSelectAllValue();\n }\n\n selectAll(checked: boolean): void {\n this.isAllSelected = checked;\n if (checked) {\n this._selectAll();\n } else {\n this._deselectAll();\n }\n }\n\n getRowAriaLabel(row: RowData, index: number): string {\n let ariaLabel = 'Select row ' + (index + 1);\n if (row.status) {\n ariaLabel += ', ' + row.status;\n }\n return ariaLabel;\n }\n\n private _selectAll(): void {\n this.tableRows.forEach((row) => (row.checked = true));\n }\n\n private _deselectAll(): void {\n this.tableRows.forEach((row) => (row.checked = false));\n }\n\n private _getSelectAllValue(): boolean | null {\n const checked = this.tableRows.filter((row) => row.checked);\n if (checked.length === this.tableRows.length) {\n return true;\n } else if (!checked.length) {\n return false;\n }\n // returning null to set selection state to \"indeterminate\"\n return null;\n }\n}\n\ninterface RowData {\n status: TableStatuses | null;\n column1: string;\n column2: string;\n column3: string;\n date: string;\n checked: boolean;\n}\n", - "html": "\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row; let i = $index) {\n \n \n \n \n \n \n \n \n }\n \n
    \n \n Column 1Column 2Column 3Date
    \n \n \n {{ row.column1 }}\n \n {{ row.column2 }}\n \n {{ row.column3 }}\n \n {{ row.date }}\n
    \n" - }, - { - "name": "table-toolbar-example", - "description": "Table Toolbar", - "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\n\nimport { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit, TemplateRef } from '@angular/core';\nimport { FormBuilder, FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BusyIndicatorComponent } from '@fundamental-ngx/core/busy-indicator';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { DialogModule, DialogService } from '@fundamental-ngx/core/dialog';\nimport { FormControlComponent, FormItemComponent, FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TableModule } from '@fundamental-ngx/core/table';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSpacerDirective } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-table-toolbar-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './table-toolbar-example.component.html',\n imports: [\n ToolbarComponent,\n TitleComponent,\n ToolbarSpacerDirective,\n InputGroupModule,\n FormsModule,\n ButtonComponent,\n ToolbarItemDirective,\n BusyIndicatorComponent,\n FocusableGridDirective,\n TableModule,\n DialogModule,\n CdkScrollable,\n ScrollbarDirective,\n ReactiveFormsModule,\n FormItemComponent,\n FormLabelComponent,\n FormControlComponent,\n BarModule\n ]\n})\nexport class TableToolbarExampleComponent implements OnInit {\n tableRows: any[];\n displayedRows: any[];\n searchTerm = '';\n confirmationReason: string;\n myForm: FormGroup;\n loading = false;\n\n constructor(\n private _dialogService: DialogService,\n private _fb: FormBuilder,\n private _cdr: ChangeDetectorRef\n ) {}\n\n ngOnInit(): void {\n this.tableRows = [\n {\n column1: 'Apple',\n column2: 'Fruit',\n region: 'Virginia'\n },\n {\n column1: 'Banana',\n column2: 'Fruit',\n region: 'Costa Rica'\n },\n {\n column1: 'Kale',\n column2: 'Vegetable',\n region: 'Colorado'\n },\n {\n column1: 'Kiwi',\n column2: 'Fruit',\n region: 'New Zealand'\n },\n {\n column1: 'Spinach',\n column2: 'Vegetable',\n region: 'California'\n }\n ];\n this.displayedRows = this.tableRows;\n\n this.myForm = this._fb.group({\n nameInput: new FormControl(''),\n typeInput: new FormControl(''),\n regionInput: new FormControl('')\n });\n }\n\n searchInputChanged(event: string): void {\n const filterRows = (row): boolean => {\n const keys = Object.keys(row);\n return !!keys.find((key) => row[key].toLowerCase().includes(event.toLowerCase()));\n };\n\n if (event) {\n this.displayedRows = this.tableRows.filter((row) => filterRows(row));\n } else {\n this.displayedRows = this.tableRows;\n }\n }\n\n resetSearch(): void {\n this.displayedRows = this.tableRows;\n this.searchTerm = '';\n }\n\n openDialog(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, { responsivePadding: true });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.confirmationReason = 'Dialog closed with result: ' + result;\n this.tableRows.push({\n column1: this.myForm.get('nameInput')?.value,\n column2: this.myForm.get('typeInput')?.value,\n region: this.myForm.get('regionInput')?.value\n });\n this.searchInputChanged(this.searchTerm);\n this.myForm.setValue({ nameInput: '', typeInput: '', regionInput: '' });\n this._cdr.detectChanges();\n },\n (error) => {\n this.confirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", - "html": "\n

    Table Toolbar Label ({{ tableRows.length }} rows)

    \n \n \n \n \n \n
    \n\n \n \n \n \n \n \n \n \n \n @for (row of displayedRows; track row) {\n \n \n \n \n \n }\n @if (!displayedRows || !displayedRows.length) {\n \n \n \n }\n \n
    NameTypeRegion Harvested
    {{ row.column1 }}{{ row.column2 }}{{ row.region }}
    No Results Found!
    \n
    \n\n \n \n

    New Item

    \n \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n
    \n
    \n" - }, - { - "name": "table-without-borders-example", - "description": "Table Without Borders", - "typescript": "import { Component, OnInit } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-without-borders-example',\n templateUrl: './table-without-borders-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, IconComponent]\n})\nexport class TableWithoutBordersExampleComponent implements OnInit {\n tableRows: any[];\n\n ngOnInit(): void {\n this.tableRows = [\n {\n column1: 'user.name@email.com',\n column2: 'Row 1',\n column3: 'Row 1',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3: 'Row 2',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n }\n}\n", - "html": "Table without Borders\n\n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}
    \n
    \nTable without Borders on Body\n\n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}
    \n
    \n" - }, - { - "name": "table-loading-example", - "description": "Table Loading", - "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective, range } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { SkeletonComponent } from '@fundamental-ngx/core/skeleton';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-loading-example',\n templateUrl: './table-loading-example.component.html',\n imports: [ButtonComponent, FocusableGridDirective, TableModule, SkeletonComponent]\n})\nexport class TableLoadingExampleComponent {\n loading = true;\n readonly loadingRange = range(3);\n}\n", - "html": "\n\n \n \n \n \n \n \n \n \n @if (!loading) {\n @for (rowI of loadingRange; track rowI) {\n \n @for (colI of loadingRange; track colI) {\n \n }\n \n }\n } @else {\n @for (_ of loadingRange; track $index) {\n \n @for (_ of loadingRange; track $index) {\n \n }\n \n }\n }\n \n
    Column 1Column 2Column 3
    Row {{ rowI + 1 }}, Col {{ colI + 1 }}
    \n \n
    \n" - }, - { - "name": "no-data-example", - "description": "No Data", - "typescript": "import { Component } from '@angular/core';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { IllustratedMessageModule } from '@fundamental-ngx/core/illustrated-message';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fdp-platform-table-no-data-example',\n templateUrl: './no-data-example.component.html',\n imports: [TableModule, LinkComponent, IconComponent, IllustratedMessageModule]\n})\nexport class NoDataExampleComponent {\n tableRows = [];\n\n sceneConfig = {\n scene: {\n url: 'assets/images/sapIllus-Scene-NoMail.svg',\n id: 'sapIllus-Scene-NoMail-1'\n },\n dialog: {\n url: 'assets/images/sapIllus-Dialog-NoMail.svg',\n id: 'sapIllus-Dialog-NoMail'\n }\n };\n}\n", - "html": "\n \n \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n

    Headline text goes here

    \n

    \n Description provides user with clarity and possible next steps.\n

    \n
    \n \n
    \n
    \n \n
    \n \n
    Column HeaderColumn HeaderColumn Header
    \n" - }, - { - "name": "table-custom-columns-example", - "description": "Table Custom Columns", - "typescript": "import { UpperCasePipe } from '@angular/common';\nimport { Component, ViewChild } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { DialogRef, DialogService } from '@fundamental-ngx/core/dialog';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableComponent, TableModule } from '@fundamental-ngx/core/table';\nimport { TableCustomDialogComponent } from './table-custom-dialog.component';\n\nexport interface DisplayedColumn {\n key: string;\n checked: boolean;\n}\n\nexport interface CellData {\n column1: string;\n column2: string;\n column3: string;\n date: string;\n type: string;\n}\n\nconst CELL_DATA: CellData[] = [\n { column1: 'Row 111', column2: 'Row 221', column3: 'Row 1', date: '09-07-18', type: 'search' },\n { column1: 'Row 112', column2: 'Row 222', column3: 'Row 2', date: '09-08-18', type: 'cart' },\n { column1: 'Row 113', column2: 'Row 223', column3: 'Row 3', date: '02-14-18', type: 'calendar' },\n { column1: 'Row 114', column2: 'Row 224', column3: 'Row 4', date: '12-30-17', type: 'search' },\n { column1: 'Row 115', column2: 'Row 225', column3: 'Row 5', date: '11-12-18', type: 'search' }\n];\n\n@Component({\n selector: 'fd-table-custom-columns-example',\n templateUrl: './table-custom-columns-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, IconComponent, ButtonComponent, UpperCasePipe]\n})\nexport class TableCustomColumnsExampleComponent {\n @ViewChild(TableComponent)\n tableComponent: TableComponent;\n\n displayedColumns: string[];\n originalDisplayedColumns: DisplayedColumn[];\n dataSource = CELL_DATA;\n dialogRef: DialogRef;\n\n constructor(private _dialogService: DialogService) {\n this.displayedColumns = Object.keys(this.dataSource[0]);\n this.originalDisplayedColumns = [];\n\n Object.keys(this.dataSource[0]).forEach((key) => {\n this.originalDisplayedColumns.push({ key, checked: true });\n });\n }\n\n openDialog(): void {\n const dialogRef = this._dialogService.open(TableCustomDialogComponent, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n data: {\n columns: this.originalDisplayedColumns\n }\n });\n\n dialogRef.afterClosed.subscribe(\n (columns) => {\n this.originalDisplayedColumns = [...columns];\n this._propagateChangeToDisplayedValue();\n },\n () => {\n console.log('closed without changes');\n }\n );\n }\n\n private _propagateChangeToDisplayedValue(): void {\n this.displayedColumns = [\n ...this.originalDisplayedColumns.filter((_col) => _col.checked).map((_col) => _col.key)\n ];\n this.tableComponent.reset(this.displayedColumns);\n }\n}\n", - "html": "\n \n \n @for (column of displayedColumns; track column) {\n \n }\n \n \n \n @for (row of dataSource; track row) {\n \n \n \n \n \n \n \n }\n \n
    {{ column | uppercase }}
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}
    \n
    \n
    \nChosen Columns: {{ displayedColumns }}\n
    \n
    \n\n" }, { "name": "table-focusable-example", "description": "Table Focusable", "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" - }, - { - "name": "table-popin-example", - "description": "Table Popin", - "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-popin-example',\n templateUrl: './table-popin-example.component.html',\n styles: [\n `\n .table-example-popin-title {\n margin: 0 0 10px 0;\n }\n `\n ],\n imports: [\n FocusableGridDirective,\n TableModule,\n FormLabelComponent,\n ObjectStatusComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class TablePopinExampleComponent {\n masterCheckbox: boolean | null = false;\n\n fruits: any[] = [\n {\n name: 'Banana',\n status: 'positive',\n statusName: 'Available',\n dateOfExpire: '12.06.2020',\n price: '5 EUR',\n country: 'India',\n description: `A banana is an elongated, edible fruit – botanically a berry – produced by several kinds of large herbaceous\n flowering plants in the genus Musa.`,\n checked: false\n },\n {\n name: 'Apple',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '10.06.2020',\n price: '5,5 EUR',\n country: 'USA',\n description: `An apple is an edible fruit produced by an apple tree (Malus domestica).\n Apple trees are cultivated worldwide and are the most widely grown species in the genus Malus.`,\n checked: false\n },\n {\n name: 'Pineapple',\n status: 'negative',\n statusName: 'Out of stock',\n dateOfExpire: '08.06.2020',\n price: '6 EUR',\n country: 'Mexico',\n description: `The pineapple (Ananas comosus) is a tropical plant with an edible fruit and the most\n economically significant plant in the family Bromeliaceae.`,\n checked: false\n },\n {\n name: 'Orange',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '18.06.2020',\n price: '10 EUR',\n country: 'Spain',\n description: `The orange is the fruit of various citrus species in the family Rutaceae\n (see list of plants known as orange); it primarily refers to Citrus × sinensis.`,\n checked: false\n }\n ];\n\n constructor() {}\n\n select(index: number, checked: boolean): void {\n this.fruits[index].checked = checked;\n\n this._handleMasterCheckboxState();\n }\n\n selectMaster(checked: boolean): void {\n checked ? this._selectAll() : this._deselectAll();\n\n this._handleMasterCheckboxState();\n }\n\n private _handleMasterCheckboxState(): void {\n this.masterCheckbox = this._allSelected() ? true : this._anySelected() ? null : false;\n }\n\n private _selectAll(): void {\n this.fruits.forEach((row) => (row.checked = true));\n }\n\n private _deselectAll(): void {\n this.fruits.forEach((row) => (row.checked = false));\n }\n\n private _anySelected(): boolean {\n return this.fruits.some((_row) => _row.checked);\n }\n\n private _allSelected(): boolean {\n return this.fruits.every((_row) => _row.checked);\n }\n}\n", - "html": "
    \n

    Mobile Mode

    \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Tablet Mode

    \n \n \n \n Fruit Description\n Price\n Status\n Date Of Expire\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n {{ fruit.dateOfExpire }}\n \n \n \n \n \n \n \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Desktop Mode

    \n \n \n \n \n \n \n \n \n \n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n \n \n \n \n \n \n \n }\n \n
    NamePriceCountryStatusDate Of ExpireDescription
    \n {{ fruit.name }}\n \n {{ fruit.country }}\n \n {{ fruit.price }}\n \n \n \n {{ fruit.dateOfExpire }}\n \n {{ fruit.description }}\n \n \n
    \n
    \n
    \n

    Popin Mobile Mode with Checkboxes

    \n \n \n \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit; let ind = $index) {\n \n \n \n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n" } ] }, { - "name": "TableFooterDirective", - "selector": "[fdTableFooter], [fd-table-footer]", + "name": "TableFixedDirective", + "selector": "[fdTableFixed], [fd-table-fixed]", "library": "@fundamental-ngx/core", "category": "table", "description": "The Table directive is used to decorate a table element, displaying data that can be compared. Usually a set of item of the same type which data is divided on columns to facilitate the comparison between items.", @@ -22910,7 +22810,7 @@ "slots": [], "methods": [], "cssProperties": [], - "sourceFile": "libs/core/table/directives/table-footer.directive.ts", + "sourceFile": "libs/core/table/directives/table-fixed.directive.ts", "source": "typedoc", "examples": [ { @@ -23015,17 +22915,147 @@ "typescript": "import { UpperCasePipe } from '@angular/common';\nimport { Component, ViewChild } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { DialogRef, DialogService } from '@fundamental-ngx/core/dialog';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableComponent, TableModule } from '@fundamental-ngx/core/table';\nimport { TableCustomDialogComponent } from './table-custom-dialog.component';\n\nexport interface DisplayedColumn {\n key: string;\n checked: boolean;\n}\n\nexport interface CellData {\n column1: string;\n column2: string;\n column3: string;\n date: string;\n type: string;\n}\n\nconst CELL_DATA: CellData[] = [\n { column1: 'Row 111', column2: 'Row 221', column3: 'Row 1', date: '09-07-18', type: 'search' },\n { column1: 'Row 112', column2: 'Row 222', column3: 'Row 2', date: '09-08-18', type: 'cart' },\n { column1: 'Row 113', column2: 'Row 223', column3: 'Row 3', date: '02-14-18', type: 'calendar' },\n { column1: 'Row 114', column2: 'Row 224', column3: 'Row 4', date: '12-30-17', type: 'search' },\n { column1: 'Row 115', column2: 'Row 225', column3: 'Row 5', date: '11-12-18', type: 'search' }\n];\n\n@Component({\n selector: 'fd-table-custom-columns-example',\n templateUrl: './table-custom-columns-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, IconComponent, ButtonComponent, UpperCasePipe]\n})\nexport class TableCustomColumnsExampleComponent {\n @ViewChild(TableComponent)\n tableComponent: TableComponent;\n\n displayedColumns: string[];\n originalDisplayedColumns: DisplayedColumn[];\n dataSource = CELL_DATA;\n dialogRef: DialogRef;\n\n constructor(private _dialogService: DialogService) {\n this.displayedColumns = Object.keys(this.dataSource[0]);\n this.originalDisplayedColumns = [];\n\n Object.keys(this.dataSource[0]).forEach((key) => {\n this.originalDisplayedColumns.push({ key, checked: true });\n });\n }\n\n openDialog(): void {\n const dialogRef = this._dialogService.open(TableCustomDialogComponent, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n data: {\n columns: this.originalDisplayedColumns\n }\n });\n\n dialogRef.afterClosed.subscribe(\n (columns) => {\n this.originalDisplayedColumns = [...columns];\n this._propagateChangeToDisplayedValue();\n },\n () => {\n console.log('closed without changes');\n }\n );\n }\n\n private _propagateChangeToDisplayedValue(): void {\n this.displayedColumns = [\n ...this.originalDisplayedColumns.filter((_col) => _col.checked).map((_col) => _col.key)\n ];\n this.tableComponent.reset(this.displayedColumns);\n }\n}\n", "html": "\n \n \n @for (column of displayedColumns; track column) {\n \n }\n \n \n \n @for (row of dataSource; track row) {\n \n \n \n \n \n \n \n }\n \n
    {{ column | uppercase }}
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}
    \n
    \n
    \nChosen Columns: {{ displayedColumns }}\n
    \n
    \n\n" }, + { + "name": "table-popin-example", + "description": "Table Popin", + "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-popin-example',\n templateUrl: './table-popin-example.component.html',\n styles: [\n `\n .table-example-popin-title {\n margin: 0 0 10px 0;\n }\n `\n ],\n imports: [\n FocusableGridDirective,\n TableModule,\n FormLabelComponent,\n ObjectStatusComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class TablePopinExampleComponent {\n masterCheckbox: boolean | null = false;\n\n fruits: any[] = [\n {\n name: 'Banana',\n status: 'positive',\n statusName: 'Available',\n dateOfExpire: '12.06.2020',\n price: '5 EUR',\n country: 'India',\n description: `A banana is an elongated, edible fruit – botanically a berry – produced by several kinds of large herbaceous\n flowering plants in the genus Musa.`,\n checked: false\n },\n {\n name: 'Apple',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '10.06.2020',\n price: '5,5 EUR',\n country: 'USA',\n description: `An apple is an edible fruit produced by an apple tree (Malus domestica).\n Apple trees are cultivated worldwide and are the most widely grown species in the genus Malus.`,\n checked: false\n },\n {\n name: 'Pineapple',\n status: 'negative',\n statusName: 'Out of stock',\n dateOfExpire: '08.06.2020',\n price: '6 EUR',\n country: 'Mexico',\n description: `The pineapple (Ananas comosus) is a tropical plant with an edible fruit and the most\n economically significant plant in the family Bromeliaceae.`,\n checked: false\n },\n {\n name: 'Orange',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '18.06.2020',\n price: '10 EUR',\n country: 'Spain',\n description: `The orange is the fruit of various citrus species in the family Rutaceae\n (see list of plants known as orange); it primarily refers to Citrus × sinensis.`,\n checked: false\n }\n ];\n\n constructor() {}\n\n select(index: number, checked: boolean): void {\n this.fruits[index].checked = checked;\n\n this._handleMasterCheckboxState();\n }\n\n selectMaster(checked: boolean): void {\n checked ? this._selectAll() : this._deselectAll();\n\n this._handleMasterCheckboxState();\n }\n\n private _handleMasterCheckboxState(): void {\n this.masterCheckbox = this._allSelected() ? true : this._anySelected() ? null : false;\n }\n\n private _selectAll(): void {\n this.fruits.forEach((row) => (row.checked = true));\n }\n\n private _deselectAll(): void {\n this.fruits.forEach((row) => (row.checked = false));\n }\n\n private _anySelected(): boolean {\n return this.fruits.some((_row) => _row.checked);\n }\n\n private _allSelected(): boolean {\n return this.fruits.every((_row) => _row.checked);\n }\n}\n", + "html": "
    \n

    Mobile Mode

    \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Tablet Mode

    \n \n \n \n Fruit Description\n Price\n Status\n Date Of Expire\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n {{ fruit.dateOfExpire }}\n \n \n \n \n \n \n \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Desktop Mode

    \n \n \n \n \n \n \n \n \n \n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n \n \n \n \n \n \n \n }\n \n
    NamePriceCountryStatusDate Of ExpireDescription
    \n {{ fruit.name }}\n \n {{ fruit.country }}\n \n {{ fruit.price }}\n \n \n \n {{ fruit.dateOfExpire }}\n \n {{ fruit.description }}\n \n \n
    \n
    \n
    \n

    Popin Mobile Mode with Checkboxes

    \n \n \n \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit; let ind = $index) {\n \n \n \n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n" + }, { "name": "table-focusable-example", "description": "Table Focusable", "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" + } + ] + }, + { + "name": "TableFooterDirective", + "selector": "[fdTableFooter], [fd-table-footer]", + "library": "@fundamental-ngx/core", + "category": "table", + "description": "The Table directive is used to decorate a table element, displaying data that can be compared. Usually a set of item of the same type which data is divided on columns to facilitate the comparison between items.", + "inputs": [], + "outputs": [], + "slots": [], + "methods": [], + "cssProperties": [], + "sourceFile": "libs/core/table/directives/table-footer.directive.ts", + "source": "typedoc", + "examples": [ + { + "name": "table-activable-example", + "description": "Table Activable", + "typescript": "import { Component, OnInit } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-activable-example',\n templateUrl: './table-activable-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent]\n})\nexport class TableActivableExampleComponent implements OnInit {\n tableRows: any[];\n\n ngOnInit(): void {\n this.tableRows = [\n {\n column1: {\n text: 'Clicking on any cell'\n },\n column2: {\n text: 'On This Row'\n },\n column3: {\n text: 'Will Cause'\n },\n column4: {\n text: 'Highlight of whole row'\n },\n date: {\n text: '09-07-18'\n },\n activable: true,\n hoverable: true\n },\n {\n column1: {\n text: 'Clicking on cell',\n activable: true\n },\n column2: {\n text: 'On This Row',\n activable: true\n },\n column3: {\n text: 'Will Cause',\n activable: true\n },\n column4: {\n text: 'Highlight of cell',\n activable: true\n },\n date: {\n text: '09-08-18',\n activable: true\n }\n },\n {\n column1: {\n text: 'Hovering On Any Cell',\n hoverable: true\n },\n column2: {\n text: 'Will Change',\n hoverable: true\n },\n column3: {\n text: 'Background',\n hoverable: true\n },\n column4: {\n text: 'Of that cell',\n hoverable: true\n },\n date: {\n text: '02-14-18',\n hoverable: true\n }\n },\n {\n column1: {\n text: 'Hovering on Any Cell'\n },\n column2: {\n text: 'On This Row'\n },\n column3: {\n text: 'Will Change'\n },\n column4: {\n text: 'Background of Whole Row'\n },\n date: {\n text: '12-30-17'\n },\n hoverable: true\n }\n ];\n }\n}\n", + "html": "\n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n }\n \n
    Hovering AndClickingOn Header's CellWill TriggerColor Change
    \n {{ row.column1.text }}\n \n {{ row.column2.text }}\n \n {{ row.column3.text }}\n \n {{ row.column4.text }}\n \n {{ row.date.text }}\n
    \n" + }, + { + "name": "table-cdk-example", + "description": "Table Cdk", + "typescript": "import { CdkDrag, CdkDragHandle, CdkDropList, moveItemInArray } from '@angular/cdk/drag-drop';\nimport { CdkTable, CdkTableModule } from '@angular/cdk/table';\nimport { Component, ViewChild } from '@angular/core';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\nexport interface CellData {\n column1: string;\n column2: string;\n column3: string;\n date: string;\n type: string;\n}\nconst CELL_DATA: CellData[] = [\n { column1: 'Row 1', column2: 'Row 1', column3: 'Row 1', date: '09-07-18', type: 'search' },\n { column1: 'Row 2', column2: 'Row 2', column3: 'Row 2', date: '09-08-18', type: 'cart' },\n { column1: 'Row 3', column2: 'Row 3', column3: 'Row 3', date: '02-14-18', type: 'calendar' },\n { column1: 'Row 4', column2: 'Row 4', column3: 'Row 4', date: '12-30-17', type: 'search' },\n { column1: 'Row 5', column2: 'Row 5', column3: 'Row 5', date: '11-12-18', type: 'search' }\n];\n\n@Component({\n selector: 'fd-table-cdk-example',\n templateUrl: './table-cdk-example.component.html',\n styleUrls: ['table-cdk-example.component.scss'],\n imports: [TableModule, CdkTableModule, CdkDropList, CdkDragHandle, LinkComponent, IconComponent, CdkDrag]\n})\nexport class TableCdkExampleComponent {\n @ViewChild('table') table: CdkTable[]>;\n\n displayedColumns: string[] = ['column1', 'column2', 'column3', 'date', 'type'];\n dataSource = CELL_DATA;\n\n dropRow(event): void {\n const previousIndex = this.dataSource.findIndex((d) => d === event.item.data);\n moveItemInArray(this.dataSource, previousIndex, event.currentIndex);\n this.table.renderRows();\n }\n}\n", + "html": "\n \n \n Column 1\n \n {{ cell.column1 }}\n \n \n\n \n Column 2\n {{ cell.column2 }}\n \n\n \n Column 3\n {{ cell.column3 }}\n \n\n \n Date\n {{ cell.date }}\n \n\n \n Type\n \n \n \n \n\n \n \n \n\n" + }, + { + "name": "table-checkboxes-example", + "description": "Table Checkboxes", + "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FocusableGridDirective, RangeSelector } from '@fundamental-ngx/cdk/utils';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-checkboxes-example',\n templateUrl: './table-checkboxes-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n ContentDensityDirective,\n CheckboxComponent,\n FormsModule,\n LinkComponent,\n IconComponent\n ]\n})\nexport class TableCheckboxesExampleComponent {\n checkboxValue: boolean | null = false;\n checkboxValueCompact: boolean | null = false;\n checkboxValueCondensed: boolean | null = false;\n\n tableRows: any[] = [\n {\n column1: 'user.name@email.com',\n column2: 'Row 1',\n column3: 'Row 1',\n date: '09-07-18',\n checked: false\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3: 'Row 2',\n date: '09-07-18',\n checked: false\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '09-07-18',\n checked: false\n }\n ];\n\n tableRowsCompact = [\n {\n column1: 'user.name@email.com',\n column2: 'Row 1',\n column3: 'Row 1',\n date: '09-07-18',\n type: 'search',\n checked: false\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'cart',\n checked: false\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '09-07-18',\n type: 'calendar',\n checked: false\n }\n ];\n\n tableRowsCondensed: Record[] = [\n {\n column1: 'user.name@email.com',\n column2: 'Row 1',\n column3: 'Row 1',\n date: '09-07-18',\n type: 'search',\n checked: false\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'cart',\n checked: false\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '09-07-18',\n type: 'calendar',\n checked: false\n }\n ];\n\n private readonly _rangeSelector = new RangeSelector();\n\n select(index: number, event: MouseEvent, size: string): void {\n // using rangeSelector utility to be able to select multiple rows while \"shift\" is pressed\n const checkedToggled = !this._getTable(size)[index].checked;\n this._rangeSelector.onRangeElementToggled(index, event);\n this._rangeSelector.applyValueToEachInRange((idx) => (this._getTable(size)[idx].checked = checkedToggled));\n this._setValue(size);\n }\n\n selectAll(checked: boolean, size: string): void {\n if (size === 'cozy') {\n this.checkboxValue = checked;\n } else if (size === 'compact') {\n this.checkboxValueCompact = checked;\n } else if (size === 'condensed') {\n this.checkboxValueCondensed = checked;\n }\n if (checked) {\n this._selectAll(size);\n } else {\n this._deselectAll(size);\n }\n }\n\n private _selectAll(size: string): void {\n this._getTable(size).forEach((row) => (row.checked = true));\n }\n\n private _deselectAll(size: string): void {\n this._getTable(size).forEach((row) => (row.checked = false));\n }\n\n private _getSelectAllValue(size: string): boolean | null {\n const table = this._getTable(size);\n const checked = table.filter((row) => row.checked);\n if (checked.length === table.length) {\n return true;\n } else if (!checked.length) {\n return false;\n }\n // returning null to set selection state to \"indeterminate\"\n return null;\n }\n\n private _getTable(size: string): any[] {\n let table = this.tableRows;\n if (size === 'compact') {\n table = this.tableRowsCompact;\n } else if (size === 'condensed') {\n table = this.tableRowsCondensed;\n }\n return table;\n }\n\n private _setValue(size: string): void {\n if (size === 'cozy') {\n this.checkboxValue = this._getSelectAllValue(size);\n } else if (size === 'compact') {\n this.checkboxValueCompact = this._getSelectAllValue(size);\n } else if (size === 'condensed') {\n this.checkboxValueCondensed = this._getSelectAllValue(size);\n }\n }\n}\n", + "html": "Table With Checkbox Cozy Mode\n\n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row; let i = $index) {\n \n \n \n \n \n \n \n }\n \n
    \n \n Column 1Column 2Column 3Date
    \n \n \n {{ row.column1 }}\n \n {{ row.column2 }}\n \n {{ row.column3 }}\n \n {{ row.date }}\n
    \n
    \nTable With Checkbox Compact Mode\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRowsCompact; track row; let i = $index) {\n \n \n \n \n \n \n \n \n }\n \n
    \n \n Column 1Column 2Column 3DateType
    \n \n \n {{ row.column1 }}\n \n {{ row.column2 }}\n \n {{ row.column3 }}\n \n {{ row.date }}\n
    \n
    \nTable With Checkbox Condensed Mode\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRowsCondensed; track row; let i = $index) {\n \n \n \n \n \n \n \n \n }\n \n
    \n \n Column 1Column 2Column 3DateType
    \n \n \n {{ row.column1 }}\n \n {{ row.column2 }}\n \n {{ row.column3 }}\n \n {{ row.date }}\n
    \n" + }, + { + "name": "table-column-sorting-example", + "description": "Table Column Sorting", + "typescript": "import { LiveAnnouncer } from '@angular/cdk/a11y';\n\nimport { ChangeDetectionStrategy, Component, OnInit, Pipe, PipeTransform } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { FormControlComponent, FormItemComponent, FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { TableModule } from '@fundamental-ngx/core/table';\nimport { ToolbarComponent, ToolbarSpacerDirective } from '@fundamental-ngx/core/toolbar';\n\nconst sort = (a, b, key?: string): number => {\n if (key) {\n return a[key] > b[key] ? 1 : -1;\n } else {\n return a > b ? 1 : -1;\n }\n};\n\n@Pipe({\n name: 'sortBy',\n pure: false,\n standalone: true\n})\nexport class SortByPipe implements PipeTransform {\n transform(tableRows: any[], ascending: boolean, sortKey?: string): any[] {\n const ascModifier: number = ascending ? 1 : -1;\n tableRows.sort((a, b) => sort(a, b, sortKey) * ascModifier);\n return tableRows;\n }\n}\n\n@Pipe({\n name: 'filter',\n standalone: true\n})\nexport class FilterPipe implements PipeTransform {\n transform(values: any[] = [], searchTerm: string = '', key: string = ''): any[] {\n if (!searchTerm) {\n return values;\n }\n if (key) {\n values = values.filter((item) => item[key].toLocaleLowerCase().includes(searchTerm.toLocaleLowerCase()));\n } else {\n values = values.filter((item) => item.toLocaleLowerCase().includes(searchTerm.toLocaleLowerCase()));\n }\n return values;\n }\n}\n\nconst rows = [\n {\n column1: 'Apple',\n column2: 'Row 1',\n column3: 'Row 1',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'Banana',\n column2: 'Row 2',\n column3: 'Row 2',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'Kiwi',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'Peach',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'Strawberry',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n];\n\ninterface ExampleRow {\n column1: any;\n column2?: any;\n column3?: any;\n date?: any;\n type?: any;\n}\n\n@Component({\n selector: 'fd-table-column-sorting-example',\n templateUrl: './table-column-sorting-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ToolbarComponent,\n ToolbarSpacerDirective,\n ContentDensityDirective,\n InputGroupModule,\n FormsModule,\n ButtonComponent,\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n IconComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n ListModule,\n FormItemComponent,\n FormLabelComponent,\n FormControlComponent,\n SortByPipe,\n FilterPipe\n ]\n})\nexport class TableColumnSortingExampleComponent implements OnInit {\n tableRows: ExampleRow[];\n displayedRows: ExampleRow[];\n tableRows2: ExampleRow[];\n displayedRows2: ExampleRow[];\n ascending = true;\n ascending2 = true;\n filterVal = '';\n filterVal2 = '';\n open = false;\n\n constructor(private liveAnnouncer: LiveAnnouncer) {}\n\n sortColumn1(asc: boolean): void {\n this.ascending2 = asc;\n this.open = false;\n }\n\n inputKeyup(event: KeyboardEvent): void {\n if (event.key === 'Enter' || event.key === 'Esc') {\n this.open = false;\n }\n }\n\n async changeSort(asc: boolean): Promise {\n this.ascending = asc;\n await this.liveAnnouncer.announce(`Set sort ${asc ? 'ascending' : 'descending'}`, 'assertive');\n }\n\n ngOnInit(): void {\n this.tableRows = [...rows];\n this.displayedRows = this.tableRows;\n this.tableRows2 = [...rows];\n this.displayedRows2 = this.tableRows2;\n }\n}\n", + "html": "

    Sorting and filtering with toolbar elements:

    \n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n @for (row of displayedRows | filter: filterVal : 'column1' | sortBy: ascending : 'column1'; track row) {\n \n \n \n \n \n \n \n }\n \n
    Column 1Column 2Column 3DateType
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}\n \n
    \n

    Sorting and filtering with inline popover:

    \n\n \n \n \n \n \n \n \n \n \n \n @for (row of displayedRows2 | filter: filterVal2 : 'column1' | sortBy: ascending2 : 'column1'; track row) {\n \n \n \n \n \n \n \n }\n \n
    \n \n \n
    \n Column 1\n \n
    \n
    \n \n
      \n
    • \n \n Sort Ascending\n
    • \n
    • \n \n Sort Descending\n
    • \n
    • \n \n
      \n \n \n
      \n
    • \n
    \n
    \n
    \n
    Column 2Column 3DateType
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}\n \n
    \n" + }, + { + "name": "table-example", + "description": "Table", + "typescript": "import { Component, OnInit } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-example',\n templateUrl: './table-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, IconComponent]\n})\nexport class TableExampleComponent implements OnInit {\n tableRows: any[];\n\n ngOnInit(): void {\n this.tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n }\n}\n", + "html": "\n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n {{ row.column2 }}\n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}
    \n\n

    \n

    individual non-interactive header cells

    \n\n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n }\n \n
    Non-interactive Column HeaderColumn HeaderColumn HeaderColumn HeaderNon-interactive Column Header
    \n {{ row.column1 }}\n \n

    \n {{ row.column2 }}\n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}
    \n\n

    \n

    non-interactive header cells

    \n\n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n {{ row.column2 }}\n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}
    \n" + }, + { + "name": "table-fixed-example", + "description": "Table Fixed", + "typescript": "import { Component, OnInit } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-fixed-example',\n templateUrl: './table-fixed-example.component.html',\n imports: [TableModule, FocusableGridDirective, LinkComponent, IconComponent]\n})\nexport class TableFixedExampleComponent implements OnInit {\n tableRows: any[];\n\n ngOnInit(): void {\n this.tableRows = [\n {\n column1: 'user.name@email.com',\n column2: 'Test',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3: 'Test',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 6',\n column3: 'Row 6',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 7',\n column3: 'Row 7',\n date: '11-12-18',\n type: 'search'\n }\n ];\n }\n}\n", + "html": "
    \n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n }\n \n \n \n \n \n \n \n \n \n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n {{ row.column2 }}\n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}
    Footer Cell
    \n
    \n" + }, + { + "name": "table-footer-example", + "description": "Table Footer", + "typescript": "import { Component, OnInit } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-footer-example',\n templateUrl: './table-footer-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, IconComponent]\n})\nexport class TableFooterExampleComponent implements OnInit {\n tableRows: any[];\n\n ngOnInit(): void {\n this.tableRows = [\n {\n column1: 'user.name@email.com',\n column2: 'Row 1',\n column3: 'Row 1',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3: 'Row 2',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n }\n}\n", + "html": "\n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n }\n \n \n \n \n \n \n \n \n \n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}
    Footer Cell
    \n" + }, + { + "name": "table-navigatable-row-example", + "description": "Table Navigatable Row", + "typescript": "import { Component, computed, inject } from '@angular/core';\n\nimport { RouterLink } from '@angular/router';\nimport { FocusableGridDirective, RtlService } from '@fundamental-ngx/cdk/utils';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ObjectStatus, ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\ninterface TableIem {\n column1: string;\n column2: string;\n column3: string;\n date: string;\n navigatable: boolean;\n active: boolean;\n}\n\ninterface TableMobileItem {\n name: string;\n status: ObjectStatus;\n statusName: string;\n dateOfExpire: string;\n price: string;\n country: string;\n description: string;\n navigatable: boolean;\n}\n\n@Component({\n selector: 'fd-table-navigatable-row-example',\n templateUrl: './table-navigatable-row-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, RouterLink, FormLabelComponent, ObjectStatusComponent]\n})\nexport class TableNavigatableRowExampleComponent {\n navigatableRows: TableIem[] = [\n {\n column1: 'user.name@email.com',\n column2: 'Row 1',\n column3: 'Row 1',\n date: '09-07-18',\n navigatable: true,\n active: false\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3: 'Row 2',\n date: '09-07-18',\n navigatable: false,\n active: false\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '09-07-18',\n navigatable: true,\n active: false\n }\n ];\n\n fruits: TableMobileItem[] = [\n {\n name: 'Banana',\n status: 'positive',\n statusName: 'Available',\n dateOfExpire: '12.06.2020',\n price: '5 EUR',\n country: 'India',\n description: `A banana is an elongated, edible fruit – botanically a berry – produced by several kinds of large herbaceous\n flowering plants in the genus Musa.`,\n navigatable: true\n },\n {\n name: 'Apple',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '10.06.2020',\n price: '5,5 EUR',\n country: 'USA',\n description: `An apple is an edible fruit produced by an apple tree (Malus domestica).\n Apple trees are cultivated worldwide and are the most widely grown species in the genus Malus.`,\n navigatable: false\n }\n ];\n\n protected readonly navigationArrow = computed(() =>\n this._rtlService?.rtl() ? 'sap-icon--navigation-left-arrow' : 'sap-icon--navigation-right-arrow'\n );\n\n private readonly _rtlService = inject(RtlService, { optional: true });\n\n alert(row: any): void {\n if (row.navigatable) {\n alert('Navigation event took place!');\n }\n }\n\n setActiveItem(index: number): void {\n this.navigatableRows.map((item, rowIndex) => {\n item.active = rowIndex === index;\n return item;\n });\n this.alert(this.navigatableRows[index]);\n }\n}\n", + "html": "

    \n Entire row is navigatable, used with icon and highlighted active item.\n

    \n\n \n \n \n \n \n \n \n \n \n \n @for (row of navigatableRows; track row; let i = $index) {\n \n \n \n \n \n \n \n }\n \n
    Column 1Column 2Column 3Date
    \n {{ row.column1 }}\n \n {{ row.column2 }}\n \n {{ row.column3 }}\n \n {{ row.date }}\n \n @if (row.navigatable) {\n \n }\n
    \n
    \n

    Row with navigation button

    \n\n \n \n \n \n \n \n \n \n \n \n @for (row of navigatableRows; track row) {\n \n \n \n \n \n \n \n }\n \n
    Column 1Column 2Column 3Column 4
    \n {{ row.column1 }}\n \n

    {{ row.column2 }}

    \n
    \n {{ row.column3 }}\n \n {{ row.date }}\n \n \n \n \n
    \n
    \n

    Mobile Mode

    \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n @if (fruit.navigatable) {\n \n }\n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n" + }, + { + "name": "table-page-scroll-example", + "description": "Table Page Scroll", + "typescript": "import { Component, OnInit } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableModule } from '@fundamental-ngx/core/table';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarLabelDirective } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-table-page-scroll-example',\n templateUrl: './table-page-scroll-example.component.html',\n imports: [\n TableModule,\n FocusableGridDirective,\n LinkComponent,\n IconComponent,\n ToolbarComponent,\n TitleComponent,\n ToolbarItemDirective,\n ToolbarLabelDirective\n ]\n})\nexport class TablePageScrollExampleComponent implements OnInit {\n tableRows: any[];\n\n ngOnInit(): void {\n this.tableRows = [\n {\n column1: 'user.name@email.com',\n column2: 'Row 1',\n column3: 'Row 1',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3: 'Row 2',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 6',\n column3: 'Row 6',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 7',\n column3: 'Row 7',\n date: '11-12-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 8',\n column3: 'Row 8',\n date: '11-12-19',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 9',\n column3: 'Row 9',\n date: '11-12-20',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 10',\n column3: 'Row 10',\n date: '11-12-21',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 11',\n column3: 'Row 11',\n date: '11-12-21',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 12',\n column3: 'Row 12',\n date: '11-12-21',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 13',\n column3: 'Row 13',\n date: '11-12-21',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 14',\n column3: 'Row 14',\n date: '11-12-21',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 15',\n column3: 'Row 15',\n date: '11-12-21',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 16',\n column3: 'Row 16',\n date: '11-12-21',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 17',\n column3: 'Row 17',\n date: '11-12-21',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 18',\n column3: 'Row 18',\n date: '11-12-21',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 19',\n column3: 'Row 19',\n date: '11-12-21',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 20',\n column3: 'Row 20',\n date: '11-12-21',\n type: 'search'\n }\n ];\n }\n}\n", + "html": "
    \n
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Commodi aut fugiat veritatis harum doloribus?\n Doloremque quo animi, illum ut officiis repellendus, dolorem, architecto quisquam placeat vel nihil ratione\n temporibus! Voluptas. Lorem ipsum dolor sit amet consectetur adipisicing elit. Commodi aut fugiat veritatis\n harum doloribus? Doloremque quo animi, illum ut officiis repellendus, dolorem, architecto quisquam placeat vel\n nihil ratione temporibus! Voluptas. Lorem ipsum dolor sit amet consectetur adipisicing elit. Commodi aut fugiat\n veritatis harum doloribus? Doloremque quo animi, illum ut officiis repellendus, dolorem, architecto quisquam\n placeat vel nihil ratione temporibus! Voluptas. Lorem ipsum dolor sit amet consectetur adipisicing elit. Commodi\n aut fugiat veritatis harum doloribus? Doloremque quo animi, illum ut officiis repellendus, dolorem, architecto\n quisquam placeat vel nihil ratione temporibus! Voluptas.


    \n
    \n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n }\n \n \n \n \n \n \n \n \n \n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n {{ row.column2 }}\n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}
    Footer Cell
    \n
    \n
    \n" + }, + { + "name": "table-pagination-example", + "description": "Table Pagination", + "typescript": "import { Component, OnInit, ViewChild } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuComponent } from '@fundamental-ngx/core/menu';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { TableModule } from '@fundamental-ngx/core/table';\nimport { ToolbarItemDirective } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-table-pagination-example',\n templateUrl: './table-pagination-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, IconComponent, PaginationModule, ToolbarItemDirective]\n})\nexport class TablePaginationExampleComponent implements OnInit {\n @ViewChild('itemsPerPageMenu')\n itemsPerPageMenu: MenuComponent;\n\n tableRows: any[];\n displayedRows: any[];\n totalItems = 30;\n itemsPerPage = 5;\n currentPage = 3;\n itemsPerPageOptions: number[] = [3, 5, 10];\n\n newPageClicked(pageNumber: number): void {\n this.currentPage = pageNumber;\n const firstDisplayedRow = (pageNumber - 1) * this.itemsPerPage;\n this.displayedRows = this.tableRows.slice(firstDisplayedRow, firstDisplayedRow + this.itemsPerPage);\n if (this.itemsPerPageMenu) {\n this.itemsPerPageMenu.close();\n }\n }\n\n itemsPerPageChange(value: number): void {\n this.itemsPerPage = value;\n this.newPageClicked(this.currentPage);\n }\n\n ngOnInit(): void {\n this.tableRows = [\n {\n column1: 'Row 1',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'Row 2',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'Row 5',\n date: '11-12-18',\n type: 'search'\n },\n {\n column1: 'Row 6',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'Row 7',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'Row 8',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'Row 9',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'Row 10',\n date: '11-12-18',\n type: 'search'\n },\n {\n column1: 'Row 11',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'Row 12',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'Row 13',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'Row 14',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'Row 15',\n date: '11-12-18',\n type: 'search'\n },\n {\n column1: 'Row 16',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'Row 17',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'Row 18',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'Row 19',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'Row 20',\n date: '11-12-18',\n type: 'search'\n },\n {\n column1: 'Row 21',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'Row 21',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'Row 23',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'Row 24',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'Row 25',\n date: '11-12-18',\n type: 'search'\n },\n {\n column1: 'Row 26',\n date: '11-12-18',\n type: 'search'\n },\n {\n column1: 'Row 27',\n date: '11-12-18',\n type: 'search'\n },\n {\n column1: 'Row 28',\n date: '11-12-20',\n type: 'search'\n },\n {\n column1: 'Row 29',\n date: '11-12-21',\n type: 'search'\n },\n {\n column1: 'Row 30',\n date: '11-12-22',\n type: 'search'\n }\n ];\n\n this.newPageClicked(3);\n }\n}\n", + "html": "\n \n \n \n \n \n \n \n \n @for (row of displayedRows; track row; let i = $index) {\n \n \n \n \n \n }\n \n
    \n \n \n \n \n \n
    Column HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n {{ row.date }}\n \n {{ row.column1 }}\n
    \n
    \n \n
    \n
    \n" + }, + { + "name": "table-responsive-example", + "description": "Table Responsive", + "typescript": "import { Component, OnInit } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-responsive-example',\n templateUrl: './table-responsive-example.component.html',\n styleUrls: ['table-responsive-example.component.scss'],\n imports: [TableModule, FocusableGridDirective, LinkComponent, IconComponent]\n})\nexport class TableResponsiveExampleComponent implements OnInit {\n tableRows: any[];\n\n ngOnInit(): void {\n this.tableRows = [\n {\n column1: 'Row 1',\n column2: 'Row 1',\n column3: 'Row 1',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'Row 2',\n column2: 'Row 2',\n column3: 'Row 2',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'Row 3',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'Row 4',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'Row 5',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n }\n}\n", + "html": "
    \n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n }\n \n
    Column 1Column 2Column 3DateType
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}
    \n
    \n" + }, + { + "name": "table-semantic-example", + "description": "Table Semantic", + "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FocusableGridDirective, RangeSelector } from '@fundamental-ngx/cdk/utils';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableModule, TableStatuses } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-semantic-example',\n templateUrl: './table-semantic-example.component.html',\n imports: [FocusableGridDirective, TableModule, CheckboxComponent, FormsModule, LinkComponent]\n})\nexport class TableSemanticExampleComponent {\n isAllSelected: boolean | null = false;\n\n tableRows: RowData[] = [\n {\n status: null,\n column1: 'user.name@email.com',\n column2: 'Row 1',\n column3: 'Row 1',\n date: '09-07-18',\n checked: false\n },\n {\n status: 'valid',\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3: 'Row 2',\n date: '09-07-18',\n checked: false\n },\n {\n status: null,\n column1: 'user.name@email.com',\n column2: 'Row 1',\n column3: 'Row 1',\n date: '09-07-18',\n checked: false\n },\n {\n status: 'warning',\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '09-07-18',\n checked: false\n },\n {\n status: null,\n column1: 'user.name@email.com',\n column2: 'Row 1',\n column3: 'Row 1',\n date: '09-07-18',\n checked: false\n },\n {\n status: 'information',\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3: 'Row 2',\n date: '09-07-18',\n checked: false\n },\n {\n status: null,\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '09-07-18',\n checked: false\n },\n {\n status: 'error',\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '09-07-18',\n checked: false\n }\n ];\n\n private readonly _rangeSelector = new RangeSelector();\n\n select(index: number, event: MouseEvent): void {\n // using rangeSelector utility to be able to select multiple rows while \"shift\" is pressed\n const checkedToggled = !this.tableRows[index].checked;\n this._rangeSelector.onRangeElementToggled(index, event);\n this._rangeSelector.applyValueToEachInRange((idx) => (this.tableRows[idx].checked = checkedToggled));\n this.isAllSelected = this._getSelectAllValue();\n }\n\n selectAll(checked: boolean): void {\n this.isAllSelected = checked;\n if (checked) {\n this._selectAll();\n } else {\n this._deselectAll();\n }\n }\n\n getRowAriaLabel(row: RowData, index: number): string {\n let ariaLabel = 'Select row ' + (index + 1);\n if (row.status) {\n ariaLabel += ', ' + row.status;\n }\n return ariaLabel;\n }\n\n private _selectAll(): void {\n this.tableRows.forEach((row) => (row.checked = true));\n }\n\n private _deselectAll(): void {\n this.tableRows.forEach((row) => (row.checked = false));\n }\n\n private _getSelectAllValue(): boolean | null {\n const checked = this.tableRows.filter((row) => row.checked);\n if (checked.length === this.tableRows.length) {\n return true;\n } else if (!checked.length) {\n return false;\n }\n // returning null to set selection state to \"indeterminate\"\n return null;\n }\n}\n\ninterface RowData {\n status: TableStatuses | null;\n column1: string;\n column2: string;\n column3: string;\n date: string;\n checked: boolean;\n}\n", + "html": "\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row; let i = $index) {\n \n \n \n \n \n \n \n \n }\n \n
    \n \n Column 1Column 2Column 3Date
    \n \n \n {{ row.column1 }}\n \n {{ row.column2 }}\n \n {{ row.column3 }}\n \n {{ row.date }}\n
    \n" + }, + { + "name": "table-toolbar-example", + "description": "Table Toolbar", + "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\n\nimport { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit, TemplateRef } from '@angular/core';\nimport { FormBuilder, FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BusyIndicatorComponent } from '@fundamental-ngx/core/busy-indicator';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { DialogModule, DialogService } from '@fundamental-ngx/core/dialog';\nimport { FormControlComponent, FormItemComponent, FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TableModule } from '@fundamental-ngx/core/table';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSpacerDirective } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-table-toolbar-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './table-toolbar-example.component.html',\n imports: [\n ToolbarComponent,\n TitleComponent,\n ToolbarSpacerDirective,\n InputGroupModule,\n FormsModule,\n ButtonComponent,\n ToolbarItemDirective,\n BusyIndicatorComponent,\n FocusableGridDirective,\n TableModule,\n DialogModule,\n CdkScrollable,\n ScrollbarDirective,\n ReactiveFormsModule,\n FormItemComponent,\n FormLabelComponent,\n FormControlComponent,\n BarModule\n ]\n})\nexport class TableToolbarExampleComponent implements OnInit {\n tableRows: any[];\n displayedRows: any[];\n searchTerm = '';\n confirmationReason: string;\n myForm: FormGroup;\n loading = false;\n\n constructor(\n private _dialogService: DialogService,\n private _fb: FormBuilder,\n private _cdr: ChangeDetectorRef\n ) {}\n\n ngOnInit(): void {\n this.tableRows = [\n {\n column1: 'Apple',\n column2: 'Fruit',\n region: 'Virginia'\n },\n {\n column1: 'Banana',\n column2: 'Fruit',\n region: 'Costa Rica'\n },\n {\n column1: 'Kale',\n column2: 'Vegetable',\n region: 'Colorado'\n },\n {\n column1: 'Kiwi',\n column2: 'Fruit',\n region: 'New Zealand'\n },\n {\n column1: 'Spinach',\n column2: 'Vegetable',\n region: 'California'\n }\n ];\n this.displayedRows = this.tableRows;\n\n this.myForm = this._fb.group({\n nameInput: new FormControl(''),\n typeInput: new FormControl(''),\n regionInput: new FormControl('')\n });\n }\n\n searchInputChanged(event: string): void {\n const filterRows = (row): boolean => {\n const keys = Object.keys(row);\n return !!keys.find((key) => row[key].toLowerCase().includes(event.toLowerCase()));\n };\n\n if (event) {\n this.displayedRows = this.tableRows.filter((row) => filterRows(row));\n } else {\n this.displayedRows = this.tableRows;\n }\n }\n\n resetSearch(): void {\n this.displayedRows = this.tableRows;\n this.searchTerm = '';\n }\n\n openDialog(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, { responsivePadding: true });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.confirmationReason = 'Dialog closed with result: ' + result;\n this.tableRows.push({\n column1: this.myForm.get('nameInput')?.value,\n column2: this.myForm.get('typeInput')?.value,\n region: this.myForm.get('regionInput')?.value\n });\n this.searchInputChanged(this.searchTerm);\n this.myForm.setValue({ nameInput: '', typeInput: '', regionInput: '' });\n this._cdr.detectChanges();\n },\n (error) => {\n this.confirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", + "html": "\n

    Table Toolbar Label ({{ tableRows.length }} rows)

    \n \n \n \n \n \n
    \n\n \n \n \n \n \n \n \n \n \n @for (row of displayedRows; track row) {\n \n \n \n \n \n }\n @if (!displayedRows || !displayedRows.length) {\n \n \n \n }\n \n
    NameTypeRegion Harvested
    {{ row.column1 }}{{ row.column2 }}{{ row.region }}
    No Results Found!
    \n
    \n\n \n \n

    New Item

    \n \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n
    \n
    \n" + }, + { + "name": "table-without-borders-example", + "description": "Table Without Borders", + "typescript": "import { Component, OnInit } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-without-borders-example',\n templateUrl: './table-without-borders-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, IconComponent]\n})\nexport class TableWithoutBordersExampleComponent implements OnInit {\n tableRows: any[];\n\n ngOnInit(): void {\n this.tableRows = [\n {\n column1: 'user.name@email.com',\n column2: 'Row 1',\n column3: 'Row 1',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3: 'Row 2',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n }\n}\n", + "html": "Table without Borders\n\n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}
    \n
    \nTable without Borders on Body\n\n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}
    \n
    \n" + }, + { + "name": "table-loading-example", + "description": "Table Loading", + "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective, range } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { SkeletonComponent } from '@fundamental-ngx/core/skeleton';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-loading-example',\n templateUrl: './table-loading-example.component.html',\n imports: [ButtonComponent, FocusableGridDirective, TableModule, SkeletonComponent]\n})\nexport class TableLoadingExampleComponent {\n loading = true;\n readonly loadingRange = range(3);\n}\n", + "html": "\n\n \n \n \n \n \n \n \n \n @if (!loading) {\n @for (rowI of loadingRange; track rowI) {\n \n @for (colI of loadingRange; track colI) {\n \n }\n \n }\n } @else {\n @for (_ of loadingRange; track $index) {\n \n @for (_ of loadingRange; track $index) {\n \n }\n \n }\n }\n \n
    Column 1Column 2Column 3
    Row {{ rowI + 1 }}, Col {{ colI + 1 }}
    \n \n
    \n" + }, + { + "name": "no-data-example", + "description": "No Data", + "typescript": "import { Component } from '@angular/core';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { IllustratedMessageModule } from '@fundamental-ngx/core/illustrated-message';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fdp-platform-table-no-data-example',\n templateUrl: './no-data-example.component.html',\n imports: [TableModule, LinkComponent, IconComponent, IllustratedMessageModule]\n})\nexport class NoDataExampleComponent {\n tableRows = [];\n\n sceneConfig = {\n scene: {\n url: 'assets/images/sapIllus-Scene-NoMail.svg',\n id: 'sapIllus-Scene-NoMail-1'\n },\n dialog: {\n url: 'assets/images/sapIllus-Dialog-NoMail.svg',\n id: 'sapIllus-Dialog-NoMail'\n }\n };\n}\n", + "html": "\n \n \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n

    Headline text goes here

    \n

    \n Description provides user with clarity and possible next steps.\n

    \n
    \n \n
    \n
    \n \n
    \n \n
    Column HeaderColumn HeaderColumn Header
    \n" + }, + { + "name": "table-custom-columns-example", + "description": "Table Custom Columns", + "typescript": "import { UpperCasePipe } from '@angular/common';\nimport { Component, ViewChild } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { DialogRef, DialogService } from '@fundamental-ngx/core/dialog';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableComponent, TableModule } from '@fundamental-ngx/core/table';\nimport { TableCustomDialogComponent } from './table-custom-dialog.component';\n\nexport interface DisplayedColumn {\n key: string;\n checked: boolean;\n}\n\nexport interface CellData {\n column1: string;\n column2: string;\n column3: string;\n date: string;\n type: string;\n}\n\nconst CELL_DATA: CellData[] = [\n { column1: 'Row 111', column2: 'Row 221', column3: 'Row 1', date: '09-07-18', type: 'search' },\n { column1: 'Row 112', column2: 'Row 222', column3: 'Row 2', date: '09-08-18', type: 'cart' },\n { column1: 'Row 113', column2: 'Row 223', column3: 'Row 3', date: '02-14-18', type: 'calendar' },\n { column1: 'Row 114', column2: 'Row 224', column3: 'Row 4', date: '12-30-17', type: 'search' },\n { column1: 'Row 115', column2: 'Row 225', column3: 'Row 5', date: '11-12-18', type: 'search' }\n];\n\n@Component({\n selector: 'fd-table-custom-columns-example',\n templateUrl: './table-custom-columns-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, IconComponent, ButtonComponent, UpperCasePipe]\n})\nexport class TableCustomColumnsExampleComponent {\n @ViewChild(TableComponent)\n tableComponent: TableComponent;\n\n displayedColumns: string[];\n originalDisplayedColumns: DisplayedColumn[];\n dataSource = CELL_DATA;\n dialogRef: DialogRef;\n\n constructor(private _dialogService: DialogService) {\n this.displayedColumns = Object.keys(this.dataSource[0]);\n this.originalDisplayedColumns = [];\n\n Object.keys(this.dataSource[0]).forEach((key) => {\n this.originalDisplayedColumns.push({ key, checked: true });\n });\n }\n\n openDialog(): void {\n const dialogRef = this._dialogService.open(TableCustomDialogComponent, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n data: {\n columns: this.originalDisplayedColumns\n }\n });\n\n dialogRef.afterClosed.subscribe(\n (columns) => {\n this.originalDisplayedColumns = [...columns];\n this._propagateChangeToDisplayedValue();\n },\n () => {\n console.log('closed without changes');\n }\n );\n }\n\n private _propagateChangeToDisplayedValue(): void {\n this.displayedColumns = [\n ...this.originalDisplayedColumns.filter((_col) => _col.checked).map((_col) => _col.key)\n ];\n this.tableComponent.reset(this.displayedColumns);\n }\n}\n", + "html": "\n \n \n @for (column of displayedColumns; track column) {\n \n }\n \n \n \n @for (row of dataSource; track row) {\n \n \n \n \n \n \n \n }\n \n
    {{ column | uppercase }}
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}
    \n
    \n
    \nChosen Columns: {{ displayedColumns }}\n
    \n
    \n\n" }, { "name": "table-popin-example", "description": "Table Popin", "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-popin-example',\n templateUrl: './table-popin-example.component.html',\n styles: [\n `\n .table-example-popin-title {\n margin: 0 0 10px 0;\n }\n `\n ],\n imports: [\n FocusableGridDirective,\n TableModule,\n FormLabelComponent,\n ObjectStatusComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class TablePopinExampleComponent {\n masterCheckbox: boolean | null = false;\n\n fruits: any[] = [\n {\n name: 'Banana',\n status: 'positive',\n statusName: 'Available',\n dateOfExpire: '12.06.2020',\n price: '5 EUR',\n country: 'India',\n description: `A banana is an elongated, edible fruit – botanically a berry – produced by several kinds of large herbaceous\n flowering plants in the genus Musa.`,\n checked: false\n },\n {\n name: 'Apple',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '10.06.2020',\n price: '5,5 EUR',\n country: 'USA',\n description: `An apple is an edible fruit produced by an apple tree (Malus domestica).\n Apple trees are cultivated worldwide and are the most widely grown species in the genus Malus.`,\n checked: false\n },\n {\n name: 'Pineapple',\n status: 'negative',\n statusName: 'Out of stock',\n dateOfExpire: '08.06.2020',\n price: '6 EUR',\n country: 'Mexico',\n description: `The pineapple (Ananas comosus) is a tropical plant with an edible fruit and the most\n economically significant plant in the family Bromeliaceae.`,\n checked: false\n },\n {\n name: 'Orange',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '18.06.2020',\n price: '10 EUR',\n country: 'Spain',\n description: `The orange is the fruit of various citrus species in the family Rutaceae\n (see list of plants known as orange); it primarily refers to Citrus × sinensis.`,\n checked: false\n }\n ];\n\n constructor() {}\n\n select(index: number, checked: boolean): void {\n this.fruits[index].checked = checked;\n\n this._handleMasterCheckboxState();\n }\n\n selectMaster(checked: boolean): void {\n checked ? this._selectAll() : this._deselectAll();\n\n this._handleMasterCheckboxState();\n }\n\n private _handleMasterCheckboxState(): void {\n this.masterCheckbox = this._allSelected() ? true : this._anySelected() ? null : false;\n }\n\n private _selectAll(): void {\n this.fruits.forEach((row) => (row.checked = true));\n }\n\n private _deselectAll(): void {\n this.fruits.forEach((row) => (row.checked = false));\n }\n\n private _anySelected(): boolean {\n return this.fruits.some((_row) => _row.checked);\n }\n\n private _allSelected(): boolean {\n return this.fruits.every((_row) => _row.checked);\n }\n}\n", "html": "
    \n

    Mobile Mode

    \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Tablet Mode

    \n \n \n \n Fruit Description\n Price\n Status\n Date Of Expire\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n {{ fruit.dateOfExpire }}\n \n \n \n \n \n \n \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Desktop Mode

    \n \n \n \n \n \n \n \n \n \n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n \n \n \n \n \n \n \n }\n \n
    NamePriceCountryStatusDate Of ExpireDescription
    \n {{ fruit.name }}\n \n {{ fruit.country }}\n \n {{ fruit.price }}\n \n \n \n {{ fruit.dateOfExpire }}\n \n {{ fruit.description }}\n \n \n
    \n
    \n
    \n

    Popin Mobile Mode with Checkboxes

    \n \n \n \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit; let ind = $index) {\n \n \n \n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n" + }, + { + "name": "table-focusable-example", + "description": "Table Focusable", + "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", + "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" } ] }, @@ -23167,17 +23197,17 @@ "typescript": "import { UpperCasePipe } from '@angular/common';\nimport { Component, ViewChild } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { DialogRef, DialogService } from '@fundamental-ngx/core/dialog';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableComponent, TableModule } from '@fundamental-ngx/core/table';\nimport { TableCustomDialogComponent } from './table-custom-dialog.component';\n\nexport interface DisplayedColumn {\n key: string;\n checked: boolean;\n}\n\nexport interface CellData {\n column1: string;\n column2: string;\n column3: string;\n date: string;\n type: string;\n}\n\nconst CELL_DATA: CellData[] = [\n { column1: 'Row 111', column2: 'Row 221', column3: 'Row 1', date: '09-07-18', type: 'search' },\n { column1: 'Row 112', column2: 'Row 222', column3: 'Row 2', date: '09-08-18', type: 'cart' },\n { column1: 'Row 113', column2: 'Row 223', column3: 'Row 3', date: '02-14-18', type: 'calendar' },\n { column1: 'Row 114', column2: 'Row 224', column3: 'Row 4', date: '12-30-17', type: 'search' },\n { column1: 'Row 115', column2: 'Row 225', column3: 'Row 5', date: '11-12-18', type: 'search' }\n];\n\n@Component({\n selector: 'fd-table-custom-columns-example',\n templateUrl: './table-custom-columns-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, IconComponent, ButtonComponent, UpperCasePipe]\n})\nexport class TableCustomColumnsExampleComponent {\n @ViewChild(TableComponent)\n tableComponent: TableComponent;\n\n displayedColumns: string[];\n originalDisplayedColumns: DisplayedColumn[];\n dataSource = CELL_DATA;\n dialogRef: DialogRef;\n\n constructor(private _dialogService: DialogService) {\n this.displayedColumns = Object.keys(this.dataSource[0]);\n this.originalDisplayedColumns = [];\n\n Object.keys(this.dataSource[0]).forEach((key) => {\n this.originalDisplayedColumns.push({ key, checked: true });\n });\n }\n\n openDialog(): void {\n const dialogRef = this._dialogService.open(TableCustomDialogComponent, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n data: {\n columns: this.originalDisplayedColumns\n }\n });\n\n dialogRef.afterClosed.subscribe(\n (columns) => {\n this.originalDisplayedColumns = [...columns];\n this._propagateChangeToDisplayedValue();\n },\n () => {\n console.log('closed without changes');\n }\n );\n }\n\n private _propagateChangeToDisplayedValue(): void {\n this.displayedColumns = [\n ...this.originalDisplayedColumns.filter((_col) => _col.checked).map((_col) => _col.key)\n ];\n this.tableComponent.reset(this.displayedColumns);\n }\n}\n", "html": "\n \n \n @for (column of displayedColumns; track column) {\n \n }\n \n \n \n @for (row of dataSource; track row) {\n \n \n \n \n \n \n \n }\n \n
    {{ column | uppercase }}
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}
    \n
    \n
    \nChosen Columns: {{ displayedColumns }}\n
    \n
    \n\n" }, - { - "name": "table-focusable-example", - "description": "Table Focusable", - "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", - "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" - }, { "name": "table-popin-example", "description": "Table Popin", "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-popin-example',\n templateUrl: './table-popin-example.component.html',\n styles: [\n `\n .table-example-popin-title {\n margin: 0 0 10px 0;\n }\n `\n ],\n imports: [\n FocusableGridDirective,\n TableModule,\n FormLabelComponent,\n ObjectStatusComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class TablePopinExampleComponent {\n masterCheckbox: boolean | null = false;\n\n fruits: any[] = [\n {\n name: 'Banana',\n status: 'positive',\n statusName: 'Available',\n dateOfExpire: '12.06.2020',\n price: '5 EUR',\n country: 'India',\n description: `A banana is an elongated, edible fruit – botanically a berry – produced by several kinds of large herbaceous\n flowering plants in the genus Musa.`,\n checked: false\n },\n {\n name: 'Apple',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '10.06.2020',\n price: '5,5 EUR',\n country: 'USA',\n description: `An apple is an edible fruit produced by an apple tree (Malus domestica).\n Apple trees are cultivated worldwide and are the most widely grown species in the genus Malus.`,\n checked: false\n },\n {\n name: 'Pineapple',\n status: 'negative',\n statusName: 'Out of stock',\n dateOfExpire: '08.06.2020',\n price: '6 EUR',\n country: 'Mexico',\n description: `The pineapple (Ananas comosus) is a tropical plant with an edible fruit and the most\n economically significant plant in the family Bromeliaceae.`,\n checked: false\n },\n {\n name: 'Orange',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '18.06.2020',\n price: '10 EUR',\n country: 'Spain',\n description: `The orange is the fruit of various citrus species in the family Rutaceae\n (see list of plants known as orange); it primarily refers to Citrus × sinensis.`,\n checked: false\n }\n ];\n\n constructor() {}\n\n select(index: number, checked: boolean): void {\n this.fruits[index].checked = checked;\n\n this._handleMasterCheckboxState();\n }\n\n selectMaster(checked: boolean): void {\n checked ? this._selectAll() : this._deselectAll();\n\n this._handleMasterCheckboxState();\n }\n\n private _handleMasterCheckboxState(): void {\n this.masterCheckbox = this._allSelected() ? true : this._anySelected() ? null : false;\n }\n\n private _selectAll(): void {\n this.fruits.forEach((row) => (row.checked = true));\n }\n\n private _deselectAll(): void {\n this.fruits.forEach((row) => (row.checked = false));\n }\n\n private _anySelected(): boolean {\n return this.fruits.some((_row) => _row.checked);\n }\n\n private _allSelected(): boolean {\n return this.fruits.every((_row) => _row.checked);\n }\n}\n", "html": "
    \n

    Mobile Mode

    \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Tablet Mode

    \n \n \n \n Fruit Description\n Price\n Status\n Date Of Expire\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n {{ fruit.dateOfExpire }}\n \n \n \n \n \n \n \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Desktop Mode

    \n \n \n \n \n \n \n \n \n \n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n \n \n \n \n \n \n \n }\n \n
    NamePriceCountryStatusDate Of ExpireDescription
    \n {{ fruit.name }}\n \n {{ fruit.country }}\n \n {{ fruit.price }}\n \n \n \n {{ fruit.dateOfExpire }}\n \n {{ fruit.description }}\n \n \n
    \n
    \n
    \n

    Popin Mobile Mode with Checkboxes

    \n \n \n \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit; let ind = $index) {\n \n \n \n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n" + }, + { + "name": "table-focusable-example", + "description": "Table Focusable", + "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", + "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" } ] }, @@ -23326,17 +23356,17 @@ "typescript": "import { UpperCasePipe } from '@angular/common';\nimport { Component, ViewChild } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { DialogRef, DialogService } from '@fundamental-ngx/core/dialog';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableComponent, TableModule } from '@fundamental-ngx/core/table';\nimport { TableCustomDialogComponent } from './table-custom-dialog.component';\n\nexport interface DisplayedColumn {\n key: string;\n checked: boolean;\n}\n\nexport interface CellData {\n column1: string;\n column2: string;\n column3: string;\n date: string;\n type: string;\n}\n\nconst CELL_DATA: CellData[] = [\n { column1: 'Row 111', column2: 'Row 221', column3: 'Row 1', date: '09-07-18', type: 'search' },\n { column1: 'Row 112', column2: 'Row 222', column3: 'Row 2', date: '09-08-18', type: 'cart' },\n { column1: 'Row 113', column2: 'Row 223', column3: 'Row 3', date: '02-14-18', type: 'calendar' },\n { column1: 'Row 114', column2: 'Row 224', column3: 'Row 4', date: '12-30-17', type: 'search' },\n { column1: 'Row 115', column2: 'Row 225', column3: 'Row 5', date: '11-12-18', type: 'search' }\n];\n\n@Component({\n selector: 'fd-table-custom-columns-example',\n templateUrl: './table-custom-columns-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, IconComponent, ButtonComponent, UpperCasePipe]\n})\nexport class TableCustomColumnsExampleComponent {\n @ViewChild(TableComponent)\n tableComponent: TableComponent;\n\n displayedColumns: string[];\n originalDisplayedColumns: DisplayedColumn[];\n dataSource = CELL_DATA;\n dialogRef: DialogRef;\n\n constructor(private _dialogService: DialogService) {\n this.displayedColumns = Object.keys(this.dataSource[0]);\n this.originalDisplayedColumns = [];\n\n Object.keys(this.dataSource[0]).forEach((key) => {\n this.originalDisplayedColumns.push({ key, checked: true });\n });\n }\n\n openDialog(): void {\n const dialogRef = this._dialogService.open(TableCustomDialogComponent, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n data: {\n columns: this.originalDisplayedColumns\n }\n });\n\n dialogRef.afterClosed.subscribe(\n (columns) => {\n this.originalDisplayedColumns = [...columns];\n this._propagateChangeToDisplayedValue();\n },\n () => {\n console.log('closed without changes');\n }\n );\n }\n\n private _propagateChangeToDisplayedValue(): void {\n this.displayedColumns = [\n ...this.originalDisplayedColumns.filter((_col) => _col.checked).map((_col) => _col.key)\n ];\n this.tableComponent.reset(this.displayedColumns);\n }\n}\n", "html": "\n \n \n @for (column of displayedColumns; track column) {\n \n }\n \n \n \n @for (row of dataSource; track row) {\n \n \n \n \n \n \n \n }\n \n
    {{ column | uppercase }}
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}
    \n
    \n
    \nChosen Columns: {{ displayedColumns }}\n
    \n
    \n\n" }, - { - "name": "table-focusable-example", - "description": "Table Focusable", - "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", - "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" - }, { "name": "table-popin-example", "description": "Table Popin", "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-popin-example',\n templateUrl: './table-popin-example.component.html',\n styles: [\n `\n .table-example-popin-title {\n margin: 0 0 10px 0;\n }\n `\n ],\n imports: [\n FocusableGridDirective,\n TableModule,\n FormLabelComponent,\n ObjectStatusComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class TablePopinExampleComponent {\n masterCheckbox: boolean | null = false;\n\n fruits: any[] = [\n {\n name: 'Banana',\n status: 'positive',\n statusName: 'Available',\n dateOfExpire: '12.06.2020',\n price: '5 EUR',\n country: 'India',\n description: `A banana is an elongated, edible fruit – botanically a berry – produced by several kinds of large herbaceous\n flowering plants in the genus Musa.`,\n checked: false\n },\n {\n name: 'Apple',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '10.06.2020',\n price: '5,5 EUR',\n country: 'USA',\n description: `An apple is an edible fruit produced by an apple tree (Malus domestica).\n Apple trees are cultivated worldwide and are the most widely grown species in the genus Malus.`,\n checked: false\n },\n {\n name: 'Pineapple',\n status: 'negative',\n statusName: 'Out of stock',\n dateOfExpire: '08.06.2020',\n price: '6 EUR',\n country: 'Mexico',\n description: `The pineapple (Ananas comosus) is a tropical plant with an edible fruit and the most\n economically significant plant in the family Bromeliaceae.`,\n checked: false\n },\n {\n name: 'Orange',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '18.06.2020',\n price: '10 EUR',\n country: 'Spain',\n description: `The orange is the fruit of various citrus species in the family Rutaceae\n (see list of plants known as orange); it primarily refers to Citrus × sinensis.`,\n checked: false\n }\n ];\n\n constructor() {}\n\n select(index: number, checked: boolean): void {\n this.fruits[index].checked = checked;\n\n this._handleMasterCheckboxState();\n }\n\n selectMaster(checked: boolean): void {\n checked ? this._selectAll() : this._deselectAll();\n\n this._handleMasterCheckboxState();\n }\n\n private _handleMasterCheckboxState(): void {\n this.masterCheckbox = this._allSelected() ? true : this._anySelected() ? null : false;\n }\n\n private _selectAll(): void {\n this.fruits.forEach((row) => (row.checked = true));\n }\n\n private _deselectAll(): void {\n this.fruits.forEach((row) => (row.checked = false));\n }\n\n private _anySelected(): boolean {\n return this.fruits.some((_row) => _row.checked);\n }\n\n private _allSelected(): boolean {\n return this.fruits.every((_row) => _row.checked);\n }\n}\n", "html": "
    \n

    Mobile Mode

    \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Tablet Mode

    \n \n \n \n Fruit Description\n Price\n Status\n Date Of Expire\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n {{ fruit.dateOfExpire }}\n \n \n \n \n \n \n \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Desktop Mode

    \n \n \n \n \n \n \n \n \n \n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n \n \n \n \n \n \n \n }\n \n
    NamePriceCountryStatusDate Of ExpireDescription
    \n {{ fruit.name }}\n \n {{ fruit.country }}\n \n {{ fruit.price }}\n \n \n \n {{ fruit.dateOfExpire }}\n \n {{ fruit.description }}\n \n \n
    \n
    \n
    \n

    Popin Mobile Mode with Checkboxes

    \n \n \n \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit; let ind = $index) {\n \n \n \n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n" + }, + { + "name": "table-focusable-example", + "description": "Table Focusable", + "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", + "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" } ] }, @@ -23456,17 +23486,17 @@ "typescript": "import { UpperCasePipe } from '@angular/common';\nimport { Component, ViewChild } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { DialogRef, DialogService } from '@fundamental-ngx/core/dialog';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableComponent, TableModule } from '@fundamental-ngx/core/table';\nimport { TableCustomDialogComponent } from './table-custom-dialog.component';\n\nexport interface DisplayedColumn {\n key: string;\n checked: boolean;\n}\n\nexport interface CellData {\n column1: string;\n column2: string;\n column3: string;\n date: string;\n type: string;\n}\n\nconst CELL_DATA: CellData[] = [\n { column1: 'Row 111', column2: 'Row 221', column3: 'Row 1', date: '09-07-18', type: 'search' },\n { column1: 'Row 112', column2: 'Row 222', column3: 'Row 2', date: '09-08-18', type: 'cart' },\n { column1: 'Row 113', column2: 'Row 223', column3: 'Row 3', date: '02-14-18', type: 'calendar' },\n { column1: 'Row 114', column2: 'Row 224', column3: 'Row 4', date: '12-30-17', type: 'search' },\n { column1: 'Row 115', column2: 'Row 225', column3: 'Row 5', date: '11-12-18', type: 'search' }\n];\n\n@Component({\n selector: 'fd-table-custom-columns-example',\n templateUrl: './table-custom-columns-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, IconComponent, ButtonComponent, UpperCasePipe]\n})\nexport class TableCustomColumnsExampleComponent {\n @ViewChild(TableComponent)\n tableComponent: TableComponent;\n\n displayedColumns: string[];\n originalDisplayedColumns: DisplayedColumn[];\n dataSource = CELL_DATA;\n dialogRef: DialogRef;\n\n constructor(private _dialogService: DialogService) {\n this.displayedColumns = Object.keys(this.dataSource[0]);\n this.originalDisplayedColumns = [];\n\n Object.keys(this.dataSource[0]).forEach((key) => {\n this.originalDisplayedColumns.push({ key, checked: true });\n });\n }\n\n openDialog(): void {\n const dialogRef = this._dialogService.open(TableCustomDialogComponent, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n data: {\n columns: this.originalDisplayedColumns\n }\n });\n\n dialogRef.afterClosed.subscribe(\n (columns) => {\n this.originalDisplayedColumns = [...columns];\n this._propagateChangeToDisplayedValue();\n },\n () => {\n console.log('closed without changes');\n }\n );\n }\n\n private _propagateChangeToDisplayedValue(): void {\n this.displayedColumns = [\n ...this.originalDisplayedColumns.filter((_col) => _col.checked).map((_col) => _col.key)\n ];\n this.tableComponent.reset(this.displayedColumns);\n }\n}\n", "html": "\n \n \n @for (column of displayedColumns; track column) {\n \n }\n \n \n \n @for (row of dataSource; track row) {\n \n \n \n \n \n \n \n }\n \n
    {{ column | uppercase }}
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}
    \n
    \n
    \nChosen Columns: {{ displayedColumns }}\n
    \n
    \n\n" }, - { - "name": "table-focusable-example", - "description": "Table Focusable", - "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", - "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" - }, { "name": "table-popin-example", "description": "Table Popin", "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-popin-example',\n templateUrl: './table-popin-example.component.html',\n styles: [\n `\n .table-example-popin-title {\n margin: 0 0 10px 0;\n }\n `\n ],\n imports: [\n FocusableGridDirective,\n TableModule,\n FormLabelComponent,\n ObjectStatusComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class TablePopinExampleComponent {\n masterCheckbox: boolean | null = false;\n\n fruits: any[] = [\n {\n name: 'Banana',\n status: 'positive',\n statusName: 'Available',\n dateOfExpire: '12.06.2020',\n price: '5 EUR',\n country: 'India',\n description: `A banana is an elongated, edible fruit – botanically a berry – produced by several kinds of large herbaceous\n flowering plants in the genus Musa.`,\n checked: false\n },\n {\n name: 'Apple',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '10.06.2020',\n price: '5,5 EUR',\n country: 'USA',\n description: `An apple is an edible fruit produced by an apple tree (Malus domestica).\n Apple trees are cultivated worldwide and are the most widely grown species in the genus Malus.`,\n checked: false\n },\n {\n name: 'Pineapple',\n status: 'negative',\n statusName: 'Out of stock',\n dateOfExpire: '08.06.2020',\n price: '6 EUR',\n country: 'Mexico',\n description: `The pineapple (Ananas comosus) is a tropical plant with an edible fruit and the most\n economically significant plant in the family Bromeliaceae.`,\n checked: false\n },\n {\n name: 'Orange',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '18.06.2020',\n price: '10 EUR',\n country: 'Spain',\n description: `The orange is the fruit of various citrus species in the family Rutaceae\n (see list of plants known as orange); it primarily refers to Citrus × sinensis.`,\n checked: false\n }\n ];\n\n constructor() {}\n\n select(index: number, checked: boolean): void {\n this.fruits[index].checked = checked;\n\n this._handleMasterCheckboxState();\n }\n\n selectMaster(checked: boolean): void {\n checked ? this._selectAll() : this._deselectAll();\n\n this._handleMasterCheckboxState();\n }\n\n private _handleMasterCheckboxState(): void {\n this.masterCheckbox = this._allSelected() ? true : this._anySelected() ? null : false;\n }\n\n private _selectAll(): void {\n this.fruits.forEach((row) => (row.checked = true));\n }\n\n private _deselectAll(): void {\n this.fruits.forEach((row) => (row.checked = false));\n }\n\n private _anySelected(): boolean {\n return this.fruits.some((_row) => _row.checked);\n }\n\n private _allSelected(): boolean {\n return this.fruits.every((_row) => _row.checked);\n }\n}\n", "html": "
    \n

    Mobile Mode

    \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Tablet Mode

    \n \n \n \n Fruit Description\n Price\n Status\n Date Of Expire\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n {{ fruit.dateOfExpire }}\n \n \n \n \n \n \n \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Desktop Mode

    \n \n \n \n \n \n \n \n \n \n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n \n \n \n \n \n \n \n }\n \n
    NamePriceCountryStatusDate Of ExpireDescription
    \n {{ fruit.name }}\n \n {{ fruit.country }}\n \n {{ fruit.price }}\n \n \n \n {{ fruit.dateOfExpire }}\n \n {{ fruit.description }}\n \n \n
    \n
    \n
    \n

    Popin Mobile Mode with Checkboxes

    \n \n \n \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit; let ind = $index) {\n \n \n \n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n" + }, + { + "name": "table-focusable-example", + "description": "Table Focusable", + "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", + "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" } ] }, @@ -23586,17 +23616,17 @@ "typescript": "import { UpperCasePipe } from '@angular/common';\nimport { Component, ViewChild } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { DialogRef, DialogService } from '@fundamental-ngx/core/dialog';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableComponent, TableModule } from '@fundamental-ngx/core/table';\nimport { TableCustomDialogComponent } from './table-custom-dialog.component';\n\nexport interface DisplayedColumn {\n key: string;\n checked: boolean;\n}\n\nexport interface CellData {\n column1: string;\n column2: string;\n column3: string;\n date: string;\n type: string;\n}\n\nconst CELL_DATA: CellData[] = [\n { column1: 'Row 111', column2: 'Row 221', column3: 'Row 1', date: '09-07-18', type: 'search' },\n { column1: 'Row 112', column2: 'Row 222', column3: 'Row 2', date: '09-08-18', type: 'cart' },\n { column1: 'Row 113', column2: 'Row 223', column3: 'Row 3', date: '02-14-18', type: 'calendar' },\n { column1: 'Row 114', column2: 'Row 224', column3: 'Row 4', date: '12-30-17', type: 'search' },\n { column1: 'Row 115', column2: 'Row 225', column3: 'Row 5', date: '11-12-18', type: 'search' }\n];\n\n@Component({\n selector: 'fd-table-custom-columns-example',\n templateUrl: './table-custom-columns-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, IconComponent, ButtonComponent, UpperCasePipe]\n})\nexport class TableCustomColumnsExampleComponent {\n @ViewChild(TableComponent)\n tableComponent: TableComponent;\n\n displayedColumns: string[];\n originalDisplayedColumns: DisplayedColumn[];\n dataSource = CELL_DATA;\n dialogRef: DialogRef;\n\n constructor(private _dialogService: DialogService) {\n this.displayedColumns = Object.keys(this.dataSource[0]);\n this.originalDisplayedColumns = [];\n\n Object.keys(this.dataSource[0]).forEach((key) => {\n this.originalDisplayedColumns.push({ key, checked: true });\n });\n }\n\n openDialog(): void {\n const dialogRef = this._dialogService.open(TableCustomDialogComponent, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n data: {\n columns: this.originalDisplayedColumns\n }\n });\n\n dialogRef.afterClosed.subscribe(\n (columns) => {\n this.originalDisplayedColumns = [...columns];\n this._propagateChangeToDisplayedValue();\n },\n () => {\n console.log('closed without changes');\n }\n );\n }\n\n private _propagateChangeToDisplayedValue(): void {\n this.displayedColumns = [\n ...this.originalDisplayedColumns.filter((_col) => _col.checked).map((_col) => _col.key)\n ];\n this.tableComponent.reset(this.displayedColumns);\n }\n}\n", "html": "\n \n \n @for (column of displayedColumns; track column) {\n \n }\n \n \n \n @for (row of dataSource; track row) {\n \n \n \n \n \n \n \n }\n \n
    {{ column | uppercase }}
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}
    \n
    \n
    \nChosen Columns: {{ displayedColumns }}\n
    \n
    \n\n" }, - { - "name": "table-focusable-example", - "description": "Table Focusable", - "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", - "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" - }, { "name": "table-popin-example", "description": "Table Popin", "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-popin-example',\n templateUrl: './table-popin-example.component.html',\n styles: [\n `\n .table-example-popin-title {\n margin: 0 0 10px 0;\n }\n `\n ],\n imports: [\n FocusableGridDirective,\n TableModule,\n FormLabelComponent,\n ObjectStatusComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class TablePopinExampleComponent {\n masterCheckbox: boolean | null = false;\n\n fruits: any[] = [\n {\n name: 'Banana',\n status: 'positive',\n statusName: 'Available',\n dateOfExpire: '12.06.2020',\n price: '5 EUR',\n country: 'India',\n description: `A banana is an elongated, edible fruit – botanically a berry – produced by several kinds of large herbaceous\n flowering plants in the genus Musa.`,\n checked: false\n },\n {\n name: 'Apple',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '10.06.2020',\n price: '5,5 EUR',\n country: 'USA',\n description: `An apple is an edible fruit produced by an apple tree (Malus domestica).\n Apple trees are cultivated worldwide and are the most widely grown species in the genus Malus.`,\n checked: false\n },\n {\n name: 'Pineapple',\n status: 'negative',\n statusName: 'Out of stock',\n dateOfExpire: '08.06.2020',\n price: '6 EUR',\n country: 'Mexico',\n description: `The pineapple (Ananas comosus) is a tropical plant with an edible fruit and the most\n economically significant plant in the family Bromeliaceae.`,\n checked: false\n },\n {\n name: 'Orange',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '18.06.2020',\n price: '10 EUR',\n country: 'Spain',\n description: `The orange is the fruit of various citrus species in the family Rutaceae\n (see list of plants known as orange); it primarily refers to Citrus × sinensis.`,\n checked: false\n }\n ];\n\n constructor() {}\n\n select(index: number, checked: boolean): void {\n this.fruits[index].checked = checked;\n\n this._handleMasterCheckboxState();\n }\n\n selectMaster(checked: boolean): void {\n checked ? this._selectAll() : this._deselectAll();\n\n this._handleMasterCheckboxState();\n }\n\n private _handleMasterCheckboxState(): void {\n this.masterCheckbox = this._allSelected() ? true : this._anySelected() ? null : false;\n }\n\n private _selectAll(): void {\n this.fruits.forEach((row) => (row.checked = true));\n }\n\n private _deselectAll(): void {\n this.fruits.forEach((row) => (row.checked = false));\n }\n\n private _anySelected(): boolean {\n return this.fruits.some((_row) => _row.checked);\n }\n\n private _allSelected(): boolean {\n return this.fruits.every((_row) => _row.checked);\n }\n}\n", "html": "
    \n

    Mobile Mode

    \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Tablet Mode

    \n \n \n \n Fruit Description\n Price\n Status\n Date Of Expire\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n {{ fruit.dateOfExpire }}\n \n \n \n \n \n \n \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Desktop Mode

    \n \n \n \n \n \n \n \n \n \n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n \n \n \n \n \n \n \n }\n \n
    NamePriceCountryStatusDate Of ExpireDescription
    \n {{ fruit.name }}\n \n {{ fruit.country }}\n \n {{ fruit.price }}\n \n \n \n {{ fruit.dateOfExpire }}\n \n {{ fruit.description }}\n \n \n
    \n
    \n
    \n

    Popin Mobile Mode with Checkboxes

    \n \n \n \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit; let ind = $index) {\n \n \n \n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n" + }, + { + "name": "table-focusable-example", + "description": "Table Focusable", + "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", + "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" } ] }, @@ -23858,17 +23888,17 @@ "typescript": "import { UpperCasePipe } from '@angular/common';\nimport { Component, ViewChild } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { DialogRef, DialogService } from '@fundamental-ngx/core/dialog';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableComponent, TableModule } from '@fundamental-ngx/core/table';\nimport { TableCustomDialogComponent } from './table-custom-dialog.component';\n\nexport interface DisplayedColumn {\n key: string;\n checked: boolean;\n}\n\nexport interface CellData {\n column1: string;\n column2: string;\n column3: string;\n date: string;\n type: string;\n}\n\nconst CELL_DATA: CellData[] = [\n { column1: 'Row 111', column2: 'Row 221', column3: 'Row 1', date: '09-07-18', type: 'search' },\n { column1: 'Row 112', column2: 'Row 222', column3: 'Row 2', date: '09-08-18', type: 'cart' },\n { column1: 'Row 113', column2: 'Row 223', column3: 'Row 3', date: '02-14-18', type: 'calendar' },\n { column1: 'Row 114', column2: 'Row 224', column3: 'Row 4', date: '12-30-17', type: 'search' },\n { column1: 'Row 115', column2: 'Row 225', column3: 'Row 5', date: '11-12-18', type: 'search' }\n];\n\n@Component({\n selector: 'fd-table-custom-columns-example',\n templateUrl: './table-custom-columns-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, IconComponent, ButtonComponent, UpperCasePipe]\n})\nexport class TableCustomColumnsExampleComponent {\n @ViewChild(TableComponent)\n tableComponent: TableComponent;\n\n displayedColumns: string[];\n originalDisplayedColumns: DisplayedColumn[];\n dataSource = CELL_DATA;\n dialogRef: DialogRef;\n\n constructor(private _dialogService: DialogService) {\n this.displayedColumns = Object.keys(this.dataSource[0]);\n this.originalDisplayedColumns = [];\n\n Object.keys(this.dataSource[0]).forEach((key) => {\n this.originalDisplayedColumns.push({ key, checked: true });\n });\n }\n\n openDialog(): void {\n const dialogRef = this._dialogService.open(TableCustomDialogComponent, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n data: {\n columns: this.originalDisplayedColumns\n }\n });\n\n dialogRef.afterClosed.subscribe(\n (columns) => {\n this.originalDisplayedColumns = [...columns];\n this._propagateChangeToDisplayedValue();\n },\n () => {\n console.log('closed without changes');\n }\n );\n }\n\n private _propagateChangeToDisplayedValue(): void {\n this.displayedColumns = [\n ...this.originalDisplayedColumns.filter((_col) => _col.checked).map((_col) => _col.key)\n ];\n this.tableComponent.reset(this.displayedColumns);\n }\n}\n", "html": "\n \n \n @for (column of displayedColumns; track column) {\n \n }\n \n \n \n @for (row of dataSource; track row) {\n \n \n \n \n \n \n \n }\n \n
    {{ column | uppercase }}
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}
    \n
    \n
    \nChosen Columns: {{ displayedColumns }}\n
    \n
    \n\n" }, - { - "name": "table-focusable-example", - "description": "Table Focusable", - "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", - "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" - }, { "name": "table-popin-example", "description": "Table Popin", "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-popin-example',\n templateUrl: './table-popin-example.component.html',\n styles: [\n `\n .table-example-popin-title {\n margin: 0 0 10px 0;\n }\n `\n ],\n imports: [\n FocusableGridDirective,\n TableModule,\n FormLabelComponent,\n ObjectStatusComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class TablePopinExampleComponent {\n masterCheckbox: boolean | null = false;\n\n fruits: any[] = [\n {\n name: 'Banana',\n status: 'positive',\n statusName: 'Available',\n dateOfExpire: '12.06.2020',\n price: '5 EUR',\n country: 'India',\n description: `A banana is an elongated, edible fruit – botanically a berry – produced by several kinds of large herbaceous\n flowering plants in the genus Musa.`,\n checked: false\n },\n {\n name: 'Apple',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '10.06.2020',\n price: '5,5 EUR',\n country: 'USA',\n description: `An apple is an edible fruit produced by an apple tree (Malus domestica).\n Apple trees are cultivated worldwide and are the most widely grown species in the genus Malus.`,\n checked: false\n },\n {\n name: 'Pineapple',\n status: 'negative',\n statusName: 'Out of stock',\n dateOfExpire: '08.06.2020',\n price: '6 EUR',\n country: 'Mexico',\n description: `The pineapple (Ananas comosus) is a tropical plant with an edible fruit and the most\n economically significant plant in the family Bromeliaceae.`,\n checked: false\n },\n {\n name: 'Orange',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '18.06.2020',\n price: '10 EUR',\n country: 'Spain',\n description: `The orange is the fruit of various citrus species in the family Rutaceae\n (see list of plants known as orange); it primarily refers to Citrus × sinensis.`,\n checked: false\n }\n ];\n\n constructor() {}\n\n select(index: number, checked: boolean): void {\n this.fruits[index].checked = checked;\n\n this._handleMasterCheckboxState();\n }\n\n selectMaster(checked: boolean): void {\n checked ? this._selectAll() : this._deselectAll();\n\n this._handleMasterCheckboxState();\n }\n\n private _handleMasterCheckboxState(): void {\n this.masterCheckbox = this._allSelected() ? true : this._anySelected() ? null : false;\n }\n\n private _selectAll(): void {\n this.fruits.forEach((row) => (row.checked = true));\n }\n\n private _deselectAll(): void {\n this.fruits.forEach((row) => (row.checked = false));\n }\n\n private _anySelected(): boolean {\n return this.fruits.some((_row) => _row.checked);\n }\n\n private _allSelected(): boolean {\n return this.fruits.every((_row) => _row.checked);\n }\n}\n", "html": "
    \n

    Mobile Mode

    \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Tablet Mode

    \n \n \n \n Fruit Description\n Price\n Status\n Date Of Expire\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n {{ fruit.dateOfExpire }}\n \n \n \n \n \n \n \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Desktop Mode

    \n \n \n \n \n \n \n \n \n \n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n \n \n \n \n \n \n \n }\n \n
    NamePriceCountryStatusDate Of ExpireDescription
    \n {{ fruit.name }}\n \n {{ fruit.country }}\n \n {{ fruit.price }}\n \n \n \n {{ fruit.dateOfExpire }}\n \n {{ fruit.description }}\n \n \n
    \n
    \n
    \n

    Popin Mobile Mode with Checkboxes

    \n \n \n \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit; let ind = $index) {\n \n \n \n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n" + }, + { + "name": "table-focusable-example", + "description": "Table Focusable", + "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", + "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" } ] }, @@ -23995,17 +24025,17 @@ "typescript": "import { UpperCasePipe } from '@angular/common';\nimport { Component, ViewChild } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { DialogRef, DialogService } from '@fundamental-ngx/core/dialog';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableComponent, TableModule } from '@fundamental-ngx/core/table';\nimport { TableCustomDialogComponent } from './table-custom-dialog.component';\n\nexport interface DisplayedColumn {\n key: string;\n checked: boolean;\n}\n\nexport interface CellData {\n column1: string;\n column2: string;\n column3: string;\n date: string;\n type: string;\n}\n\nconst CELL_DATA: CellData[] = [\n { column1: 'Row 111', column2: 'Row 221', column3: 'Row 1', date: '09-07-18', type: 'search' },\n { column1: 'Row 112', column2: 'Row 222', column3: 'Row 2', date: '09-08-18', type: 'cart' },\n { column1: 'Row 113', column2: 'Row 223', column3: 'Row 3', date: '02-14-18', type: 'calendar' },\n { column1: 'Row 114', column2: 'Row 224', column3: 'Row 4', date: '12-30-17', type: 'search' },\n { column1: 'Row 115', column2: 'Row 225', column3: 'Row 5', date: '11-12-18', type: 'search' }\n];\n\n@Component({\n selector: 'fd-table-custom-columns-example',\n templateUrl: './table-custom-columns-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, IconComponent, ButtonComponent, UpperCasePipe]\n})\nexport class TableCustomColumnsExampleComponent {\n @ViewChild(TableComponent)\n tableComponent: TableComponent;\n\n displayedColumns: string[];\n originalDisplayedColumns: DisplayedColumn[];\n dataSource = CELL_DATA;\n dialogRef: DialogRef;\n\n constructor(private _dialogService: DialogService) {\n this.displayedColumns = Object.keys(this.dataSource[0]);\n this.originalDisplayedColumns = [];\n\n Object.keys(this.dataSource[0]).forEach((key) => {\n this.originalDisplayedColumns.push({ key, checked: true });\n });\n }\n\n openDialog(): void {\n const dialogRef = this._dialogService.open(TableCustomDialogComponent, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n data: {\n columns: this.originalDisplayedColumns\n }\n });\n\n dialogRef.afterClosed.subscribe(\n (columns) => {\n this.originalDisplayedColumns = [...columns];\n this._propagateChangeToDisplayedValue();\n },\n () => {\n console.log('closed without changes');\n }\n );\n }\n\n private _propagateChangeToDisplayedValue(): void {\n this.displayedColumns = [\n ...this.originalDisplayedColumns.filter((_col) => _col.checked).map((_col) => _col.key)\n ];\n this.tableComponent.reset(this.displayedColumns);\n }\n}\n", "html": "\n \n \n @for (column of displayedColumns; track column) {\n \n }\n \n \n \n @for (row of dataSource; track row) {\n \n \n \n \n \n \n \n }\n \n
    {{ column | uppercase }}
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}
    \n
    \n
    \nChosen Columns: {{ displayedColumns }}\n
    \n
    \n\n" }, - { - "name": "table-focusable-example", - "description": "Table Focusable", - "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", - "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" - }, { "name": "table-popin-example", "description": "Table Popin", "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-popin-example',\n templateUrl: './table-popin-example.component.html',\n styles: [\n `\n .table-example-popin-title {\n margin: 0 0 10px 0;\n }\n `\n ],\n imports: [\n FocusableGridDirective,\n TableModule,\n FormLabelComponent,\n ObjectStatusComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class TablePopinExampleComponent {\n masterCheckbox: boolean | null = false;\n\n fruits: any[] = [\n {\n name: 'Banana',\n status: 'positive',\n statusName: 'Available',\n dateOfExpire: '12.06.2020',\n price: '5 EUR',\n country: 'India',\n description: `A banana is an elongated, edible fruit – botanically a berry – produced by several kinds of large herbaceous\n flowering plants in the genus Musa.`,\n checked: false\n },\n {\n name: 'Apple',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '10.06.2020',\n price: '5,5 EUR',\n country: 'USA',\n description: `An apple is an edible fruit produced by an apple tree (Malus domestica).\n Apple trees are cultivated worldwide and are the most widely grown species in the genus Malus.`,\n checked: false\n },\n {\n name: 'Pineapple',\n status: 'negative',\n statusName: 'Out of stock',\n dateOfExpire: '08.06.2020',\n price: '6 EUR',\n country: 'Mexico',\n description: `The pineapple (Ananas comosus) is a tropical plant with an edible fruit and the most\n economically significant plant in the family Bromeliaceae.`,\n checked: false\n },\n {\n name: 'Orange',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '18.06.2020',\n price: '10 EUR',\n country: 'Spain',\n description: `The orange is the fruit of various citrus species in the family Rutaceae\n (see list of plants known as orange); it primarily refers to Citrus × sinensis.`,\n checked: false\n }\n ];\n\n constructor() {}\n\n select(index: number, checked: boolean): void {\n this.fruits[index].checked = checked;\n\n this._handleMasterCheckboxState();\n }\n\n selectMaster(checked: boolean): void {\n checked ? this._selectAll() : this._deselectAll();\n\n this._handleMasterCheckboxState();\n }\n\n private _handleMasterCheckboxState(): void {\n this.masterCheckbox = this._allSelected() ? true : this._anySelected() ? null : false;\n }\n\n private _selectAll(): void {\n this.fruits.forEach((row) => (row.checked = true));\n }\n\n private _deselectAll(): void {\n this.fruits.forEach((row) => (row.checked = false));\n }\n\n private _anySelected(): boolean {\n return this.fruits.some((_row) => _row.checked);\n }\n\n private _allSelected(): boolean {\n return this.fruits.every((_row) => _row.checked);\n }\n}\n", "html": "
    \n

    Mobile Mode

    \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Tablet Mode

    \n \n \n \n Fruit Description\n Price\n Status\n Date Of Expire\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n {{ fruit.dateOfExpire }}\n \n \n \n \n \n \n \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Desktop Mode

    \n \n \n \n \n \n \n \n \n \n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n \n \n \n \n \n \n \n }\n \n
    NamePriceCountryStatusDate Of ExpireDescription
    \n {{ fruit.name }}\n \n {{ fruit.country }}\n \n {{ fruit.price }}\n \n \n \n {{ fruit.dateOfExpire }}\n \n {{ fruit.description }}\n \n \n
    \n
    \n
    \n

    Popin Mobile Mode with Checkboxes

    \n \n \n \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit; let ind = $index) {\n \n \n \n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n" + }, + { + "name": "table-focusable-example", + "description": "Table Focusable", + "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", + "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" } ] }, @@ -24153,17 +24183,17 @@ "typescript": "import { UpperCasePipe } from '@angular/common';\nimport { Component, ViewChild } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { DialogRef, DialogService } from '@fundamental-ngx/core/dialog';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableComponent, TableModule } from '@fundamental-ngx/core/table';\nimport { TableCustomDialogComponent } from './table-custom-dialog.component';\n\nexport interface DisplayedColumn {\n key: string;\n checked: boolean;\n}\n\nexport interface CellData {\n column1: string;\n column2: string;\n column3: string;\n date: string;\n type: string;\n}\n\nconst CELL_DATA: CellData[] = [\n { column1: 'Row 111', column2: 'Row 221', column3: 'Row 1', date: '09-07-18', type: 'search' },\n { column1: 'Row 112', column2: 'Row 222', column3: 'Row 2', date: '09-08-18', type: 'cart' },\n { column1: 'Row 113', column2: 'Row 223', column3: 'Row 3', date: '02-14-18', type: 'calendar' },\n { column1: 'Row 114', column2: 'Row 224', column3: 'Row 4', date: '12-30-17', type: 'search' },\n { column1: 'Row 115', column2: 'Row 225', column3: 'Row 5', date: '11-12-18', type: 'search' }\n];\n\n@Component({\n selector: 'fd-table-custom-columns-example',\n templateUrl: './table-custom-columns-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, IconComponent, ButtonComponent, UpperCasePipe]\n})\nexport class TableCustomColumnsExampleComponent {\n @ViewChild(TableComponent)\n tableComponent: TableComponent;\n\n displayedColumns: string[];\n originalDisplayedColumns: DisplayedColumn[];\n dataSource = CELL_DATA;\n dialogRef: DialogRef;\n\n constructor(private _dialogService: DialogService) {\n this.displayedColumns = Object.keys(this.dataSource[0]);\n this.originalDisplayedColumns = [];\n\n Object.keys(this.dataSource[0]).forEach((key) => {\n this.originalDisplayedColumns.push({ key, checked: true });\n });\n }\n\n openDialog(): void {\n const dialogRef = this._dialogService.open(TableCustomDialogComponent, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n data: {\n columns: this.originalDisplayedColumns\n }\n });\n\n dialogRef.afterClosed.subscribe(\n (columns) => {\n this.originalDisplayedColumns = [...columns];\n this._propagateChangeToDisplayedValue();\n },\n () => {\n console.log('closed without changes');\n }\n );\n }\n\n private _propagateChangeToDisplayedValue(): void {\n this.displayedColumns = [\n ...this.originalDisplayedColumns.filter((_col) => _col.checked).map((_col) => _col.key)\n ];\n this.tableComponent.reset(this.displayedColumns);\n }\n}\n", "html": "\n \n \n @for (column of displayedColumns; track column) {\n \n }\n \n \n \n @for (row of dataSource; track row) {\n \n \n \n \n \n \n \n }\n \n
    {{ column | uppercase }}
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}
    \n
    \n
    \nChosen Columns: {{ displayedColumns }}\n
    \n
    \n\n" }, - { - "name": "table-focusable-example", - "description": "Table Focusable", - "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", - "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" - }, { "name": "table-popin-example", "description": "Table Popin", "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-popin-example',\n templateUrl: './table-popin-example.component.html',\n styles: [\n `\n .table-example-popin-title {\n margin: 0 0 10px 0;\n }\n `\n ],\n imports: [\n FocusableGridDirective,\n TableModule,\n FormLabelComponent,\n ObjectStatusComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class TablePopinExampleComponent {\n masterCheckbox: boolean | null = false;\n\n fruits: any[] = [\n {\n name: 'Banana',\n status: 'positive',\n statusName: 'Available',\n dateOfExpire: '12.06.2020',\n price: '5 EUR',\n country: 'India',\n description: `A banana is an elongated, edible fruit – botanically a berry – produced by several kinds of large herbaceous\n flowering plants in the genus Musa.`,\n checked: false\n },\n {\n name: 'Apple',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '10.06.2020',\n price: '5,5 EUR',\n country: 'USA',\n description: `An apple is an edible fruit produced by an apple tree (Malus domestica).\n Apple trees are cultivated worldwide and are the most widely grown species in the genus Malus.`,\n checked: false\n },\n {\n name: 'Pineapple',\n status: 'negative',\n statusName: 'Out of stock',\n dateOfExpire: '08.06.2020',\n price: '6 EUR',\n country: 'Mexico',\n description: `The pineapple (Ananas comosus) is a tropical plant with an edible fruit and the most\n economically significant plant in the family Bromeliaceae.`,\n checked: false\n },\n {\n name: 'Orange',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '18.06.2020',\n price: '10 EUR',\n country: 'Spain',\n description: `The orange is the fruit of various citrus species in the family Rutaceae\n (see list of plants known as orange); it primarily refers to Citrus × sinensis.`,\n checked: false\n }\n ];\n\n constructor() {}\n\n select(index: number, checked: boolean): void {\n this.fruits[index].checked = checked;\n\n this._handleMasterCheckboxState();\n }\n\n selectMaster(checked: boolean): void {\n checked ? this._selectAll() : this._deselectAll();\n\n this._handleMasterCheckboxState();\n }\n\n private _handleMasterCheckboxState(): void {\n this.masterCheckbox = this._allSelected() ? true : this._anySelected() ? null : false;\n }\n\n private _selectAll(): void {\n this.fruits.forEach((row) => (row.checked = true));\n }\n\n private _deselectAll(): void {\n this.fruits.forEach((row) => (row.checked = false));\n }\n\n private _anySelected(): boolean {\n return this.fruits.some((_row) => _row.checked);\n }\n\n private _allSelected(): boolean {\n return this.fruits.every((_row) => _row.checked);\n }\n}\n", "html": "
    \n

    Mobile Mode

    \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Tablet Mode

    \n \n \n \n Fruit Description\n Price\n Status\n Date Of Expire\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n {{ fruit.dateOfExpire }}\n \n \n \n \n \n \n \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Desktop Mode

    \n \n \n \n \n \n \n \n \n \n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n \n \n \n \n \n \n \n }\n \n
    NamePriceCountryStatusDate Of ExpireDescription
    \n {{ fruit.name }}\n \n {{ fruit.country }}\n \n {{ fruit.price }}\n \n \n \n {{ fruit.dateOfExpire }}\n \n {{ fruit.description }}\n \n \n
    \n
    \n
    \n

    Popin Mobile Mode with Checkboxes

    \n \n \n \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit; let ind = $index) {\n \n \n \n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n" + }, + { + "name": "table-focusable-example", + "description": "Table Focusable", + "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", + "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" } ] }, @@ -29956,18 +29986,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

    Table card

    \n 3 of 10\n
    \n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    NameCountryPriceStatus
    BananaIndia5 EUR\n \n
    PineappleMexico2 EUR\n \n
    OrangeSpain6 EUR\n \n
    \n
    \n
    \n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
    \n \n \n \n

    My calendar

    \n

    {{ calendarViewSubTitle }}

    \n 4 of 10\n
    \n
    \n\n \n \n \n
    \n
    \n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -30080,18 +30110,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

    Table card

    \n 3 of 10\n
    \n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    NameCountryPriceStatus
    BananaIndia5 EUR\n \n
    PineappleMexico2 EUR\n \n
    OrangeSpain6 EUR\n \n
    \n
    \n
    \n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
    \n \n \n \n

    My calendar

    \n

    {{ calendarViewSubTitle }}

    \n 4 of 10\n
    \n
    \n\n \n \n \n
    \n
    \n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -30221,18 +30251,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

    Table card

    \n 3 of 10\n
    \n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    NameCountryPriceStatus
    BananaIndia5 EUR\n \n
    PineappleMexico2 EUR\n \n
    OrangeSpain6 EUR\n \n
    \n
    \n
    \n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
    \n \n \n \n

    My calendar

    \n

    {{ calendarViewSubTitle }}

    \n 4 of 10\n
    \n
    \n\n \n \n \n
    \n
    \n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -30345,18 +30375,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

    Table card

    \n 3 of 10\n
    \n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    NameCountryPriceStatus
    BananaIndia5 EUR\n \n
    PineappleMexico2 EUR\n \n
    OrangeSpain6 EUR\n \n
    \n
    \n
    \n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
    \n \n \n \n

    My calendar

    \n

    {{ calendarViewSubTitle }}

    \n 4 of 10\n
    \n
    \n\n \n \n \n
    \n
    \n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -30476,18 +30506,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

    Table card

    \n 3 of 10\n
    \n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    NameCountryPriceStatus
    BananaIndia5 EUR\n \n
    PineappleMexico2 EUR\n \n
    OrangeSpain6 EUR\n \n
    \n
    \n
    \n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
    \n \n \n \n

    My calendar

    \n

    {{ calendarViewSubTitle }}

    \n 4 of 10\n
    \n
    \n\n \n \n \n
    \n
    \n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -30600,18 +30630,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

    Table card

    \n 3 of 10\n
    \n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    NameCountryPriceStatus
    BananaIndia5 EUR\n \n
    PineappleMexico2 EUR\n \n
    OrangeSpain6 EUR\n \n
    \n
    \n
    \n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
    \n \n \n \n

    My calendar

    \n

    {{ calendarViewSubTitle }}

    \n 4 of 10\n
    \n
    \n\n \n \n \n
    \n
    \n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -30724,18 +30754,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

    Table card

    \n 3 of 10\n
    \n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    NameCountryPriceStatus
    BananaIndia5 EUR\n \n
    PineappleMexico2 EUR\n \n
    OrangeSpain6 EUR\n \n
    \n
    \n
    \n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
    \n \n \n \n

    My calendar

    \n

    {{ calendarViewSubTitle }}

    \n 4 of 10\n
    \n
    \n\n \n \n \n
    \n
    \n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -30848,18 +30878,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

    Table card

    \n 3 of 10\n
    \n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    NameCountryPriceStatus
    BananaIndia5 EUR\n \n
    PineappleMexico2 EUR\n \n
    OrangeSpain6 EUR\n \n
    \n
    \n
    \n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
    \n \n \n \n

    My calendar

    \n

    {{ calendarViewSubTitle }}

    \n 4 of 10\n
    \n
    \n\n \n \n \n
    \n
    \n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -30985,18 +31015,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

    Table card

    \n 3 of 10\n
    \n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    NameCountryPriceStatus
    BananaIndia5 EUR\n \n
    PineappleMexico2 EUR\n \n
    OrangeSpain6 EUR\n \n
    \n
    \n
    \n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
    \n \n \n \n

    My calendar

    \n

    {{ calendarViewSubTitle }}

    \n 4 of 10\n
    \n
    \n\n \n \n \n
    \n
    \n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -31134,18 +31164,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

    Table card

    \n 3 of 10\n
    \n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    NameCountryPriceStatus
    BananaIndia5 EUR\n \n
    PineappleMexico2 EUR\n \n
    OrangeSpain6 EUR\n \n
    \n
    \n
    \n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
    \n \n \n \n

    My calendar

    \n

    {{ calendarViewSubTitle }}

    \n 4 of 10\n
    \n
    \n\n \n \n \n
    \n
    \n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -31258,18 +31288,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

    Table card

    \n 3 of 10\n
    \n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    NameCountryPriceStatus
    BananaIndia5 EUR\n \n
    PineappleMexico2 EUR\n \n
    OrangeSpain6 EUR\n \n
    \n
    \n
    \n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
    \n \n \n \n

    My calendar

    \n

    {{ calendarViewSubTitle }}

    \n 4 of 10\n
    \n
    \n\n \n \n \n
    \n
    \n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -31389,18 +31419,18 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-card-table-example',\n templateUrl: './card-table-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, FocusableGridDirective, TableModule, ObjectStatusComponent]\n})\nexport class CardTableExampleComponent {}\n", "html": "\n \n \n

    Table card

    \n 3 of 10\n
    \n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    NameCountryPriceStatus
    BananaIndia5 EUR\n \n
    PineappleMexico2 EUR\n \n
    OrangeSpain6 EUR\n \n
    \n
    \n
    \n" }, - { - "name": "bar-chart-list-card-example", - "description": "Bar Chart List Card", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", - "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" - }, { "name": "card-calendar-example", "description": "Card Calendar", "typescript": "import { ChangeDetectorRef, Component } from '@angular/core';\nimport { CalendarComponent, FdCalendarView } from '@fundamental-ngx/core/calendar';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\n\n@Component({\n selector: 'fd-card-calendar-example',\n templateUrl: 'card-calendar-example.component.html',\n styleUrls: ['./card-calendar-example.component.scss'],\n imports: [CardModule, CalendarComponent, FdDatetimeModule]\n})\nexport class CardCalendarExampleComponent {\n calendarViewSubTitle = 'For Today';\n\n constructor(private _changeDetectorRef: ChangeDetectorRef) {}\n\n calendarViewChange(event: FdCalendarView): void {\n if (event === 'day') {\n this.calendarViewSubTitle = 'For Today';\n } else if (event === 'month') {\n this.calendarViewSubTitle = 'For This Month';\n } else if (event === 'year') {\n this.calendarViewSubTitle = 'For This Year';\n } else if (event === 'aggregatedYear') {\n this.calendarViewSubTitle = 'For This Year';\n }\n this._changeDetectorRef.markForCheck();\n }\n}\n", "html": "
    \n \n \n \n

    My calendar

    \n

    {{ calendarViewSubTitle }}

    \n 4 of 10\n
    \n
    \n\n \n \n \n
    \n
    \n" }, + { + "name": "bar-chart-list-card-example", + "description": "Bar Chart List Card", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { CardModule } from '@fundamental-ngx/core/card';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { CardBarComponent } from './card-bar.component';\n\n@Component({\n selector: 'fd-bar-chart-list-card-example',\n templateUrl: './bar-chart-list-card-example.component.html',\n styleUrls: ['./bar-chart-list-card-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CardModule, ListModule, CardBarComponent]\n})\nexport class BarChartListCardExampleComponent {}\n", + "html": "\n \n \n

    Bar Chart List Card

    \n 4 of 10\n
    \n
    \n \n
      \n
    • \n
      \n
      Contact A
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract B
      \n
      \n
      \n
    • \n
    • \n
      \n
      Contract C
      \n
      \n \n
      \n
      \n
    • \n
    • \n
      \n
      Contract D
      \n
      \n \n
      \n
      \n
    • \n
    \n
    \n
    \n" + }, { "name": "card-loading-example", "description": "Card Loading", @@ -33632,18 +33662,18 @@ "description": "Datetime Allow Null", "typescript": "import { Component } from '@angular/core';\n\nimport { FormsModule } from '@angular/forms';\nimport {\n DATE_TIME_FORMATS,\n DatetimeAdapter,\n FD_DATETIME_FORMATS,\n FdDate,\n FdDatetimeAdapter\n} from '@fundamental-ngx/core/datetime';\nimport { DatetimePickerComponent } from '@fundamental-ngx/core/datetime-picker';\n\n@Component({\n selector: 'fd-date-time-picker-allow-null-example',\n template: `\n \n
    \n
    \n Selected Date: {{ selectedDay || 'null' }}\n `,\n providers: [\n {\n provide: DatetimeAdapter,\n useClass: FdDatetimeAdapter\n },\n {\n provide: DATE_TIME_FORMATS,\n useValue: FD_DATETIME_FORMATS\n }\n ],\n imports: [DatetimePickerComponent, FormsModule]\n})\nexport class DatetimePickerAllowNullExampleComponent {\n selectedDay: FdDate = FdDate.getNow();\n}\n" }, - { - "name": "datetime-disabled-example", - "description": "Datetime Disabled", - "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport {\n DATE_TIME_FORMATS,\n DatetimeAdapter,\n FD_DATETIME_FORMATS,\n FdDate,\n FdDatetimeAdapter\n} from '@fundamental-ngx/core/datetime';\nimport { DatetimePickerComponent } from '@fundamental-ngx/core/datetime-picker';\n\n@Component({\n selector: 'fd-datetime-disabled-example',\n templateUrl: './datetime-disabled-example.component.html',\n providers: [\n {\n provide: DatetimeAdapter,\n useClass: FdDatetimeAdapter\n },\n {\n provide: DATE_TIME_FORMATS,\n useValue: FD_DATETIME_FORMATS\n }\n ],\n imports: [DatetimePickerComponent, FormsModule]\n})\nexport class DatetimeDisabledExampleComponent {\n date = FdDate.getNow();\n}\n", - "html": "\n\n" - }, { "name": "datetime-example", "description": "Datetime", "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport {\n DATE_TIME_FORMATS,\n DatetimeAdapter,\n FD_DATETIME_FORMATS,\n FdDate,\n FdDatetimeAdapter\n} from '@fundamental-ngx/core/datetime';\nimport { DatetimePickerComponent } from '@fundamental-ngx/core/datetime-picker';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\n\n@Component({\n selector: 'fd-datetime-example',\n templateUrl: './datetime-example.component.html',\n providers: [\n {\n provide: DatetimeAdapter,\n useClass: FdDatetimeAdapter\n },\n {\n provide: DATE_TIME_FORMATS,\n useValue: FD_DATETIME_FORMATS\n }\n ],\n imports: [FormLabelComponent, DatetimePickerComponent, FormsModule]\n})\nexport class DatetimeExampleComponent {\n date = FdDate.getNow();\n}\n", "html": "\n\n\n
    \n
    \n Selected: {{ date || 'null' }} \n" }, + { + "name": "datetime-disabled-example", + "description": "Datetime Disabled", + "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport {\n DATE_TIME_FORMATS,\n DatetimeAdapter,\n FD_DATETIME_FORMATS,\n FdDate,\n FdDatetimeAdapter\n} from '@fundamental-ngx/core/datetime';\nimport { DatetimePickerComponent } from '@fundamental-ngx/core/datetime-picker';\n\n@Component({\n selector: 'fd-datetime-disabled-example',\n templateUrl: './datetime-disabled-example.component.html',\n providers: [\n {\n provide: DatetimeAdapter,\n useClass: FdDatetimeAdapter\n },\n {\n provide: DATE_TIME_FORMATS,\n useValue: FD_DATETIME_FORMATS\n }\n ],\n imports: [DatetimePickerComponent, FormsModule]\n})\nexport class DatetimeDisabledExampleComponent {\n date = FdDate.getNow();\n}\n", + "html": "\n\n" + }, { "name": "datetime-form-example", "description": "Datetime Form", @@ -33700,18 +33730,18 @@ "description": "Datetime Allow Null", "typescript": "import { Component } from '@angular/core';\n\nimport { FormsModule } from '@angular/forms';\nimport {\n DATE_TIME_FORMATS,\n DatetimeAdapter,\n FD_DATETIME_FORMATS,\n FdDate,\n FdDatetimeAdapter\n} from '@fundamental-ngx/core/datetime';\nimport { DatetimePickerComponent } from '@fundamental-ngx/core/datetime-picker';\n\n@Component({\n selector: 'fd-date-time-picker-allow-null-example',\n template: `\n \n
    \n
    \n Selected Date: {{ selectedDay || 'null' }}\n `,\n providers: [\n {\n provide: DatetimeAdapter,\n useClass: FdDatetimeAdapter\n },\n {\n provide: DATE_TIME_FORMATS,\n useValue: FD_DATETIME_FORMATS\n }\n ],\n imports: [DatetimePickerComponent, FormsModule]\n})\nexport class DatetimePickerAllowNullExampleComponent {\n selectedDay: FdDate = FdDate.getNow();\n}\n" }, - { - "name": "datetime-disabled-example", - "description": "Datetime Disabled", - "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport {\n DATE_TIME_FORMATS,\n DatetimeAdapter,\n FD_DATETIME_FORMATS,\n FdDate,\n FdDatetimeAdapter\n} from '@fundamental-ngx/core/datetime';\nimport { DatetimePickerComponent } from '@fundamental-ngx/core/datetime-picker';\n\n@Component({\n selector: 'fd-datetime-disabled-example',\n templateUrl: './datetime-disabled-example.component.html',\n providers: [\n {\n provide: DatetimeAdapter,\n useClass: FdDatetimeAdapter\n },\n {\n provide: DATE_TIME_FORMATS,\n useValue: FD_DATETIME_FORMATS\n }\n ],\n imports: [DatetimePickerComponent, FormsModule]\n})\nexport class DatetimeDisabledExampleComponent {\n date = FdDate.getNow();\n}\n", - "html": "\n\n" - }, { "name": "datetime-example", "description": "Datetime", "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport {\n DATE_TIME_FORMATS,\n DatetimeAdapter,\n FD_DATETIME_FORMATS,\n FdDate,\n FdDatetimeAdapter\n} from '@fundamental-ngx/core/datetime';\nimport { DatetimePickerComponent } from '@fundamental-ngx/core/datetime-picker';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\n\n@Component({\n selector: 'fd-datetime-example',\n templateUrl: './datetime-example.component.html',\n providers: [\n {\n provide: DatetimeAdapter,\n useClass: FdDatetimeAdapter\n },\n {\n provide: DATE_TIME_FORMATS,\n useValue: FD_DATETIME_FORMATS\n }\n ],\n imports: [FormLabelComponent, DatetimePickerComponent, FormsModule]\n})\nexport class DatetimeExampleComponent {\n date = FdDate.getNow();\n}\n", "html": "\n\n\n
    \n
    \n Selected: {{ date || 'null' }} \n" }, + { + "name": "datetime-disabled-example", + "description": "Datetime Disabled", + "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport {\n DATE_TIME_FORMATS,\n DatetimeAdapter,\n FD_DATETIME_FORMATS,\n FdDate,\n FdDatetimeAdapter\n} from '@fundamental-ngx/core/datetime';\nimport { DatetimePickerComponent } from '@fundamental-ngx/core/datetime-picker';\n\n@Component({\n selector: 'fd-datetime-disabled-example',\n templateUrl: './datetime-disabled-example.component.html',\n providers: [\n {\n provide: DatetimeAdapter,\n useClass: FdDatetimeAdapter\n },\n {\n provide: DATE_TIME_FORMATS,\n useValue: FD_DATETIME_FORMATS\n }\n ],\n imports: [DatetimePickerComponent, FormsModule]\n})\nexport class DatetimeDisabledExampleComponent {\n date = FdDate.getNow();\n}\n", + "html": "\n\n" + }, { "name": "datetime-form-example", "description": "Datetime Form", @@ -33786,6 +33816,12 @@ "description": "Dialog", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\n\nimport { NgStyle } from '@angular/common';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogRef\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n template: `\n \n \n

    {{ dialogRef.data.title }}

    \n
    \n \n

    \n {{ dialogRef.data.pinnapleDescription }}\n

    \n
      \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
    • \n {{ fact }}\n
    • \n }\n
    \n
    \n \n \n \n \n \n \n
    \n `,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n" }, + { + "name": "dialog-configuration-example", + "description": "Dialog Configuration", + "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-configuration-example',\n templateUrl: './dialog-configuration-example.component.html',\n styleUrls: ['./dialog-configuration-example.component.scss'],\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogConfigurationExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDraggableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n draggable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openResizableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n resizable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openClosableByButtonDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n escKeyCloseable: false,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n}\n", + "html": "\n \n \n

    Origin of the Pineapple Word

    \n
    \n\n \n
    \n The word pineapple in English was first recorded in 1398, when it was originally used to describe the\n reproductive organs of conifer trees (now termed pine cones). When European explorers discovered this\n tropical fruit they called them pineapples (term first recorded in that sense in 1664) because of their\n resemblance to what is now known as the pine cone. The term pine cone was first recorded in 1694, and\n was used to replace the original meaning of pineapple.\n
    \n
    \n\n \n \n \n \n
    \n
    \n\n\n\n\n" + }, { "name": "dialog-backdrop-container-example", "description": "Dialog Backdrop Container", @@ -33798,30 +33834,24 @@ "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { AsyncPipe, NgClass } from '@angular/common';\nimport { Component, TemplateRef } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { InitialFocusDirective, TemplateDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ListModule, ListSecondaryDirective } from '@fundamental-ngx/core/list';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\ninterface Fruit {\n id: number;\n name: string;\n price: number;\n}\n\n@Component({\n selector: 'fd-dialog-complex-example',\n templateUrl: './dialog-complex-example.component.html',\n imports: [\n TemplateDirective,\n BarModule,\n TitleComponent,\n InputGroupModule,\n InitialFocusDirective,\n FormsModule,\n CdkScrollable,\n ScrollbarDirective,\n ListModule,\n NgClass,\n ListSecondaryDirective,\n ButtonComponent,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogComplexExampleComponent {\n fruitCollection: Fruit[] = [\n { id: 1, name: 'Pineapple', price: Infinity },\n { id: 2, name: 'Passion Fruit', price: 10.0 },\n { id: 3, name: 'Papaya', price: 8.99 },\n { id: 4, name: 'Kiwifruit', price: 3.0 },\n { id: 5, name: 'Mango', price: 15.0 },\n { id: 6, name: 'Pomegranate', price: 12.5 },\n { id: 7, name: 'Guava', price: 10.15 },\n { id: 8, name: 'Durian', price: 15.25 },\n { id: 9, name: 'Jackfruit', price: 10.0 },\n { id: 10, name: 'Dragon Fruit', price: 9.0 },\n { id: 11, name: 'Cherimoya', price: 7.45 },\n { id: 12, name: 'Kiwano', price: 4.5 },\n { id: 13, name: 'Korean Melon', price: 6.5 },\n { id: 14, name: 'Feijoa', price: 2.0 },\n { id: 15, name: 'Tamarillo ', price: 8.75 },\n { id: 16, name: 'Loquat', price: 0.99 }\n ];\n\n selectedFruits: Fruit[] = [];\n\n dialogRef: DialogRef;\n\n searchedPhrase = '';\n\n constructor(public _dialogService: DialogService) {}\n\n openDialog(template: TemplateRef): void {\n this.dialogRef = this._dialogService.open(template, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n ariaLabelledBy: 'fd-dialog-header-complex',\n ariaDescribedBy: 'fd-dialog-description-complex'\n });\n this.dialogRef.loading(true);\n setTimeout(() => this.dialogRef.loading(false), 2000);\n }\n\n get totalPrice(): number {\n const sum = this.selectedFruits.reduce((total, fruit) => total + fruit.price, 0);\n return Math.round(sum * 100) / 100;\n }\n\n filterFruits(fruits: Fruit[], searchedPhrase: string): Fruit[] {\n return this.fruitCollection.filter((fruit) => fruit.name.toLowerCase().includes(searchedPhrase.toLowerCase()));\n }\n\n isSelected(id: number): boolean {\n return this.selectedFruits.some((fruit) => fruit.id === id);\n }\n\n selectFruit(fruit: Fruit): void {\n const fruitIndex = this.selectedFruits.indexOf(fruit);\n\n if (fruitIndex !== -1) {\n this.selectedFruits.splice(fruitIndex, 1);\n } else {\n this.selectedFruits.push(fruit);\n }\n }\n\n clear(): void {\n this.searchedPhrase = '';\n this.selectedFruits = [];\n }\n\n checkout(): void {\n this.dialogRef.close();\n }\n}\n", "html": "\n \n \n \n
    \n \n

    Fresh Market

    \n Search for fresh produce items\n
    \n
    \n
    \n \n
    \n
    \n \n
    \n \n \n \n \n
    \n
    \n
    \n \n @if ((dialogRef.onLoading | async) === false) {\n
      \n @for (fruit of filterFruits(fruitCollection, searchedPhrase); track fruit) {\n
    • \n {{ fruit.name }}\n {{ fruit.price }} €\n
    • \n }\n
    \n }\n
    \n \n \n
    \n Total price: {{ totalPrice }}€ \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n" }, - { - "name": "dialog-configuration-example", - "description": "Dialog Configuration", - "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-configuration-example',\n templateUrl: './dialog-configuration-example.component.html',\n styleUrls: ['./dialog-configuration-example.component.scss'],\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogConfigurationExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDraggableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n draggable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openResizableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n resizable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openClosableByButtonDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n escKeyCloseable: false,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n}\n", - "html": "\n \n \n

    Origin of the Pineapple Word

    \n
    \n\n \n
    \n The word pineapple in English was first recorded in 1398, when it was originally used to describe the\n reproductive organs of conifer trees (now termed pine cones). When European explorers discovered this\n tropical fruit they called them pineapples (term first recorded in that sense in 1664) because of their\n resemblance to what is now known as the pine cone. The term pine cone was first recorded in 1694, and\n was used to replace the original meaning of pineapple.\n
    \n
    \n\n \n \n \n \n
    \n
    \n\n\n\n\n" - }, { "name": "form-dialog-example", "description": "Form Dialog", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { ChangeDetectionStrategy, ChangeDetectorRef, Component, TemplateRef } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-form-dialog-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './form-dialog-example.component.html',\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n CheckboxComponent,\n FormsModule,\n ButtonComponent,\n DialogHeaderComponent,\n DialogBodyComponent,\n DialogFooterComponent,\n DialogComponent\n ]\n})\nexport class FormDialogExampleComponent {\n confirmationReason: string;\n responsivePadding = false;\n verticalPadding = false;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openDialog(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: this.responsivePadding,\n focusTrapped: true,\n verticalPadding: this.verticalPadding,\n ariaLabelledBy: 'fd-dialog-header-form'\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.confirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.confirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", "html": "\n \n \n

    The History of Pineapple

    \n
    \n\n \n \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n \n
    \n\n \n \n\n \n \n
    \n
    \n\n\n\n\n\n

    {{ confirmationReason }}

    \n" }, - { - "name": "dialog-full-screen-example", - "description": "Dialog Full Screen", - "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\nimport { AsyncPipe, NgStyle } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n TemplateRef,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogDefaultContent,\n DialogFooterComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-full-screen-inner-example',\n template: ` \n \n

    {{ dialogRef.data.title }}

    \n \n
    \n \n \n {{ dialogRef.data.pinnapleDescription }}\n

    \n
      \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
    • \n {{ fact }}\n
    • \n }\n
    \n
    \n \n \n \n \n \n \n
    `,\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n AsyncPipe,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogFullScreenInnerExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n\n@Component({\n selector: 'fd-dialog-full-screen-example',\n imports: [\n ButtonComponent,\n BarModule,\n InputGroupModule,\n InitialFocusDirective,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n TitleComponent,\n DialogHeaderComponent,\n DialogComponent\n ],\n templateUrl: './dialog-full-screen-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DialogFullScreenExampleComponent {\n @ViewChild('dialogContent', { read: TemplateRef })\n dialogContent: TemplateRef;\n\n @ViewChild('dialogSubHeader', { read: TemplateRef })\n dialogSubHeader: TemplateRef;\n\n closeReason = '';\n\n templateBasedConfirmationReason = '';\n\n componentCloseReason = '';\n\n private _dialogReference: DialogRef;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openFromComponent(): void {\n const dialogRef = this._dialogService.open(DialogFullScreenInnerExampleComponent, {\n data: {\n title: `Pineapple Fun Facts`,\n pinnapleDescription: `\n The pineapple (Ananas comosus) is a tropical plant with an edible fruit\n and the most economically significant plant in the family Bromeliaceae.\n The pineapple is indigenous to South America,\n where it has been cultivated for many centuries.\n The introduction of the pineapple to Europe in the 17th\n century made it a significant cultural icon of luxury.\n Since the 1820s, pineapple has been commercially grown in\n greenhouses and many tropical plantations.\n `,\n pineappleFunFacts: [\n `You can grow your own pineapple by planting the top of the pineapple in soil`,\n `Pulling leaves from a pineapple is not an indication of ripeness as many people think`,\n `James Dole is considered the “King of Pineapples“`,\n `A pineapple cannot continue to ripen after it has been picked`,\n `An unripe pineapple not only tastes awful, but can also be poisonous`,\n `One of the ways you can tell if a pineapple is ripe is by smelling it`,\n `In Hawaii, the word for pineapple is “Hala kahiki“`\n ]\n },\n width: '400px',\n ariaLabelledBy: 'fd-dialog-header-fs-component',\n ariaDescribedBy: 'fd-dialog-body-fs-component',\n responsivePadding: true,\n draggable: true,\n resizable: true,\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.componentCloseReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.componentCloseReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialogFromTemplate(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: true,\n draggable: true,\n resizable: true,\n ariaLabelledBy: 'fd-dialog-header-fs-template',\n ariaDescribedBy: 'fd-dialog-body-fs-template',\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.templateBasedConfirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.templateBasedConfirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialog(): void {\n const object: DialogDefaultContent = {\n title: 'Dialog Title',\n titleId: 'fd-dialog-header-fs-object',\n content: this.dialogContent,\n contentId: 'fd-dialog-body-fs-object',\n subHeader: this.dialogSubHeader,\n approveButton: 'Ok',\n approveButtonAriaLabel: 'Ok Emphasized',\n approveButtonCallback: () => this._dialogReference.close('Approved'),\n cancelButton: 'Cancel',\n cancelButtonCallback: () => this._dialogReference.close('Canceled'),\n closeButtonCallback: () => this._dialogReference.dismiss('Dismissed'),\n fullScreenButtonCallback: () => this._dialogReference.toggleFullScreen(),\n closeButtonTitle: 'close',\n allowFullScreen: true,\n fullScreenExpandButtonText: 'Enter full-screen mode',\n fullScreenMinifyButtonText: 'Exit full-screen mode'\n };\n\n this._dialogReference = this._dialogService.open(object, {\n ariaLabelledBy: 'fd-dialog-header-fs-object',\n ariaDescribedBy: 'fd-dialog-body-fs-object',\n focusTrapped: true,\n resizable: true,\n draggable: true\n });\n\n this._dialogReference.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", - "html": "\n\n\n\n
    You can also create dialog without building whole template.
    \n
    \n\n\n
    \n \n \n \n
    \n
    \n\n

    {{ closeReason }}

    \n\n\n\n\n \n \n

    The History of Pineapple

    \n \n
    \n\n \n

    Are you interested in The Great History of Pineapple?

    \n
    \n\n \n \n\n \n \n
    \n
    \n\n\n

    {{ templateBasedConfirmationReason }}

    \n\n\n\n\n

    {{ componentCloseReason }}

    \n\n" - }, { "name": "dialog-mobile-example", "description": "Dialog Mobile", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { ContentDensityMode } from '@fundamental-ngx/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-mobile-example',\n templateUrl: './dialog-mobile-example.component.html',\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogMobileExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDialog(dialogTemplate): void {\n this._dialogService.open(dialogTemplate, {\n mobile: true,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-mobile',\n ariaDescribedBy: 'fd-dialog-body-mobile',\n contentDensity: ContentDensityMode.COZY\n });\n }\n}\n", "html": "\n \n \n

    Wild pineapples

    \n
    \n\n \n
    \n Certain bat-pollinated wild pineapples, members of the Bromeliad family, do the exact opposite of most\n flowers by opening their flowers at night and closing them during the day.\n
    \n
    \n\n \n \n \n \n
    \n
    \n\n\n" }, + { + "name": "dialog-full-screen-example", + "description": "Dialog Full Screen", + "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\nimport { AsyncPipe, NgStyle } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n TemplateRef,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogDefaultContent,\n DialogFooterComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-full-screen-inner-example',\n template: ` \n \n

    {{ dialogRef.data.title }}

    \n \n
    \n \n \n {{ dialogRef.data.pinnapleDescription }}\n

    \n
      \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
    • \n {{ fact }}\n
    • \n }\n
    \n
    \n \n \n \n \n \n \n
    `,\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n AsyncPipe,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogFullScreenInnerExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n\n@Component({\n selector: 'fd-dialog-full-screen-example',\n imports: [\n ButtonComponent,\n BarModule,\n InputGroupModule,\n InitialFocusDirective,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n TitleComponent,\n DialogHeaderComponent,\n DialogComponent\n ],\n templateUrl: './dialog-full-screen-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DialogFullScreenExampleComponent {\n @ViewChild('dialogContent', { read: TemplateRef })\n dialogContent: TemplateRef;\n\n @ViewChild('dialogSubHeader', { read: TemplateRef })\n dialogSubHeader: TemplateRef;\n\n closeReason = '';\n\n templateBasedConfirmationReason = '';\n\n componentCloseReason = '';\n\n private _dialogReference: DialogRef;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openFromComponent(): void {\n const dialogRef = this._dialogService.open(DialogFullScreenInnerExampleComponent, {\n data: {\n title: `Pineapple Fun Facts`,\n pinnapleDescription: `\n The pineapple (Ananas comosus) is a tropical plant with an edible fruit\n and the most economically significant plant in the family Bromeliaceae.\n The pineapple is indigenous to South America,\n where it has been cultivated for many centuries.\n The introduction of the pineapple to Europe in the 17th\n century made it a significant cultural icon of luxury.\n Since the 1820s, pineapple has been commercially grown in\n greenhouses and many tropical plantations.\n `,\n pineappleFunFacts: [\n `You can grow your own pineapple by planting the top of the pineapple in soil`,\n `Pulling leaves from a pineapple is not an indication of ripeness as many people think`,\n `James Dole is considered the “King of Pineapples“`,\n `A pineapple cannot continue to ripen after it has been picked`,\n `An unripe pineapple not only tastes awful, but can also be poisonous`,\n `One of the ways you can tell if a pineapple is ripe is by smelling it`,\n `In Hawaii, the word for pineapple is “Hala kahiki“`\n ]\n },\n width: '400px',\n ariaLabelledBy: 'fd-dialog-header-fs-component',\n ariaDescribedBy: 'fd-dialog-body-fs-component',\n responsivePadding: true,\n draggable: true,\n resizable: true,\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.componentCloseReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.componentCloseReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialogFromTemplate(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: true,\n draggable: true,\n resizable: true,\n ariaLabelledBy: 'fd-dialog-header-fs-template',\n ariaDescribedBy: 'fd-dialog-body-fs-template',\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.templateBasedConfirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.templateBasedConfirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialog(): void {\n const object: DialogDefaultContent = {\n title: 'Dialog Title',\n titleId: 'fd-dialog-header-fs-object',\n content: this.dialogContent,\n contentId: 'fd-dialog-body-fs-object',\n subHeader: this.dialogSubHeader,\n approveButton: 'Ok',\n approveButtonAriaLabel: 'Ok Emphasized',\n approveButtonCallback: () => this._dialogReference.close('Approved'),\n cancelButton: 'Cancel',\n cancelButtonCallback: () => this._dialogReference.close('Canceled'),\n closeButtonCallback: () => this._dialogReference.dismiss('Dismissed'),\n fullScreenButtonCallback: () => this._dialogReference.toggleFullScreen(),\n closeButtonTitle: 'close',\n allowFullScreen: true,\n fullScreenExpandButtonText: 'Enter full-screen mode',\n fullScreenMinifyButtonText: 'Exit full-screen mode'\n };\n\n this._dialogReference = this._dialogService.open(object, {\n ariaLabelledBy: 'fd-dialog-header-fs-object',\n ariaDescribedBy: 'fd-dialog-body-fs-object',\n focusTrapped: true,\n resizable: true,\n draggable: true\n });\n\n this._dialogReference.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", + "html": "\n\n\n\n
    You can also create dialog without building whole template.
    \n
    \n\n\n
    \n \n \n \n
    \n
    \n\n

    {{ closeReason }}

    \n\n\n\n\n \n \n

    The History of Pineapple

    \n \n
    \n\n \n

    Are you interested in The Great History of Pineapple?

    \n
    \n\n \n \n\n \n \n
    \n
    \n\n\n

    {{ templateBasedConfirmationReason }}

    \n\n\n\n\n

    {{ componentCloseReason }}

    \n\n" + }, { "name": "dialog-object-example", "description": "Dialog Object", @@ -33933,6 +33963,12 @@ "description": "Dialog", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\n\nimport { NgStyle } from '@angular/common';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogRef\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n template: `\n \n \n

    {{ dialogRef.data.title }}

    \n
    \n \n

    \n {{ dialogRef.data.pinnapleDescription }}\n

    \n
      \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
    • \n {{ fact }}\n
    • \n }\n
    \n
    \n \n \n \n \n \n \n
    \n `,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n" }, + { + "name": "dialog-configuration-example", + "description": "Dialog Configuration", + "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-configuration-example',\n templateUrl: './dialog-configuration-example.component.html',\n styleUrls: ['./dialog-configuration-example.component.scss'],\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogConfigurationExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDraggableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n draggable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openResizableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n resizable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openClosableByButtonDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n escKeyCloseable: false,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n}\n", + "html": "\n \n \n

    Origin of the Pineapple Word

    \n
    \n\n \n
    \n The word pineapple in English was first recorded in 1398, when it was originally used to describe the\n reproductive organs of conifer trees (now termed pine cones). When European explorers discovered this\n tropical fruit they called them pineapples (term first recorded in that sense in 1664) because of their\n resemblance to what is now known as the pine cone. The term pine cone was first recorded in 1694, and\n was used to replace the original meaning of pineapple.\n
    \n
    \n\n \n \n \n \n
    \n
    \n\n\n\n\n" + }, { "name": "dialog-backdrop-container-example", "description": "Dialog Backdrop Container", @@ -33945,30 +33981,24 @@ "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { AsyncPipe, NgClass } from '@angular/common';\nimport { Component, TemplateRef } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { InitialFocusDirective, TemplateDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ListModule, ListSecondaryDirective } from '@fundamental-ngx/core/list';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\ninterface Fruit {\n id: number;\n name: string;\n price: number;\n}\n\n@Component({\n selector: 'fd-dialog-complex-example',\n templateUrl: './dialog-complex-example.component.html',\n imports: [\n TemplateDirective,\n BarModule,\n TitleComponent,\n InputGroupModule,\n InitialFocusDirective,\n FormsModule,\n CdkScrollable,\n ScrollbarDirective,\n ListModule,\n NgClass,\n ListSecondaryDirective,\n ButtonComponent,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogComplexExampleComponent {\n fruitCollection: Fruit[] = [\n { id: 1, name: 'Pineapple', price: Infinity },\n { id: 2, name: 'Passion Fruit', price: 10.0 },\n { id: 3, name: 'Papaya', price: 8.99 },\n { id: 4, name: 'Kiwifruit', price: 3.0 },\n { id: 5, name: 'Mango', price: 15.0 },\n { id: 6, name: 'Pomegranate', price: 12.5 },\n { id: 7, name: 'Guava', price: 10.15 },\n { id: 8, name: 'Durian', price: 15.25 },\n { id: 9, name: 'Jackfruit', price: 10.0 },\n { id: 10, name: 'Dragon Fruit', price: 9.0 },\n { id: 11, name: 'Cherimoya', price: 7.45 },\n { id: 12, name: 'Kiwano', price: 4.5 },\n { id: 13, name: 'Korean Melon', price: 6.5 },\n { id: 14, name: 'Feijoa', price: 2.0 },\n { id: 15, name: 'Tamarillo ', price: 8.75 },\n { id: 16, name: 'Loquat', price: 0.99 }\n ];\n\n selectedFruits: Fruit[] = [];\n\n dialogRef: DialogRef;\n\n searchedPhrase = '';\n\n constructor(public _dialogService: DialogService) {}\n\n openDialog(template: TemplateRef): void {\n this.dialogRef = this._dialogService.open(template, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n ariaLabelledBy: 'fd-dialog-header-complex',\n ariaDescribedBy: 'fd-dialog-description-complex'\n });\n this.dialogRef.loading(true);\n setTimeout(() => this.dialogRef.loading(false), 2000);\n }\n\n get totalPrice(): number {\n const sum = this.selectedFruits.reduce((total, fruit) => total + fruit.price, 0);\n return Math.round(sum * 100) / 100;\n }\n\n filterFruits(fruits: Fruit[], searchedPhrase: string): Fruit[] {\n return this.fruitCollection.filter((fruit) => fruit.name.toLowerCase().includes(searchedPhrase.toLowerCase()));\n }\n\n isSelected(id: number): boolean {\n return this.selectedFruits.some((fruit) => fruit.id === id);\n }\n\n selectFruit(fruit: Fruit): void {\n const fruitIndex = this.selectedFruits.indexOf(fruit);\n\n if (fruitIndex !== -1) {\n this.selectedFruits.splice(fruitIndex, 1);\n } else {\n this.selectedFruits.push(fruit);\n }\n }\n\n clear(): void {\n this.searchedPhrase = '';\n this.selectedFruits = [];\n }\n\n checkout(): void {\n this.dialogRef.close();\n }\n}\n", "html": "\n \n \n \n
    \n \n

    Fresh Market

    \n Search for fresh produce items\n
    \n
    \n
    \n \n
    \n
    \n \n
    \n \n \n \n \n
    \n
    \n
    \n \n @if ((dialogRef.onLoading | async) === false) {\n
      \n @for (fruit of filterFruits(fruitCollection, searchedPhrase); track fruit) {\n
    • \n {{ fruit.name }}\n {{ fruit.price }} €\n
    • \n }\n
    \n }\n
    \n \n \n
    \n Total price: {{ totalPrice }}€ \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n" }, - { - "name": "dialog-configuration-example", - "description": "Dialog Configuration", - "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-configuration-example',\n templateUrl: './dialog-configuration-example.component.html',\n styleUrls: ['./dialog-configuration-example.component.scss'],\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogConfigurationExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDraggableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n draggable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openResizableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n resizable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openClosableByButtonDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n escKeyCloseable: false,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n}\n", - "html": "\n \n \n

    Origin of the Pineapple Word

    \n
    \n\n \n
    \n The word pineapple in English was first recorded in 1398, when it was originally used to describe the\n reproductive organs of conifer trees (now termed pine cones). When European explorers discovered this\n tropical fruit they called them pineapples (term first recorded in that sense in 1664) because of their\n resemblance to what is now known as the pine cone. The term pine cone was first recorded in 1694, and\n was used to replace the original meaning of pineapple.\n
    \n
    \n\n \n \n \n \n
    \n
    \n\n\n\n\n" - }, { "name": "form-dialog-example", "description": "Form Dialog", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { ChangeDetectionStrategy, ChangeDetectorRef, Component, TemplateRef } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-form-dialog-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './form-dialog-example.component.html',\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n CheckboxComponent,\n FormsModule,\n ButtonComponent,\n DialogHeaderComponent,\n DialogBodyComponent,\n DialogFooterComponent,\n DialogComponent\n ]\n})\nexport class FormDialogExampleComponent {\n confirmationReason: string;\n responsivePadding = false;\n verticalPadding = false;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openDialog(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: this.responsivePadding,\n focusTrapped: true,\n verticalPadding: this.verticalPadding,\n ariaLabelledBy: 'fd-dialog-header-form'\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.confirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.confirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", "html": "\n \n \n

    The History of Pineapple

    \n
    \n\n \n \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n \n
    \n\n \n \n\n \n \n
    \n
    \n\n\n\n\n\n

    {{ confirmationReason }}

    \n" }, - { - "name": "dialog-full-screen-example", - "description": "Dialog Full Screen", - "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\nimport { AsyncPipe, NgStyle } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n TemplateRef,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogDefaultContent,\n DialogFooterComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-full-screen-inner-example',\n template: ` \n \n

    {{ dialogRef.data.title }}

    \n \n
    \n \n \n {{ dialogRef.data.pinnapleDescription }}\n

    \n
      \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
    • \n {{ fact }}\n
    • \n }\n
    \n
    \n \n \n \n \n \n \n
    `,\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n AsyncPipe,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogFullScreenInnerExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n\n@Component({\n selector: 'fd-dialog-full-screen-example',\n imports: [\n ButtonComponent,\n BarModule,\n InputGroupModule,\n InitialFocusDirective,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n TitleComponent,\n DialogHeaderComponent,\n DialogComponent\n ],\n templateUrl: './dialog-full-screen-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DialogFullScreenExampleComponent {\n @ViewChild('dialogContent', { read: TemplateRef })\n dialogContent: TemplateRef;\n\n @ViewChild('dialogSubHeader', { read: TemplateRef })\n dialogSubHeader: TemplateRef;\n\n closeReason = '';\n\n templateBasedConfirmationReason = '';\n\n componentCloseReason = '';\n\n private _dialogReference: DialogRef;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openFromComponent(): void {\n const dialogRef = this._dialogService.open(DialogFullScreenInnerExampleComponent, {\n data: {\n title: `Pineapple Fun Facts`,\n pinnapleDescription: `\n The pineapple (Ananas comosus) is a tropical plant with an edible fruit\n and the most economically significant plant in the family Bromeliaceae.\n The pineapple is indigenous to South America,\n where it has been cultivated for many centuries.\n The introduction of the pineapple to Europe in the 17th\n century made it a significant cultural icon of luxury.\n Since the 1820s, pineapple has been commercially grown in\n greenhouses and many tropical plantations.\n `,\n pineappleFunFacts: [\n `You can grow your own pineapple by planting the top of the pineapple in soil`,\n `Pulling leaves from a pineapple is not an indication of ripeness as many people think`,\n `James Dole is considered the “King of Pineapples“`,\n `A pineapple cannot continue to ripen after it has been picked`,\n `An unripe pineapple not only tastes awful, but can also be poisonous`,\n `One of the ways you can tell if a pineapple is ripe is by smelling it`,\n `In Hawaii, the word for pineapple is “Hala kahiki“`\n ]\n },\n width: '400px',\n ariaLabelledBy: 'fd-dialog-header-fs-component',\n ariaDescribedBy: 'fd-dialog-body-fs-component',\n responsivePadding: true,\n draggable: true,\n resizable: true,\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.componentCloseReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.componentCloseReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialogFromTemplate(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: true,\n draggable: true,\n resizable: true,\n ariaLabelledBy: 'fd-dialog-header-fs-template',\n ariaDescribedBy: 'fd-dialog-body-fs-template',\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.templateBasedConfirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.templateBasedConfirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialog(): void {\n const object: DialogDefaultContent = {\n title: 'Dialog Title',\n titleId: 'fd-dialog-header-fs-object',\n content: this.dialogContent,\n contentId: 'fd-dialog-body-fs-object',\n subHeader: this.dialogSubHeader,\n approveButton: 'Ok',\n approveButtonAriaLabel: 'Ok Emphasized',\n approveButtonCallback: () => this._dialogReference.close('Approved'),\n cancelButton: 'Cancel',\n cancelButtonCallback: () => this._dialogReference.close('Canceled'),\n closeButtonCallback: () => this._dialogReference.dismiss('Dismissed'),\n fullScreenButtonCallback: () => this._dialogReference.toggleFullScreen(),\n closeButtonTitle: 'close',\n allowFullScreen: true,\n fullScreenExpandButtonText: 'Enter full-screen mode',\n fullScreenMinifyButtonText: 'Exit full-screen mode'\n };\n\n this._dialogReference = this._dialogService.open(object, {\n ariaLabelledBy: 'fd-dialog-header-fs-object',\n ariaDescribedBy: 'fd-dialog-body-fs-object',\n focusTrapped: true,\n resizable: true,\n draggable: true\n });\n\n this._dialogReference.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", - "html": "\n\n\n\n
    You can also create dialog without building whole template.
    \n
    \n\n\n
    \n \n \n \n
    \n
    \n\n

    {{ closeReason }}

    \n\n\n\n\n \n \n

    The History of Pineapple

    \n \n
    \n\n \n

    Are you interested in The Great History of Pineapple?

    \n
    \n\n \n \n\n \n \n
    \n
    \n\n\n

    {{ templateBasedConfirmationReason }}

    \n\n\n\n\n

    {{ componentCloseReason }}

    \n\n" - }, { "name": "dialog-mobile-example", "description": "Dialog Mobile", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { ContentDensityMode } from '@fundamental-ngx/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-mobile-example',\n templateUrl: './dialog-mobile-example.component.html',\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogMobileExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDialog(dialogTemplate): void {\n this._dialogService.open(dialogTemplate, {\n mobile: true,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-mobile',\n ariaDescribedBy: 'fd-dialog-body-mobile',\n contentDensity: ContentDensityMode.COZY\n });\n }\n}\n", "html": "\n \n \n

    Wild pineapples

    \n
    \n\n \n
    \n Certain bat-pollinated wild pineapples, members of the Bromeliad family, do the exact opposite of most\n flowers by opening their flowers at night and closing them during the day.\n
    \n
    \n\n \n \n \n \n
    \n
    \n\n\n" }, + { + "name": "dialog-full-screen-example", + "description": "Dialog Full Screen", + "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\nimport { AsyncPipe, NgStyle } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n TemplateRef,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogDefaultContent,\n DialogFooterComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-full-screen-inner-example',\n template: ` \n \n

    {{ dialogRef.data.title }}

    \n \n
    \n \n \n {{ dialogRef.data.pinnapleDescription }}\n

    \n
      \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
    • \n {{ fact }}\n
    • \n }\n
    \n
    \n \n \n \n \n \n \n
    `,\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n AsyncPipe,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogFullScreenInnerExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n\n@Component({\n selector: 'fd-dialog-full-screen-example',\n imports: [\n ButtonComponent,\n BarModule,\n InputGroupModule,\n InitialFocusDirective,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n TitleComponent,\n DialogHeaderComponent,\n DialogComponent\n ],\n templateUrl: './dialog-full-screen-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DialogFullScreenExampleComponent {\n @ViewChild('dialogContent', { read: TemplateRef })\n dialogContent: TemplateRef;\n\n @ViewChild('dialogSubHeader', { read: TemplateRef })\n dialogSubHeader: TemplateRef;\n\n closeReason = '';\n\n templateBasedConfirmationReason = '';\n\n componentCloseReason = '';\n\n private _dialogReference: DialogRef;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openFromComponent(): void {\n const dialogRef = this._dialogService.open(DialogFullScreenInnerExampleComponent, {\n data: {\n title: `Pineapple Fun Facts`,\n pinnapleDescription: `\n The pineapple (Ananas comosus) is a tropical plant with an edible fruit\n and the most economically significant plant in the family Bromeliaceae.\n The pineapple is indigenous to South America,\n where it has been cultivated for many centuries.\n The introduction of the pineapple to Europe in the 17th\n century made it a significant cultural icon of luxury.\n Since the 1820s, pineapple has been commercially grown in\n greenhouses and many tropical plantations.\n `,\n pineappleFunFacts: [\n `You can grow your own pineapple by planting the top of the pineapple in soil`,\n `Pulling leaves from a pineapple is not an indication of ripeness as many people think`,\n `James Dole is considered the “King of Pineapples“`,\n `A pineapple cannot continue to ripen after it has been picked`,\n `An unripe pineapple not only tastes awful, but can also be poisonous`,\n `One of the ways you can tell if a pineapple is ripe is by smelling it`,\n `In Hawaii, the word for pineapple is “Hala kahiki“`\n ]\n },\n width: '400px',\n ariaLabelledBy: 'fd-dialog-header-fs-component',\n ariaDescribedBy: 'fd-dialog-body-fs-component',\n responsivePadding: true,\n draggable: true,\n resizable: true,\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.componentCloseReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.componentCloseReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialogFromTemplate(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: true,\n draggable: true,\n resizable: true,\n ariaLabelledBy: 'fd-dialog-header-fs-template',\n ariaDescribedBy: 'fd-dialog-body-fs-template',\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.templateBasedConfirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.templateBasedConfirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialog(): void {\n const object: DialogDefaultContent = {\n title: 'Dialog Title',\n titleId: 'fd-dialog-header-fs-object',\n content: this.dialogContent,\n contentId: 'fd-dialog-body-fs-object',\n subHeader: this.dialogSubHeader,\n approveButton: 'Ok',\n approveButtonAriaLabel: 'Ok Emphasized',\n approveButtonCallback: () => this._dialogReference.close('Approved'),\n cancelButton: 'Cancel',\n cancelButtonCallback: () => this._dialogReference.close('Canceled'),\n closeButtonCallback: () => this._dialogReference.dismiss('Dismissed'),\n fullScreenButtonCallback: () => this._dialogReference.toggleFullScreen(),\n closeButtonTitle: 'close',\n allowFullScreen: true,\n fullScreenExpandButtonText: 'Enter full-screen mode',\n fullScreenMinifyButtonText: 'Exit full-screen mode'\n };\n\n this._dialogReference = this._dialogService.open(object, {\n ariaLabelledBy: 'fd-dialog-header-fs-object',\n ariaDescribedBy: 'fd-dialog-body-fs-object',\n focusTrapped: true,\n resizable: true,\n draggable: true\n });\n\n this._dialogReference.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", + "html": "\n\n\n\n
    You can also create dialog without building whole template.
    \n
    \n\n\n
    \n \n \n \n
    \n
    \n\n

    {{ closeReason }}

    \n\n\n\n\n \n \n

    The History of Pineapple

    \n \n
    \n\n \n

    Are you interested in The Great History of Pineapple?

    \n
    \n\n \n \n\n \n \n
    \n
    \n\n\n

    {{ templateBasedConfirmationReason }}

    \n\n\n\n\n

    {{ componentCloseReason }}

    \n\n" + }, { "name": "dialog-object-example", "description": "Dialog Object", @@ -34086,6 +34116,12 @@ "description": "Dialog", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\n\nimport { NgStyle } from '@angular/common';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogRef\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n template: `\n \n \n

    {{ dialogRef.data.title }}

    \n
    \n \n

    \n {{ dialogRef.data.pinnapleDescription }}\n

    \n
      \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
    • \n {{ fact }}\n
    • \n }\n
    \n
    \n \n \n \n \n \n \n
    \n `,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n" }, + { + "name": "dialog-configuration-example", + "description": "Dialog Configuration", + "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-configuration-example',\n templateUrl: './dialog-configuration-example.component.html',\n styleUrls: ['./dialog-configuration-example.component.scss'],\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogConfigurationExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDraggableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n draggable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openResizableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n resizable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openClosableByButtonDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n escKeyCloseable: false,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n}\n", + "html": "\n \n \n

    Origin of the Pineapple Word

    \n
    \n\n \n
    \n The word pineapple in English was first recorded in 1398, when it was originally used to describe the\n reproductive organs of conifer trees (now termed pine cones). When European explorers discovered this\n tropical fruit they called them pineapples (term first recorded in that sense in 1664) because of their\n resemblance to what is now known as the pine cone. The term pine cone was first recorded in 1694, and\n was used to replace the original meaning of pineapple.\n
    \n
    \n\n \n \n \n \n
    \n
    \n\n\n\n\n" + }, { "name": "dialog-backdrop-container-example", "description": "Dialog Backdrop Container", @@ -34098,30 +34134,24 @@ "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { AsyncPipe, NgClass } from '@angular/common';\nimport { Component, TemplateRef } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { InitialFocusDirective, TemplateDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ListModule, ListSecondaryDirective } from '@fundamental-ngx/core/list';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\ninterface Fruit {\n id: number;\n name: string;\n price: number;\n}\n\n@Component({\n selector: 'fd-dialog-complex-example',\n templateUrl: './dialog-complex-example.component.html',\n imports: [\n TemplateDirective,\n BarModule,\n TitleComponent,\n InputGroupModule,\n InitialFocusDirective,\n FormsModule,\n CdkScrollable,\n ScrollbarDirective,\n ListModule,\n NgClass,\n ListSecondaryDirective,\n ButtonComponent,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogComplexExampleComponent {\n fruitCollection: Fruit[] = [\n { id: 1, name: 'Pineapple', price: Infinity },\n { id: 2, name: 'Passion Fruit', price: 10.0 },\n { id: 3, name: 'Papaya', price: 8.99 },\n { id: 4, name: 'Kiwifruit', price: 3.0 },\n { id: 5, name: 'Mango', price: 15.0 },\n { id: 6, name: 'Pomegranate', price: 12.5 },\n { id: 7, name: 'Guava', price: 10.15 },\n { id: 8, name: 'Durian', price: 15.25 },\n { id: 9, name: 'Jackfruit', price: 10.0 },\n { id: 10, name: 'Dragon Fruit', price: 9.0 },\n { id: 11, name: 'Cherimoya', price: 7.45 },\n { id: 12, name: 'Kiwano', price: 4.5 },\n { id: 13, name: 'Korean Melon', price: 6.5 },\n { id: 14, name: 'Feijoa', price: 2.0 },\n { id: 15, name: 'Tamarillo ', price: 8.75 },\n { id: 16, name: 'Loquat', price: 0.99 }\n ];\n\n selectedFruits: Fruit[] = [];\n\n dialogRef: DialogRef;\n\n searchedPhrase = '';\n\n constructor(public _dialogService: DialogService) {}\n\n openDialog(template: TemplateRef): void {\n this.dialogRef = this._dialogService.open(template, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n ariaLabelledBy: 'fd-dialog-header-complex',\n ariaDescribedBy: 'fd-dialog-description-complex'\n });\n this.dialogRef.loading(true);\n setTimeout(() => this.dialogRef.loading(false), 2000);\n }\n\n get totalPrice(): number {\n const sum = this.selectedFruits.reduce((total, fruit) => total + fruit.price, 0);\n return Math.round(sum * 100) / 100;\n }\n\n filterFruits(fruits: Fruit[], searchedPhrase: string): Fruit[] {\n return this.fruitCollection.filter((fruit) => fruit.name.toLowerCase().includes(searchedPhrase.toLowerCase()));\n }\n\n isSelected(id: number): boolean {\n return this.selectedFruits.some((fruit) => fruit.id === id);\n }\n\n selectFruit(fruit: Fruit): void {\n const fruitIndex = this.selectedFruits.indexOf(fruit);\n\n if (fruitIndex !== -1) {\n this.selectedFruits.splice(fruitIndex, 1);\n } else {\n this.selectedFruits.push(fruit);\n }\n }\n\n clear(): void {\n this.searchedPhrase = '';\n this.selectedFruits = [];\n }\n\n checkout(): void {\n this.dialogRef.close();\n }\n}\n", "html": "\n \n \n \n
    \n \n

    Fresh Market

    \n Search for fresh produce items\n
    \n
    \n
    \n \n
    \n
    \n \n
    \n \n \n \n \n
    \n
    \n
    \n \n @if ((dialogRef.onLoading | async) === false) {\n
      \n @for (fruit of filterFruits(fruitCollection, searchedPhrase); track fruit) {\n
    • \n {{ fruit.name }}\n {{ fruit.price }} €\n
    • \n }\n
    \n }\n
    \n \n \n
    \n Total price: {{ totalPrice }}€ \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n" }, - { - "name": "dialog-configuration-example", - "description": "Dialog Configuration", - "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-configuration-example',\n templateUrl: './dialog-configuration-example.component.html',\n styleUrls: ['./dialog-configuration-example.component.scss'],\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogConfigurationExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDraggableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n draggable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openResizableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n resizable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openClosableByButtonDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n escKeyCloseable: false,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n}\n", - "html": "\n \n \n

    Origin of the Pineapple Word

    \n
    \n\n \n
    \n The word pineapple in English was first recorded in 1398, when it was originally used to describe the\n reproductive organs of conifer trees (now termed pine cones). When European explorers discovered this\n tropical fruit they called them pineapples (term first recorded in that sense in 1664) because of their\n resemblance to what is now known as the pine cone. The term pine cone was first recorded in 1694, and\n was used to replace the original meaning of pineapple.\n
    \n
    \n\n \n \n \n \n
    \n
    \n\n\n\n\n" - }, { "name": "form-dialog-example", "description": "Form Dialog", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { ChangeDetectionStrategy, ChangeDetectorRef, Component, TemplateRef } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-form-dialog-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './form-dialog-example.component.html',\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n CheckboxComponent,\n FormsModule,\n ButtonComponent,\n DialogHeaderComponent,\n DialogBodyComponent,\n DialogFooterComponent,\n DialogComponent\n ]\n})\nexport class FormDialogExampleComponent {\n confirmationReason: string;\n responsivePadding = false;\n verticalPadding = false;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openDialog(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: this.responsivePadding,\n focusTrapped: true,\n verticalPadding: this.verticalPadding,\n ariaLabelledBy: 'fd-dialog-header-form'\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.confirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.confirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", "html": "\n \n \n

    The History of Pineapple

    \n
    \n\n \n \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n \n
    \n\n \n \n\n \n \n
    \n
    \n\n\n\n\n\n

    {{ confirmationReason }}

    \n" }, - { - "name": "dialog-full-screen-example", - "description": "Dialog Full Screen", - "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\nimport { AsyncPipe, NgStyle } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n TemplateRef,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogDefaultContent,\n DialogFooterComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-full-screen-inner-example',\n template: ` \n \n

    {{ dialogRef.data.title }}

    \n \n
    \n \n \n {{ dialogRef.data.pinnapleDescription }}\n

    \n
      \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
    • \n {{ fact }}\n
    • \n }\n
    \n
    \n \n \n \n \n \n \n
    `,\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n AsyncPipe,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogFullScreenInnerExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n\n@Component({\n selector: 'fd-dialog-full-screen-example',\n imports: [\n ButtonComponent,\n BarModule,\n InputGroupModule,\n InitialFocusDirective,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n TitleComponent,\n DialogHeaderComponent,\n DialogComponent\n ],\n templateUrl: './dialog-full-screen-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DialogFullScreenExampleComponent {\n @ViewChild('dialogContent', { read: TemplateRef })\n dialogContent: TemplateRef;\n\n @ViewChild('dialogSubHeader', { read: TemplateRef })\n dialogSubHeader: TemplateRef;\n\n closeReason = '';\n\n templateBasedConfirmationReason = '';\n\n componentCloseReason = '';\n\n private _dialogReference: DialogRef;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openFromComponent(): void {\n const dialogRef = this._dialogService.open(DialogFullScreenInnerExampleComponent, {\n data: {\n title: `Pineapple Fun Facts`,\n pinnapleDescription: `\n The pineapple (Ananas comosus) is a tropical plant with an edible fruit\n and the most economically significant plant in the family Bromeliaceae.\n The pineapple is indigenous to South America,\n where it has been cultivated for many centuries.\n The introduction of the pineapple to Europe in the 17th\n century made it a significant cultural icon of luxury.\n Since the 1820s, pineapple has been commercially grown in\n greenhouses and many tropical plantations.\n `,\n pineappleFunFacts: [\n `You can grow your own pineapple by planting the top of the pineapple in soil`,\n `Pulling leaves from a pineapple is not an indication of ripeness as many people think`,\n `James Dole is considered the “King of Pineapples“`,\n `A pineapple cannot continue to ripen after it has been picked`,\n `An unripe pineapple not only tastes awful, but can also be poisonous`,\n `One of the ways you can tell if a pineapple is ripe is by smelling it`,\n `In Hawaii, the word for pineapple is “Hala kahiki“`\n ]\n },\n width: '400px',\n ariaLabelledBy: 'fd-dialog-header-fs-component',\n ariaDescribedBy: 'fd-dialog-body-fs-component',\n responsivePadding: true,\n draggable: true,\n resizable: true,\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.componentCloseReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.componentCloseReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialogFromTemplate(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: true,\n draggable: true,\n resizable: true,\n ariaLabelledBy: 'fd-dialog-header-fs-template',\n ariaDescribedBy: 'fd-dialog-body-fs-template',\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.templateBasedConfirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.templateBasedConfirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialog(): void {\n const object: DialogDefaultContent = {\n title: 'Dialog Title',\n titleId: 'fd-dialog-header-fs-object',\n content: this.dialogContent,\n contentId: 'fd-dialog-body-fs-object',\n subHeader: this.dialogSubHeader,\n approveButton: 'Ok',\n approveButtonAriaLabel: 'Ok Emphasized',\n approveButtonCallback: () => this._dialogReference.close('Approved'),\n cancelButton: 'Cancel',\n cancelButtonCallback: () => this._dialogReference.close('Canceled'),\n closeButtonCallback: () => this._dialogReference.dismiss('Dismissed'),\n fullScreenButtonCallback: () => this._dialogReference.toggleFullScreen(),\n closeButtonTitle: 'close',\n allowFullScreen: true,\n fullScreenExpandButtonText: 'Enter full-screen mode',\n fullScreenMinifyButtonText: 'Exit full-screen mode'\n };\n\n this._dialogReference = this._dialogService.open(object, {\n ariaLabelledBy: 'fd-dialog-header-fs-object',\n ariaDescribedBy: 'fd-dialog-body-fs-object',\n focusTrapped: true,\n resizable: true,\n draggable: true\n });\n\n this._dialogReference.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", - "html": "\n\n\n\n
    You can also create dialog without building whole template.
    \n
    \n\n\n
    \n \n \n \n
    \n
    \n\n

    {{ closeReason }}

    \n\n\n\n\n \n \n

    The History of Pineapple

    \n \n
    \n\n \n

    Are you interested in The Great History of Pineapple?

    \n
    \n\n \n \n\n \n \n
    \n
    \n\n\n

    {{ templateBasedConfirmationReason }}

    \n\n\n\n\n

    {{ componentCloseReason }}

    \n\n" - }, { "name": "dialog-mobile-example", "description": "Dialog Mobile", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { ContentDensityMode } from '@fundamental-ngx/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-mobile-example',\n templateUrl: './dialog-mobile-example.component.html',\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogMobileExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDialog(dialogTemplate): void {\n this._dialogService.open(dialogTemplate, {\n mobile: true,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-mobile',\n ariaDescribedBy: 'fd-dialog-body-mobile',\n contentDensity: ContentDensityMode.COZY\n });\n }\n}\n", "html": "\n \n \n

    Wild pineapples

    \n
    \n\n \n
    \n Certain bat-pollinated wild pineapples, members of the Bromeliad family, do the exact opposite of most\n flowers by opening their flowers at night and closing them during the day.\n
    \n
    \n\n \n \n \n \n
    \n
    \n\n\n" }, + { + "name": "dialog-full-screen-example", + "description": "Dialog Full Screen", + "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\nimport { AsyncPipe, NgStyle } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n TemplateRef,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogDefaultContent,\n DialogFooterComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-full-screen-inner-example',\n template: ` \n \n

    {{ dialogRef.data.title }}

    \n \n
    \n \n \n {{ dialogRef.data.pinnapleDescription }}\n

    \n
      \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
    • \n {{ fact }}\n
    • \n }\n
    \n
    \n \n \n \n \n \n \n
    `,\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n AsyncPipe,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogFullScreenInnerExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n\n@Component({\n selector: 'fd-dialog-full-screen-example',\n imports: [\n ButtonComponent,\n BarModule,\n InputGroupModule,\n InitialFocusDirective,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n TitleComponent,\n DialogHeaderComponent,\n DialogComponent\n ],\n templateUrl: './dialog-full-screen-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DialogFullScreenExampleComponent {\n @ViewChild('dialogContent', { read: TemplateRef })\n dialogContent: TemplateRef;\n\n @ViewChild('dialogSubHeader', { read: TemplateRef })\n dialogSubHeader: TemplateRef;\n\n closeReason = '';\n\n templateBasedConfirmationReason = '';\n\n componentCloseReason = '';\n\n private _dialogReference: DialogRef;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openFromComponent(): void {\n const dialogRef = this._dialogService.open(DialogFullScreenInnerExampleComponent, {\n data: {\n title: `Pineapple Fun Facts`,\n pinnapleDescription: `\n The pineapple (Ananas comosus) is a tropical plant with an edible fruit\n and the most economically significant plant in the family Bromeliaceae.\n The pineapple is indigenous to South America,\n where it has been cultivated for many centuries.\n The introduction of the pineapple to Europe in the 17th\n century made it a significant cultural icon of luxury.\n Since the 1820s, pineapple has been commercially grown in\n greenhouses and many tropical plantations.\n `,\n pineappleFunFacts: [\n `You can grow your own pineapple by planting the top of the pineapple in soil`,\n `Pulling leaves from a pineapple is not an indication of ripeness as many people think`,\n `James Dole is considered the “King of Pineapples“`,\n `A pineapple cannot continue to ripen after it has been picked`,\n `An unripe pineapple not only tastes awful, but can also be poisonous`,\n `One of the ways you can tell if a pineapple is ripe is by smelling it`,\n `In Hawaii, the word for pineapple is “Hala kahiki“`\n ]\n },\n width: '400px',\n ariaLabelledBy: 'fd-dialog-header-fs-component',\n ariaDescribedBy: 'fd-dialog-body-fs-component',\n responsivePadding: true,\n draggable: true,\n resizable: true,\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.componentCloseReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.componentCloseReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialogFromTemplate(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: true,\n draggable: true,\n resizable: true,\n ariaLabelledBy: 'fd-dialog-header-fs-template',\n ariaDescribedBy: 'fd-dialog-body-fs-template',\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.templateBasedConfirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.templateBasedConfirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialog(): void {\n const object: DialogDefaultContent = {\n title: 'Dialog Title',\n titleId: 'fd-dialog-header-fs-object',\n content: this.dialogContent,\n contentId: 'fd-dialog-body-fs-object',\n subHeader: this.dialogSubHeader,\n approveButton: 'Ok',\n approveButtonAriaLabel: 'Ok Emphasized',\n approveButtonCallback: () => this._dialogReference.close('Approved'),\n cancelButton: 'Cancel',\n cancelButtonCallback: () => this._dialogReference.close('Canceled'),\n closeButtonCallback: () => this._dialogReference.dismiss('Dismissed'),\n fullScreenButtonCallback: () => this._dialogReference.toggleFullScreen(),\n closeButtonTitle: 'close',\n allowFullScreen: true,\n fullScreenExpandButtonText: 'Enter full-screen mode',\n fullScreenMinifyButtonText: 'Exit full-screen mode'\n };\n\n this._dialogReference = this._dialogService.open(object, {\n ariaLabelledBy: 'fd-dialog-header-fs-object',\n ariaDescribedBy: 'fd-dialog-body-fs-object',\n focusTrapped: true,\n resizable: true,\n draggable: true\n });\n\n this._dialogReference.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", + "html": "\n\n\n\n
    You can also create dialog without building whole template.
    \n
    \n\n\n
    \n \n \n \n
    \n
    \n\n

    {{ closeReason }}

    \n\n\n\n\n \n \n

    The History of Pineapple

    \n \n
    \n\n \n

    Are you interested in The Great History of Pineapple?

    \n
    \n\n \n \n\n \n \n
    \n
    \n\n\n

    {{ templateBasedConfirmationReason }}

    \n\n\n\n\n

    {{ componentCloseReason }}

    \n\n" + }, { "name": "dialog-object-example", "description": "Dialog Object", @@ -34239,6 +34269,12 @@ "description": "Dialog", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\n\nimport { NgStyle } from '@angular/common';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogRef\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n template: `\n \n \n

    {{ dialogRef.data.title }}

    \n
    \n \n

    \n {{ dialogRef.data.pinnapleDescription }}\n

    \n
      \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
    • \n {{ fact }}\n
    • \n }\n
    \n
    \n \n \n \n \n \n \n
    \n `,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n" }, + { + "name": "dialog-configuration-example", + "description": "Dialog Configuration", + "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-configuration-example',\n templateUrl: './dialog-configuration-example.component.html',\n styleUrls: ['./dialog-configuration-example.component.scss'],\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogConfigurationExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDraggableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n draggable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openResizableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n resizable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openClosableByButtonDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n escKeyCloseable: false,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n}\n", + "html": "\n \n \n

    Origin of the Pineapple Word

    \n
    \n\n \n
    \n The word pineapple in English was first recorded in 1398, when it was originally used to describe the\n reproductive organs of conifer trees (now termed pine cones). When European explorers discovered this\n tropical fruit they called them pineapples (term first recorded in that sense in 1664) because of their\n resemblance to what is now known as the pine cone. The term pine cone was first recorded in 1694, and\n was used to replace the original meaning of pineapple.\n
    \n
    \n\n \n \n \n \n
    \n
    \n\n\n\n\n" + }, { "name": "dialog-backdrop-container-example", "description": "Dialog Backdrop Container", @@ -34251,30 +34287,24 @@ "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { AsyncPipe, NgClass } from '@angular/common';\nimport { Component, TemplateRef } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { InitialFocusDirective, TemplateDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ListModule, ListSecondaryDirective } from '@fundamental-ngx/core/list';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\ninterface Fruit {\n id: number;\n name: string;\n price: number;\n}\n\n@Component({\n selector: 'fd-dialog-complex-example',\n templateUrl: './dialog-complex-example.component.html',\n imports: [\n TemplateDirective,\n BarModule,\n TitleComponent,\n InputGroupModule,\n InitialFocusDirective,\n FormsModule,\n CdkScrollable,\n ScrollbarDirective,\n ListModule,\n NgClass,\n ListSecondaryDirective,\n ButtonComponent,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogComplexExampleComponent {\n fruitCollection: Fruit[] = [\n { id: 1, name: 'Pineapple', price: Infinity },\n { id: 2, name: 'Passion Fruit', price: 10.0 },\n { id: 3, name: 'Papaya', price: 8.99 },\n { id: 4, name: 'Kiwifruit', price: 3.0 },\n { id: 5, name: 'Mango', price: 15.0 },\n { id: 6, name: 'Pomegranate', price: 12.5 },\n { id: 7, name: 'Guava', price: 10.15 },\n { id: 8, name: 'Durian', price: 15.25 },\n { id: 9, name: 'Jackfruit', price: 10.0 },\n { id: 10, name: 'Dragon Fruit', price: 9.0 },\n { id: 11, name: 'Cherimoya', price: 7.45 },\n { id: 12, name: 'Kiwano', price: 4.5 },\n { id: 13, name: 'Korean Melon', price: 6.5 },\n { id: 14, name: 'Feijoa', price: 2.0 },\n { id: 15, name: 'Tamarillo ', price: 8.75 },\n { id: 16, name: 'Loquat', price: 0.99 }\n ];\n\n selectedFruits: Fruit[] = [];\n\n dialogRef: DialogRef;\n\n searchedPhrase = '';\n\n constructor(public _dialogService: DialogService) {}\n\n openDialog(template: TemplateRef): void {\n this.dialogRef = this._dialogService.open(template, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n ariaLabelledBy: 'fd-dialog-header-complex',\n ariaDescribedBy: 'fd-dialog-description-complex'\n });\n this.dialogRef.loading(true);\n setTimeout(() => this.dialogRef.loading(false), 2000);\n }\n\n get totalPrice(): number {\n const sum = this.selectedFruits.reduce((total, fruit) => total + fruit.price, 0);\n return Math.round(sum * 100) / 100;\n }\n\n filterFruits(fruits: Fruit[], searchedPhrase: string): Fruit[] {\n return this.fruitCollection.filter((fruit) => fruit.name.toLowerCase().includes(searchedPhrase.toLowerCase()));\n }\n\n isSelected(id: number): boolean {\n return this.selectedFruits.some((fruit) => fruit.id === id);\n }\n\n selectFruit(fruit: Fruit): void {\n const fruitIndex = this.selectedFruits.indexOf(fruit);\n\n if (fruitIndex !== -1) {\n this.selectedFruits.splice(fruitIndex, 1);\n } else {\n this.selectedFruits.push(fruit);\n }\n }\n\n clear(): void {\n this.searchedPhrase = '';\n this.selectedFruits = [];\n }\n\n checkout(): void {\n this.dialogRef.close();\n }\n}\n", "html": "\n \n \n \n
    \n \n

    Fresh Market

    \n Search for fresh produce items\n
    \n
    \n
    \n \n
    \n
    \n \n
    \n \n \n \n \n
    \n
    \n
    \n \n @if ((dialogRef.onLoading | async) === false) {\n
      \n @for (fruit of filterFruits(fruitCollection, searchedPhrase); track fruit) {\n
    • \n {{ fruit.name }}\n {{ fruit.price }} €\n
    • \n }\n
    \n }\n
    \n \n \n
    \n Total price: {{ totalPrice }}€ \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n" }, - { - "name": "dialog-configuration-example", - "description": "Dialog Configuration", - "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-configuration-example',\n templateUrl: './dialog-configuration-example.component.html',\n styleUrls: ['./dialog-configuration-example.component.scss'],\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogConfigurationExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDraggableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n draggable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openResizableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n resizable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openClosableByButtonDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n escKeyCloseable: false,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n}\n", - "html": "\n \n \n

    Origin of the Pineapple Word

    \n
    \n\n \n
    \n The word pineapple in English was first recorded in 1398, when it was originally used to describe the\n reproductive organs of conifer trees (now termed pine cones). When European explorers discovered this\n tropical fruit they called them pineapples (term first recorded in that sense in 1664) because of their\n resemblance to what is now known as the pine cone. The term pine cone was first recorded in 1694, and\n was used to replace the original meaning of pineapple.\n
    \n
    \n\n \n \n \n \n
    \n
    \n\n\n\n\n" - }, { "name": "form-dialog-example", "description": "Form Dialog", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { ChangeDetectionStrategy, ChangeDetectorRef, Component, TemplateRef } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-form-dialog-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './form-dialog-example.component.html',\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n CheckboxComponent,\n FormsModule,\n ButtonComponent,\n DialogHeaderComponent,\n DialogBodyComponent,\n DialogFooterComponent,\n DialogComponent\n ]\n})\nexport class FormDialogExampleComponent {\n confirmationReason: string;\n responsivePadding = false;\n verticalPadding = false;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openDialog(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: this.responsivePadding,\n focusTrapped: true,\n verticalPadding: this.verticalPadding,\n ariaLabelledBy: 'fd-dialog-header-form'\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.confirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.confirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", "html": "\n \n \n

    The History of Pineapple

    \n
    \n\n \n \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n \n
    \n\n \n \n\n \n \n
    \n
    \n\n\n\n\n\n

    {{ confirmationReason }}

    \n" }, - { - "name": "dialog-full-screen-example", - "description": "Dialog Full Screen", - "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\nimport { AsyncPipe, NgStyle } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n TemplateRef,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogDefaultContent,\n DialogFooterComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-full-screen-inner-example',\n template: ` \n \n

    {{ dialogRef.data.title }}

    \n \n
    \n \n \n {{ dialogRef.data.pinnapleDescription }}\n

    \n
      \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
    • \n {{ fact }}\n
    • \n }\n
    \n
    \n \n \n \n \n \n \n
    `,\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n AsyncPipe,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogFullScreenInnerExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n\n@Component({\n selector: 'fd-dialog-full-screen-example',\n imports: [\n ButtonComponent,\n BarModule,\n InputGroupModule,\n InitialFocusDirective,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n TitleComponent,\n DialogHeaderComponent,\n DialogComponent\n ],\n templateUrl: './dialog-full-screen-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DialogFullScreenExampleComponent {\n @ViewChild('dialogContent', { read: TemplateRef })\n dialogContent: TemplateRef;\n\n @ViewChild('dialogSubHeader', { read: TemplateRef })\n dialogSubHeader: TemplateRef;\n\n closeReason = '';\n\n templateBasedConfirmationReason = '';\n\n componentCloseReason = '';\n\n private _dialogReference: DialogRef;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openFromComponent(): void {\n const dialogRef = this._dialogService.open(DialogFullScreenInnerExampleComponent, {\n data: {\n title: `Pineapple Fun Facts`,\n pinnapleDescription: `\n The pineapple (Ananas comosus) is a tropical plant with an edible fruit\n and the most economically significant plant in the family Bromeliaceae.\n The pineapple is indigenous to South America,\n where it has been cultivated for many centuries.\n The introduction of the pineapple to Europe in the 17th\n century made it a significant cultural icon of luxury.\n Since the 1820s, pineapple has been commercially grown in\n greenhouses and many tropical plantations.\n `,\n pineappleFunFacts: [\n `You can grow your own pineapple by planting the top of the pineapple in soil`,\n `Pulling leaves from a pineapple is not an indication of ripeness as many people think`,\n `James Dole is considered the “King of Pineapples“`,\n `A pineapple cannot continue to ripen after it has been picked`,\n `An unripe pineapple not only tastes awful, but can also be poisonous`,\n `One of the ways you can tell if a pineapple is ripe is by smelling it`,\n `In Hawaii, the word for pineapple is “Hala kahiki“`\n ]\n },\n width: '400px',\n ariaLabelledBy: 'fd-dialog-header-fs-component',\n ariaDescribedBy: 'fd-dialog-body-fs-component',\n responsivePadding: true,\n draggable: true,\n resizable: true,\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.componentCloseReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.componentCloseReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialogFromTemplate(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: true,\n draggable: true,\n resizable: true,\n ariaLabelledBy: 'fd-dialog-header-fs-template',\n ariaDescribedBy: 'fd-dialog-body-fs-template',\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.templateBasedConfirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.templateBasedConfirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialog(): void {\n const object: DialogDefaultContent = {\n title: 'Dialog Title',\n titleId: 'fd-dialog-header-fs-object',\n content: this.dialogContent,\n contentId: 'fd-dialog-body-fs-object',\n subHeader: this.dialogSubHeader,\n approveButton: 'Ok',\n approveButtonAriaLabel: 'Ok Emphasized',\n approveButtonCallback: () => this._dialogReference.close('Approved'),\n cancelButton: 'Cancel',\n cancelButtonCallback: () => this._dialogReference.close('Canceled'),\n closeButtonCallback: () => this._dialogReference.dismiss('Dismissed'),\n fullScreenButtonCallback: () => this._dialogReference.toggleFullScreen(),\n closeButtonTitle: 'close',\n allowFullScreen: true,\n fullScreenExpandButtonText: 'Enter full-screen mode',\n fullScreenMinifyButtonText: 'Exit full-screen mode'\n };\n\n this._dialogReference = this._dialogService.open(object, {\n ariaLabelledBy: 'fd-dialog-header-fs-object',\n ariaDescribedBy: 'fd-dialog-body-fs-object',\n focusTrapped: true,\n resizable: true,\n draggable: true\n });\n\n this._dialogReference.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", - "html": "\n\n\n\n
    You can also create dialog without building whole template.
    \n
    \n\n\n
    \n \n \n \n
    \n
    \n\n

    {{ closeReason }}

    \n\n\n\n\n \n \n

    The History of Pineapple

    \n \n
    \n\n \n

    Are you interested in The Great History of Pineapple?

    \n
    \n\n \n \n\n \n \n
    \n
    \n\n\n

    {{ templateBasedConfirmationReason }}

    \n\n\n\n\n

    {{ componentCloseReason }}

    \n\n" - }, { "name": "dialog-mobile-example", "description": "Dialog Mobile", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { ContentDensityMode } from '@fundamental-ngx/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-mobile-example',\n templateUrl: './dialog-mobile-example.component.html',\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogMobileExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDialog(dialogTemplate): void {\n this._dialogService.open(dialogTemplate, {\n mobile: true,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-mobile',\n ariaDescribedBy: 'fd-dialog-body-mobile',\n contentDensity: ContentDensityMode.COZY\n });\n }\n}\n", "html": "\n \n \n

    Wild pineapples

    \n
    \n\n \n
    \n Certain bat-pollinated wild pineapples, members of the Bromeliad family, do the exact opposite of most\n flowers by opening their flowers at night and closing them during the day.\n
    \n
    \n\n \n \n \n \n
    \n
    \n\n\n" }, + { + "name": "dialog-full-screen-example", + "description": "Dialog Full Screen", + "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\nimport { AsyncPipe, NgStyle } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n TemplateRef,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogDefaultContent,\n DialogFooterComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-full-screen-inner-example',\n template: ` \n \n

    {{ dialogRef.data.title }}

    \n \n
    \n \n \n {{ dialogRef.data.pinnapleDescription }}\n

    \n
      \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
    • \n {{ fact }}\n
    • \n }\n
    \n
    \n \n \n \n \n \n \n
    `,\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n AsyncPipe,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogFullScreenInnerExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n\n@Component({\n selector: 'fd-dialog-full-screen-example',\n imports: [\n ButtonComponent,\n BarModule,\n InputGroupModule,\n InitialFocusDirective,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n TitleComponent,\n DialogHeaderComponent,\n DialogComponent\n ],\n templateUrl: './dialog-full-screen-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DialogFullScreenExampleComponent {\n @ViewChild('dialogContent', { read: TemplateRef })\n dialogContent: TemplateRef;\n\n @ViewChild('dialogSubHeader', { read: TemplateRef })\n dialogSubHeader: TemplateRef;\n\n closeReason = '';\n\n templateBasedConfirmationReason = '';\n\n componentCloseReason = '';\n\n private _dialogReference: DialogRef;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openFromComponent(): void {\n const dialogRef = this._dialogService.open(DialogFullScreenInnerExampleComponent, {\n data: {\n title: `Pineapple Fun Facts`,\n pinnapleDescription: `\n The pineapple (Ananas comosus) is a tropical plant with an edible fruit\n and the most economically significant plant in the family Bromeliaceae.\n The pineapple is indigenous to South America,\n where it has been cultivated for many centuries.\n The introduction of the pineapple to Europe in the 17th\n century made it a significant cultural icon of luxury.\n Since the 1820s, pineapple has been commercially grown in\n greenhouses and many tropical plantations.\n `,\n pineappleFunFacts: [\n `You can grow your own pineapple by planting the top of the pineapple in soil`,\n `Pulling leaves from a pineapple is not an indication of ripeness as many people think`,\n `James Dole is considered the “King of Pineapples“`,\n `A pineapple cannot continue to ripen after it has been picked`,\n `An unripe pineapple not only tastes awful, but can also be poisonous`,\n `One of the ways you can tell if a pineapple is ripe is by smelling it`,\n `In Hawaii, the word for pineapple is “Hala kahiki“`\n ]\n },\n width: '400px',\n ariaLabelledBy: 'fd-dialog-header-fs-component',\n ariaDescribedBy: 'fd-dialog-body-fs-component',\n responsivePadding: true,\n draggable: true,\n resizable: true,\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.componentCloseReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.componentCloseReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialogFromTemplate(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: true,\n draggable: true,\n resizable: true,\n ariaLabelledBy: 'fd-dialog-header-fs-template',\n ariaDescribedBy: 'fd-dialog-body-fs-template',\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.templateBasedConfirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.templateBasedConfirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialog(): void {\n const object: DialogDefaultContent = {\n title: 'Dialog Title',\n titleId: 'fd-dialog-header-fs-object',\n content: this.dialogContent,\n contentId: 'fd-dialog-body-fs-object',\n subHeader: this.dialogSubHeader,\n approveButton: 'Ok',\n approveButtonAriaLabel: 'Ok Emphasized',\n approveButtonCallback: () => this._dialogReference.close('Approved'),\n cancelButton: 'Cancel',\n cancelButtonCallback: () => this._dialogReference.close('Canceled'),\n closeButtonCallback: () => this._dialogReference.dismiss('Dismissed'),\n fullScreenButtonCallback: () => this._dialogReference.toggleFullScreen(),\n closeButtonTitle: 'close',\n allowFullScreen: true,\n fullScreenExpandButtonText: 'Enter full-screen mode',\n fullScreenMinifyButtonText: 'Exit full-screen mode'\n };\n\n this._dialogReference = this._dialogService.open(object, {\n ariaLabelledBy: 'fd-dialog-header-fs-object',\n ariaDescribedBy: 'fd-dialog-body-fs-object',\n focusTrapped: true,\n resizable: true,\n draggable: true\n });\n\n this._dialogReference.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", + "html": "\n\n\n\n
    You can also create dialog without building whole template.
    \n
    \n\n\n
    \n \n \n \n
    \n
    \n\n

    {{ closeReason }}

    \n\n\n\n\n \n \n

    The History of Pineapple

    \n \n
    \n\n \n

    Are you interested in The Great History of Pineapple?

    \n
    \n\n \n \n\n \n \n
    \n
    \n\n\n

    {{ templateBasedConfirmationReason }}

    \n\n\n\n\n

    {{ componentCloseReason }}

    \n\n" + }, { "name": "dialog-object-example", "description": "Dialog Object", @@ -34379,6 +34409,12 @@ "description": "Dialog", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\n\nimport { NgStyle } from '@angular/common';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogRef\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n template: `\n \n \n

    {{ dialogRef.data.title }}

    \n
    \n \n

    \n {{ dialogRef.data.pinnapleDescription }}\n

    \n
      \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
    • \n {{ fact }}\n
    • \n }\n
    \n
    \n \n \n \n \n \n \n
    \n `,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n" }, + { + "name": "dialog-configuration-example", + "description": "Dialog Configuration", + "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-configuration-example',\n templateUrl: './dialog-configuration-example.component.html',\n styleUrls: ['./dialog-configuration-example.component.scss'],\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogConfigurationExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDraggableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n draggable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openResizableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n resizable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openClosableByButtonDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n escKeyCloseable: false,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n}\n", + "html": "\n \n \n

    Origin of the Pineapple Word

    \n
    \n\n \n
    \n The word pineapple in English was first recorded in 1398, when it was originally used to describe the\n reproductive organs of conifer trees (now termed pine cones). When European explorers discovered this\n tropical fruit they called them pineapples (term first recorded in that sense in 1664) because of their\n resemblance to what is now known as the pine cone. The term pine cone was first recorded in 1694, and\n was used to replace the original meaning of pineapple.\n
    \n
    \n\n \n \n \n \n
    \n
    \n\n\n\n\n" + }, { "name": "dialog-backdrop-container-example", "description": "Dialog Backdrop Container", @@ -34391,30 +34427,24 @@ "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { AsyncPipe, NgClass } from '@angular/common';\nimport { Component, TemplateRef } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { InitialFocusDirective, TemplateDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ListModule, ListSecondaryDirective } from '@fundamental-ngx/core/list';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\ninterface Fruit {\n id: number;\n name: string;\n price: number;\n}\n\n@Component({\n selector: 'fd-dialog-complex-example',\n templateUrl: './dialog-complex-example.component.html',\n imports: [\n TemplateDirective,\n BarModule,\n TitleComponent,\n InputGroupModule,\n InitialFocusDirective,\n FormsModule,\n CdkScrollable,\n ScrollbarDirective,\n ListModule,\n NgClass,\n ListSecondaryDirective,\n ButtonComponent,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogComplexExampleComponent {\n fruitCollection: Fruit[] = [\n { id: 1, name: 'Pineapple', price: Infinity },\n { id: 2, name: 'Passion Fruit', price: 10.0 },\n { id: 3, name: 'Papaya', price: 8.99 },\n { id: 4, name: 'Kiwifruit', price: 3.0 },\n { id: 5, name: 'Mango', price: 15.0 },\n { id: 6, name: 'Pomegranate', price: 12.5 },\n { id: 7, name: 'Guava', price: 10.15 },\n { id: 8, name: 'Durian', price: 15.25 },\n { id: 9, name: 'Jackfruit', price: 10.0 },\n { id: 10, name: 'Dragon Fruit', price: 9.0 },\n { id: 11, name: 'Cherimoya', price: 7.45 },\n { id: 12, name: 'Kiwano', price: 4.5 },\n { id: 13, name: 'Korean Melon', price: 6.5 },\n { id: 14, name: 'Feijoa', price: 2.0 },\n { id: 15, name: 'Tamarillo ', price: 8.75 },\n { id: 16, name: 'Loquat', price: 0.99 }\n ];\n\n selectedFruits: Fruit[] = [];\n\n dialogRef: DialogRef;\n\n searchedPhrase = '';\n\n constructor(public _dialogService: DialogService) {}\n\n openDialog(template: TemplateRef): void {\n this.dialogRef = this._dialogService.open(template, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n ariaLabelledBy: 'fd-dialog-header-complex',\n ariaDescribedBy: 'fd-dialog-description-complex'\n });\n this.dialogRef.loading(true);\n setTimeout(() => this.dialogRef.loading(false), 2000);\n }\n\n get totalPrice(): number {\n const sum = this.selectedFruits.reduce((total, fruit) => total + fruit.price, 0);\n return Math.round(sum * 100) / 100;\n }\n\n filterFruits(fruits: Fruit[], searchedPhrase: string): Fruit[] {\n return this.fruitCollection.filter((fruit) => fruit.name.toLowerCase().includes(searchedPhrase.toLowerCase()));\n }\n\n isSelected(id: number): boolean {\n return this.selectedFruits.some((fruit) => fruit.id === id);\n }\n\n selectFruit(fruit: Fruit): void {\n const fruitIndex = this.selectedFruits.indexOf(fruit);\n\n if (fruitIndex !== -1) {\n this.selectedFruits.splice(fruitIndex, 1);\n } else {\n this.selectedFruits.push(fruit);\n }\n }\n\n clear(): void {\n this.searchedPhrase = '';\n this.selectedFruits = [];\n }\n\n checkout(): void {\n this.dialogRef.close();\n }\n}\n", "html": "\n \n \n \n
    \n \n

    Fresh Market

    \n Search for fresh produce items\n
    \n
    \n
    \n \n
    \n
    \n \n
    \n \n \n \n \n
    \n
    \n
    \n \n @if ((dialogRef.onLoading | async) === false) {\n
      \n @for (fruit of filterFruits(fruitCollection, searchedPhrase); track fruit) {\n
    • \n {{ fruit.name }}\n {{ fruit.price }} €\n
    • \n }\n
    \n }\n
    \n \n \n
    \n Total price: {{ totalPrice }}€ \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n" }, - { - "name": "dialog-configuration-example", - "description": "Dialog Configuration", - "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-configuration-example',\n templateUrl: './dialog-configuration-example.component.html',\n styleUrls: ['./dialog-configuration-example.component.scss'],\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogConfigurationExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDraggableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n draggable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openResizableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n resizable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openClosableByButtonDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n escKeyCloseable: false,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n}\n", - "html": "\n \n \n

    Origin of the Pineapple Word

    \n
    \n\n \n
    \n The word pineapple in English was first recorded in 1398, when it was originally used to describe the\n reproductive organs of conifer trees (now termed pine cones). When European explorers discovered this\n tropical fruit they called them pineapples (term first recorded in that sense in 1664) because of their\n resemblance to what is now known as the pine cone. The term pine cone was first recorded in 1694, and\n was used to replace the original meaning of pineapple.\n
    \n
    \n\n \n \n \n \n
    \n
    \n\n\n\n\n" - }, { "name": "form-dialog-example", "description": "Form Dialog", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { ChangeDetectionStrategy, ChangeDetectorRef, Component, TemplateRef } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-form-dialog-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './form-dialog-example.component.html',\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n CheckboxComponent,\n FormsModule,\n ButtonComponent,\n DialogHeaderComponent,\n DialogBodyComponent,\n DialogFooterComponent,\n DialogComponent\n ]\n})\nexport class FormDialogExampleComponent {\n confirmationReason: string;\n responsivePadding = false;\n verticalPadding = false;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openDialog(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: this.responsivePadding,\n focusTrapped: true,\n verticalPadding: this.verticalPadding,\n ariaLabelledBy: 'fd-dialog-header-form'\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.confirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.confirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", "html": "\n \n \n

    The History of Pineapple

    \n
    \n\n \n \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n \n
    \n\n \n \n\n \n \n
    \n
    \n\n\n\n\n\n

    {{ confirmationReason }}

    \n" }, - { - "name": "dialog-full-screen-example", - "description": "Dialog Full Screen", - "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\nimport { AsyncPipe, NgStyle } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n TemplateRef,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogDefaultContent,\n DialogFooterComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-full-screen-inner-example',\n template: ` \n \n

    {{ dialogRef.data.title }}

    \n \n
    \n \n \n {{ dialogRef.data.pinnapleDescription }}\n

    \n
      \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
    • \n {{ fact }}\n
    • \n }\n
    \n
    \n \n \n \n \n \n \n
    `,\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n AsyncPipe,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogFullScreenInnerExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n\n@Component({\n selector: 'fd-dialog-full-screen-example',\n imports: [\n ButtonComponent,\n BarModule,\n InputGroupModule,\n InitialFocusDirective,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n TitleComponent,\n DialogHeaderComponent,\n DialogComponent\n ],\n templateUrl: './dialog-full-screen-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DialogFullScreenExampleComponent {\n @ViewChild('dialogContent', { read: TemplateRef })\n dialogContent: TemplateRef;\n\n @ViewChild('dialogSubHeader', { read: TemplateRef })\n dialogSubHeader: TemplateRef;\n\n closeReason = '';\n\n templateBasedConfirmationReason = '';\n\n componentCloseReason = '';\n\n private _dialogReference: DialogRef;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openFromComponent(): void {\n const dialogRef = this._dialogService.open(DialogFullScreenInnerExampleComponent, {\n data: {\n title: `Pineapple Fun Facts`,\n pinnapleDescription: `\n The pineapple (Ananas comosus) is a tropical plant with an edible fruit\n and the most economically significant plant in the family Bromeliaceae.\n The pineapple is indigenous to South America,\n where it has been cultivated for many centuries.\n The introduction of the pineapple to Europe in the 17th\n century made it a significant cultural icon of luxury.\n Since the 1820s, pineapple has been commercially grown in\n greenhouses and many tropical plantations.\n `,\n pineappleFunFacts: [\n `You can grow your own pineapple by planting the top of the pineapple in soil`,\n `Pulling leaves from a pineapple is not an indication of ripeness as many people think`,\n `James Dole is considered the “King of Pineapples“`,\n `A pineapple cannot continue to ripen after it has been picked`,\n `An unripe pineapple not only tastes awful, but can also be poisonous`,\n `One of the ways you can tell if a pineapple is ripe is by smelling it`,\n `In Hawaii, the word for pineapple is “Hala kahiki“`\n ]\n },\n width: '400px',\n ariaLabelledBy: 'fd-dialog-header-fs-component',\n ariaDescribedBy: 'fd-dialog-body-fs-component',\n responsivePadding: true,\n draggable: true,\n resizable: true,\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.componentCloseReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.componentCloseReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialogFromTemplate(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: true,\n draggable: true,\n resizable: true,\n ariaLabelledBy: 'fd-dialog-header-fs-template',\n ariaDescribedBy: 'fd-dialog-body-fs-template',\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.templateBasedConfirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.templateBasedConfirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialog(): void {\n const object: DialogDefaultContent = {\n title: 'Dialog Title',\n titleId: 'fd-dialog-header-fs-object',\n content: this.dialogContent,\n contentId: 'fd-dialog-body-fs-object',\n subHeader: this.dialogSubHeader,\n approveButton: 'Ok',\n approveButtonAriaLabel: 'Ok Emphasized',\n approveButtonCallback: () => this._dialogReference.close('Approved'),\n cancelButton: 'Cancel',\n cancelButtonCallback: () => this._dialogReference.close('Canceled'),\n closeButtonCallback: () => this._dialogReference.dismiss('Dismissed'),\n fullScreenButtonCallback: () => this._dialogReference.toggleFullScreen(),\n closeButtonTitle: 'close',\n allowFullScreen: true,\n fullScreenExpandButtonText: 'Enter full-screen mode',\n fullScreenMinifyButtonText: 'Exit full-screen mode'\n };\n\n this._dialogReference = this._dialogService.open(object, {\n ariaLabelledBy: 'fd-dialog-header-fs-object',\n ariaDescribedBy: 'fd-dialog-body-fs-object',\n focusTrapped: true,\n resizable: true,\n draggable: true\n });\n\n this._dialogReference.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", - "html": "\n\n\n\n
    You can also create dialog without building whole template.
    \n
    \n\n\n
    \n \n \n \n
    \n
    \n\n

    {{ closeReason }}

    \n\n\n\n\n \n \n

    The History of Pineapple

    \n \n
    \n\n \n

    Are you interested in The Great History of Pineapple?

    \n
    \n\n \n \n\n \n \n
    \n
    \n\n\n

    {{ templateBasedConfirmationReason }}

    \n\n\n\n\n

    {{ componentCloseReason }}

    \n\n" - }, { "name": "dialog-mobile-example", "description": "Dialog Mobile", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { ContentDensityMode } from '@fundamental-ngx/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-mobile-example',\n templateUrl: './dialog-mobile-example.component.html',\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogMobileExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDialog(dialogTemplate): void {\n this._dialogService.open(dialogTemplate, {\n mobile: true,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-mobile',\n ariaDescribedBy: 'fd-dialog-body-mobile',\n contentDensity: ContentDensityMode.COZY\n });\n }\n}\n", "html": "\n \n \n

    Wild pineapples

    \n
    \n\n \n
    \n Certain bat-pollinated wild pineapples, members of the Bromeliad family, do the exact opposite of most\n flowers by opening their flowers at night and closing them during the day.\n
    \n
    \n\n \n \n \n \n
    \n
    \n\n\n" }, + { + "name": "dialog-full-screen-example", + "description": "Dialog Full Screen", + "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\nimport { AsyncPipe, NgStyle } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n TemplateRef,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogDefaultContent,\n DialogFooterComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-full-screen-inner-example',\n template: ` \n \n

    {{ dialogRef.data.title }}

    \n \n
    \n \n \n {{ dialogRef.data.pinnapleDescription }}\n

    \n
      \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
    • \n {{ fact }}\n
    • \n }\n
    \n
    \n \n \n \n \n \n \n
    `,\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n AsyncPipe,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogFullScreenInnerExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n\n@Component({\n selector: 'fd-dialog-full-screen-example',\n imports: [\n ButtonComponent,\n BarModule,\n InputGroupModule,\n InitialFocusDirective,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n TitleComponent,\n DialogHeaderComponent,\n DialogComponent\n ],\n templateUrl: './dialog-full-screen-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DialogFullScreenExampleComponent {\n @ViewChild('dialogContent', { read: TemplateRef })\n dialogContent: TemplateRef;\n\n @ViewChild('dialogSubHeader', { read: TemplateRef })\n dialogSubHeader: TemplateRef;\n\n closeReason = '';\n\n templateBasedConfirmationReason = '';\n\n componentCloseReason = '';\n\n private _dialogReference: DialogRef;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openFromComponent(): void {\n const dialogRef = this._dialogService.open(DialogFullScreenInnerExampleComponent, {\n data: {\n title: `Pineapple Fun Facts`,\n pinnapleDescription: `\n The pineapple (Ananas comosus) is a tropical plant with an edible fruit\n and the most economically significant plant in the family Bromeliaceae.\n The pineapple is indigenous to South America,\n where it has been cultivated for many centuries.\n The introduction of the pineapple to Europe in the 17th\n century made it a significant cultural icon of luxury.\n Since the 1820s, pineapple has been commercially grown in\n greenhouses and many tropical plantations.\n `,\n pineappleFunFacts: [\n `You can grow your own pineapple by planting the top of the pineapple in soil`,\n `Pulling leaves from a pineapple is not an indication of ripeness as many people think`,\n `James Dole is considered the “King of Pineapples“`,\n `A pineapple cannot continue to ripen after it has been picked`,\n `An unripe pineapple not only tastes awful, but can also be poisonous`,\n `One of the ways you can tell if a pineapple is ripe is by smelling it`,\n `In Hawaii, the word for pineapple is “Hala kahiki“`\n ]\n },\n width: '400px',\n ariaLabelledBy: 'fd-dialog-header-fs-component',\n ariaDescribedBy: 'fd-dialog-body-fs-component',\n responsivePadding: true,\n draggable: true,\n resizable: true,\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.componentCloseReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.componentCloseReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialogFromTemplate(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: true,\n draggable: true,\n resizable: true,\n ariaLabelledBy: 'fd-dialog-header-fs-template',\n ariaDescribedBy: 'fd-dialog-body-fs-template',\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.templateBasedConfirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.templateBasedConfirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialog(): void {\n const object: DialogDefaultContent = {\n title: 'Dialog Title',\n titleId: 'fd-dialog-header-fs-object',\n content: this.dialogContent,\n contentId: 'fd-dialog-body-fs-object',\n subHeader: this.dialogSubHeader,\n approveButton: 'Ok',\n approveButtonAriaLabel: 'Ok Emphasized',\n approveButtonCallback: () => this._dialogReference.close('Approved'),\n cancelButton: 'Cancel',\n cancelButtonCallback: () => this._dialogReference.close('Canceled'),\n closeButtonCallback: () => this._dialogReference.dismiss('Dismissed'),\n fullScreenButtonCallback: () => this._dialogReference.toggleFullScreen(),\n closeButtonTitle: 'close',\n allowFullScreen: true,\n fullScreenExpandButtonText: 'Enter full-screen mode',\n fullScreenMinifyButtonText: 'Exit full-screen mode'\n };\n\n this._dialogReference = this._dialogService.open(object, {\n ariaLabelledBy: 'fd-dialog-header-fs-object',\n ariaDescribedBy: 'fd-dialog-body-fs-object',\n focusTrapped: true,\n resizable: true,\n draggable: true\n });\n\n this._dialogReference.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", + "html": "\n\n\n\n
    You can also create dialog without building whole template.
    \n
    \n\n\n
    \n \n \n \n
    \n
    \n\n

    {{ closeReason }}

    \n\n\n\n\n \n \n

    The History of Pineapple

    \n \n
    \n\n \n

    Are you interested in The Great History of Pineapple?

    \n
    \n\n \n \n\n \n \n
    \n
    \n\n\n

    {{ templateBasedConfirmationReason }}

    \n\n\n\n\n

    {{ componentCloseReason }}

    \n\n" + }, { "name": "dialog-object-example", "description": "Dialog Object", @@ -34500,6 +34530,12 @@ "description": "Dialog", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\n\nimport { NgStyle } from '@angular/common';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogRef\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n template: `\n \n \n

    {{ dialogRef.data.title }}

    \n
    \n \n

    \n {{ dialogRef.data.pinnapleDescription }}\n

    \n
      \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
    • \n {{ fact }}\n
    • \n }\n
    \n
    \n \n \n \n \n \n \n
    \n `,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n" }, + { + "name": "dialog-configuration-example", + "description": "Dialog Configuration", + "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-configuration-example',\n templateUrl: './dialog-configuration-example.component.html',\n styleUrls: ['./dialog-configuration-example.component.scss'],\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogConfigurationExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDraggableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n draggable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openResizableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n resizable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openClosableByButtonDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n escKeyCloseable: false,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n}\n", + "html": "\n \n \n

    Origin of the Pineapple Word

    \n
    \n\n \n
    \n The word pineapple in English was first recorded in 1398, when it was originally used to describe the\n reproductive organs of conifer trees (now termed pine cones). When European explorers discovered this\n tropical fruit they called them pineapples (term first recorded in that sense in 1664) because of their\n resemblance to what is now known as the pine cone. The term pine cone was first recorded in 1694, and\n was used to replace the original meaning of pineapple.\n
    \n
    \n\n \n \n \n \n
    \n
    \n\n\n\n\n" + }, { "name": "dialog-backdrop-container-example", "description": "Dialog Backdrop Container", @@ -34512,30 +34548,24 @@ "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { AsyncPipe, NgClass } from '@angular/common';\nimport { Component, TemplateRef } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { InitialFocusDirective, TemplateDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ListModule, ListSecondaryDirective } from '@fundamental-ngx/core/list';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\ninterface Fruit {\n id: number;\n name: string;\n price: number;\n}\n\n@Component({\n selector: 'fd-dialog-complex-example',\n templateUrl: './dialog-complex-example.component.html',\n imports: [\n TemplateDirective,\n BarModule,\n TitleComponent,\n InputGroupModule,\n InitialFocusDirective,\n FormsModule,\n CdkScrollable,\n ScrollbarDirective,\n ListModule,\n NgClass,\n ListSecondaryDirective,\n ButtonComponent,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogComplexExampleComponent {\n fruitCollection: Fruit[] = [\n { id: 1, name: 'Pineapple', price: Infinity },\n { id: 2, name: 'Passion Fruit', price: 10.0 },\n { id: 3, name: 'Papaya', price: 8.99 },\n { id: 4, name: 'Kiwifruit', price: 3.0 },\n { id: 5, name: 'Mango', price: 15.0 },\n { id: 6, name: 'Pomegranate', price: 12.5 },\n { id: 7, name: 'Guava', price: 10.15 },\n { id: 8, name: 'Durian', price: 15.25 },\n { id: 9, name: 'Jackfruit', price: 10.0 },\n { id: 10, name: 'Dragon Fruit', price: 9.0 },\n { id: 11, name: 'Cherimoya', price: 7.45 },\n { id: 12, name: 'Kiwano', price: 4.5 },\n { id: 13, name: 'Korean Melon', price: 6.5 },\n { id: 14, name: 'Feijoa', price: 2.0 },\n { id: 15, name: 'Tamarillo ', price: 8.75 },\n { id: 16, name: 'Loquat', price: 0.99 }\n ];\n\n selectedFruits: Fruit[] = [];\n\n dialogRef: DialogRef;\n\n searchedPhrase = '';\n\n constructor(public _dialogService: DialogService) {}\n\n openDialog(template: TemplateRef): void {\n this.dialogRef = this._dialogService.open(template, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n ariaLabelledBy: 'fd-dialog-header-complex',\n ariaDescribedBy: 'fd-dialog-description-complex'\n });\n this.dialogRef.loading(true);\n setTimeout(() => this.dialogRef.loading(false), 2000);\n }\n\n get totalPrice(): number {\n const sum = this.selectedFruits.reduce((total, fruit) => total + fruit.price, 0);\n return Math.round(sum * 100) / 100;\n }\n\n filterFruits(fruits: Fruit[], searchedPhrase: string): Fruit[] {\n return this.fruitCollection.filter((fruit) => fruit.name.toLowerCase().includes(searchedPhrase.toLowerCase()));\n }\n\n isSelected(id: number): boolean {\n return this.selectedFruits.some((fruit) => fruit.id === id);\n }\n\n selectFruit(fruit: Fruit): void {\n const fruitIndex = this.selectedFruits.indexOf(fruit);\n\n if (fruitIndex !== -1) {\n this.selectedFruits.splice(fruitIndex, 1);\n } else {\n this.selectedFruits.push(fruit);\n }\n }\n\n clear(): void {\n this.searchedPhrase = '';\n this.selectedFruits = [];\n }\n\n checkout(): void {\n this.dialogRef.close();\n }\n}\n", "html": "\n \n \n \n
    \n \n

    Fresh Market

    \n Search for fresh produce items\n
    \n
    \n
    \n \n
    \n
    \n \n
    \n \n \n \n \n
    \n
    \n
    \n \n @if ((dialogRef.onLoading | async) === false) {\n
      \n @for (fruit of filterFruits(fruitCollection, searchedPhrase); track fruit) {\n
    • \n {{ fruit.name }}\n {{ fruit.price }} €\n
    • \n }\n
    \n }\n
    \n \n \n
    \n Total price: {{ totalPrice }}€ \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n" }, - { - "name": "dialog-configuration-example", - "description": "Dialog Configuration", - "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-configuration-example',\n templateUrl: './dialog-configuration-example.component.html',\n styleUrls: ['./dialog-configuration-example.component.scss'],\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogConfigurationExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDraggableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n draggable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openResizableDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n resizable: true,\n responsivePadding: true,\n backdropClickCloseable: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n\n openClosableByButtonDialog(template): void {\n this._dialogService.open(template, {\n width: '300px',\n escKeyCloseable: false,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-config',\n ariaDescribedBy: 'fd-dialog-body-config'\n });\n }\n}\n", - "html": "\n \n \n

    Origin of the Pineapple Word

    \n
    \n\n \n
    \n The word pineapple in English was first recorded in 1398, when it was originally used to describe the\n reproductive organs of conifer trees (now termed pine cones). When European explorers discovered this\n tropical fruit they called them pineapples (term first recorded in that sense in 1664) because of their\n resemblance to what is now known as the pine cone. The term pine cone was first recorded in 1694, and\n was used to replace the original meaning of pineapple.\n
    \n
    \n\n \n \n \n \n
    \n
    \n\n\n\n\n" - }, { "name": "form-dialog-example", "description": "Form Dialog", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { ChangeDetectionStrategy, ChangeDetectorRef, Component, TemplateRef } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-form-dialog-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './form-dialog-example.component.html',\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n CheckboxComponent,\n FormsModule,\n ButtonComponent,\n DialogHeaderComponent,\n DialogBodyComponent,\n DialogFooterComponent,\n DialogComponent\n ]\n})\nexport class FormDialogExampleComponent {\n confirmationReason: string;\n responsivePadding = false;\n verticalPadding = false;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openDialog(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: this.responsivePadding,\n focusTrapped: true,\n verticalPadding: this.verticalPadding,\n ariaLabelledBy: 'fd-dialog-header-form'\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.confirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.confirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", "html": "\n \n \n

    The History of Pineapple

    \n
    \n\n \n \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n \n
    \n\n \n \n\n \n \n
    \n
    \n\n\n\n\n\n

    {{ confirmationReason }}

    \n" }, - { - "name": "dialog-full-screen-example", - "description": "Dialog Full Screen", - "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\nimport { AsyncPipe, NgStyle } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n TemplateRef,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogDefaultContent,\n DialogFooterComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-full-screen-inner-example',\n template: ` \n \n

    {{ dialogRef.data.title }}

    \n \n
    \n \n \n {{ dialogRef.data.pinnapleDescription }}\n

    \n
      \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
    • \n {{ fact }}\n
    • \n }\n
    \n
    \n \n \n \n \n \n \n
    `,\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n AsyncPipe,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogFullScreenInnerExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n\n@Component({\n selector: 'fd-dialog-full-screen-example',\n imports: [\n ButtonComponent,\n BarModule,\n InputGroupModule,\n InitialFocusDirective,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n TitleComponent,\n DialogHeaderComponent,\n DialogComponent\n ],\n templateUrl: './dialog-full-screen-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DialogFullScreenExampleComponent {\n @ViewChild('dialogContent', { read: TemplateRef })\n dialogContent: TemplateRef;\n\n @ViewChild('dialogSubHeader', { read: TemplateRef })\n dialogSubHeader: TemplateRef;\n\n closeReason = '';\n\n templateBasedConfirmationReason = '';\n\n componentCloseReason = '';\n\n private _dialogReference: DialogRef;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openFromComponent(): void {\n const dialogRef = this._dialogService.open(DialogFullScreenInnerExampleComponent, {\n data: {\n title: `Pineapple Fun Facts`,\n pinnapleDescription: `\n The pineapple (Ananas comosus) is a tropical plant with an edible fruit\n and the most economically significant plant in the family Bromeliaceae.\n The pineapple is indigenous to South America,\n where it has been cultivated for many centuries.\n The introduction of the pineapple to Europe in the 17th\n century made it a significant cultural icon of luxury.\n Since the 1820s, pineapple has been commercially grown in\n greenhouses and many tropical plantations.\n `,\n pineappleFunFacts: [\n `You can grow your own pineapple by planting the top of the pineapple in soil`,\n `Pulling leaves from a pineapple is not an indication of ripeness as many people think`,\n `James Dole is considered the “King of Pineapples“`,\n `A pineapple cannot continue to ripen after it has been picked`,\n `An unripe pineapple not only tastes awful, but can also be poisonous`,\n `One of the ways you can tell if a pineapple is ripe is by smelling it`,\n `In Hawaii, the word for pineapple is “Hala kahiki“`\n ]\n },\n width: '400px',\n ariaLabelledBy: 'fd-dialog-header-fs-component',\n ariaDescribedBy: 'fd-dialog-body-fs-component',\n responsivePadding: true,\n draggable: true,\n resizable: true,\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.componentCloseReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.componentCloseReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialogFromTemplate(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: true,\n draggable: true,\n resizable: true,\n ariaLabelledBy: 'fd-dialog-header-fs-template',\n ariaDescribedBy: 'fd-dialog-body-fs-template',\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.templateBasedConfirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.templateBasedConfirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialog(): void {\n const object: DialogDefaultContent = {\n title: 'Dialog Title',\n titleId: 'fd-dialog-header-fs-object',\n content: this.dialogContent,\n contentId: 'fd-dialog-body-fs-object',\n subHeader: this.dialogSubHeader,\n approveButton: 'Ok',\n approveButtonAriaLabel: 'Ok Emphasized',\n approveButtonCallback: () => this._dialogReference.close('Approved'),\n cancelButton: 'Cancel',\n cancelButtonCallback: () => this._dialogReference.close('Canceled'),\n closeButtonCallback: () => this._dialogReference.dismiss('Dismissed'),\n fullScreenButtonCallback: () => this._dialogReference.toggleFullScreen(),\n closeButtonTitle: 'close',\n allowFullScreen: true,\n fullScreenExpandButtonText: 'Enter full-screen mode',\n fullScreenMinifyButtonText: 'Exit full-screen mode'\n };\n\n this._dialogReference = this._dialogService.open(object, {\n ariaLabelledBy: 'fd-dialog-header-fs-object',\n ariaDescribedBy: 'fd-dialog-body-fs-object',\n focusTrapped: true,\n resizable: true,\n draggable: true\n });\n\n this._dialogReference.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", - "html": "\n\n\n\n
    You can also create dialog without building whole template.
    \n
    \n\n\n
    \n \n \n \n
    \n
    \n\n

    {{ closeReason }}

    \n\n\n\n\n \n \n

    The History of Pineapple

    \n \n
    \n\n \n

    Are you interested in The Great History of Pineapple?

    \n
    \n\n \n \n\n \n \n
    \n
    \n\n\n

    {{ templateBasedConfirmationReason }}

    \n\n\n\n\n

    {{ componentCloseReason }}

    \n\n" - }, { "name": "dialog-mobile-example", "description": "Dialog Mobile", "typescript": "import { CdkScrollable } from '@angular/cdk/overlay';\nimport { Component } from '@angular/core';\nimport { ContentDensityMode } from '@fundamental-ngx/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-mobile-example',\n templateUrl: './dialog-mobile-example.component.html',\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n ButtonComponent,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogMobileExampleComponent {\n constructor(public _dialogService: DialogService) {}\n\n openDialog(dialogTemplate): void {\n this._dialogService.open(dialogTemplate, {\n mobile: true,\n responsivePadding: true,\n ariaLabelledBy: 'fd-dialog-header-mobile',\n ariaDescribedBy: 'fd-dialog-body-mobile',\n contentDensity: ContentDensityMode.COZY\n });\n }\n}\n", "html": "\n \n \n

    Wild pineapples

    \n
    \n\n \n
    \n Certain bat-pollinated wild pineapples, members of the Bromeliad family, do the exact opposite of most\n flowers by opening their flowers at night and closing them during the day.\n
    \n
    \n\n \n \n \n \n
    \n
    \n\n\n" }, + { + "name": "dialog-full-screen-example", + "description": "Dialog Full Screen", + "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\nimport { AsyncPipe, NgStyle } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n TemplateRef,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogDefaultContent,\n DialogFooterComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogRef,\n DialogService\n} from '@fundamental-ngx/core/dialog';\nimport { InputGroupModule } from '@fundamental-ngx/core/input-group';\nimport { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-dialog-full-screen-inner-example',\n template: ` \n \n

    {{ dialogRef.data.title }}

    \n \n
    \n \n \n {{ dialogRef.data.pinnapleDescription }}\n

    \n
      \n @for (fact of dialogRef.data.pineappleFunFacts; track fact) {\n
    • \n {{ fact }}\n
    • \n }\n
    \n
    \n \n \n \n \n \n \n
    `,\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TitleComponent,\n CdkScrollable,\n ScrollbarDirective,\n BarModule,\n AsyncPipe,\n NgStyle,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n DialogHeaderComponent,\n DialogComponent\n ]\n})\nexport class DialogFullScreenInnerExampleComponent {\n constructor(public dialogRef: DialogRef) {}\n}\n\n@Component({\n selector: 'fd-dialog-full-screen-example',\n imports: [\n ButtonComponent,\n BarModule,\n InputGroupModule,\n InitialFocusDirective,\n AsyncPipe,\n DialogFooterComponent,\n DialogBodyComponent,\n DialogFullScreenTogglerButtonComponent,\n TitleComponent,\n DialogHeaderComponent,\n DialogComponent\n ],\n templateUrl: './dialog-full-screen-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DialogFullScreenExampleComponent {\n @ViewChild('dialogContent', { read: TemplateRef })\n dialogContent: TemplateRef;\n\n @ViewChild('dialogSubHeader', { read: TemplateRef })\n dialogSubHeader: TemplateRef;\n\n closeReason = '';\n\n templateBasedConfirmationReason = '';\n\n componentCloseReason = '';\n\n private _dialogReference: DialogRef;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openFromComponent(): void {\n const dialogRef = this._dialogService.open(DialogFullScreenInnerExampleComponent, {\n data: {\n title: `Pineapple Fun Facts`,\n pinnapleDescription: `\n The pineapple (Ananas comosus) is a tropical plant with an edible fruit\n and the most economically significant plant in the family Bromeliaceae.\n The pineapple is indigenous to South America,\n where it has been cultivated for many centuries.\n The introduction of the pineapple to Europe in the 17th\n century made it a significant cultural icon of luxury.\n Since the 1820s, pineapple has been commercially grown in\n greenhouses and many tropical plantations.\n `,\n pineappleFunFacts: [\n `You can grow your own pineapple by planting the top of the pineapple in soil`,\n `Pulling leaves from a pineapple is not an indication of ripeness as many people think`,\n `James Dole is considered the “King of Pineapples“`,\n `A pineapple cannot continue to ripen after it has been picked`,\n `An unripe pineapple not only tastes awful, but can also be poisonous`,\n `One of the ways you can tell if a pineapple is ripe is by smelling it`,\n `In Hawaii, the word for pineapple is “Hala kahiki“`\n ]\n },\n width: '400px',\n ariaLabelledBy: 'fd-dialog-header-fs-component',\n ariaDescribedBy: 'fd-dialog-body-fs-component',\n responsivePadding: true,\n draggable: true,\n resizable: true,\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.componentCloseReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.componentCloseReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialogFromTemplate(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n responsivePadding: true,\n draggable: true,\n resizable: true,\n ariaLabelledBy: 'fd-dialog-header-fs-template',\n ariaDescribedBy: 'fd-dialog-body-fs-template',\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result) => {\n this.templateBasedConfirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.templateBasedConfirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n openDialog(): void {\n const object: DialogDefaultContent = {\n title: 'Dialog Title',\n titleId: 'fd-dialog-header-fs-object',\n content: this.dialogContent,\n contentId: 'fd-dialog-body-fs-object',\n subHeader: this.dialogSubHeader,\n approveButton: 'Ok',\n approveButtonAriaLabel: 'Ok Emphasized',\n approveButtonCallback: () => this._dialogReference.close('Approved'),\n cancelButton: 'Cancel',\n cancelButtonCallback: () => this._dialogReference.close('Canceled'),\n closeButtonCallback: () => this._dialogReference.dismiss('Dismissed'),\n fullScreenButtonCallback: () => this._dialogReference.toggleFullScreen(),\n closeButtonTitle: 'close',\n allowFullScreen: true,\n fullScreenExpandButtonText: 'Enter full-screen mode',\n fullScreenMinifyButtonText: 'Exit full-screen mode'\n };\n\n this._dialogReference = this._dialogService.open(object, {\n ariaLabelledBy: 'fd-dialog-header-fs-object',\n ariaDescribedBy: 'fd-dialog-body-fs-object',\n focusTrapped: true,\n resizable: true,\n draggable: true\n });\n\n this._dialogReference.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", + "html": "\n\n\n\n
    You can also create dialog without building whole template.
    \n
    \n\n\n
    \n \n \n \n
    \n
    \n\n

    {{ closeReason }}

    \n\n\n\n\n \n \n

    The History of Pineapple

    \n \n
    \n\n \n

    Are you interested in The Great History of Pineapple?

    \n
    \n\n \n \n\n \n \n
    \n
    \n\n\n

    {{ templateBasedConfirmationReason }}

    \n\n\n\n\n

    {{ componentCloseReason }}

    \n\n" + }, { "name": "dialog-object-example", "description": "Dialog Object", @@ -34692,6 +34722,12 @@ "typescript": "import { Component } from '@angular/core';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\n\nimport { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { FlexibleColumnLayout, FlexibleColumnLayoutModule } from '@fundamental-ngx/core/flexible-column-layout';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\n@Component({\n selector: 'fd-dynamic-page-column-layout-example',\n templateUrl: './dynamic-page-column-layout-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n FlexibleColumnLayoutModule,\n DynamicPageModule,\n BreadcrumbModule,\n LinkComponent,\n ContentDensityDirective,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n FDP_ICON_TAB_BAR,\n MessageToastModule\n ]\n})\nexport class DynamicPageColumnLayoutExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n /**\n * documentation related property\n * sets the initial layout of the component to 'OneColumnStartFullScreen'\n * sets a new layout for the component\n */\n localLayout: FlexibleColumnLayout = 'OneColumnStartFullScreen';\n\n separatorAriaLabel = 'separator';\n\n expandTitle = 'Expand';\n\n collapseTitle = 'Collapse';\n\n constructor(private _messageToastService: MessageToastService) {}\n\n /**\n * this function is reacting to events (button clicks) and\n * updates the local property which sets a new layout for the component.\n * Available values for the layouts include:\n * 'OneColumnStartFullScreen' | 'OneColumnMidFullScreen' | 'OneColumnEndFullScreen' |\n * 'TwoColumnsStartExpanded' | 'TwoColumnsMidExpanded' | 'TwoColumnsEndExpanded' |\n * 'ThreeColumnsMidExpanded' | 'ThreeColumnsEndExpanded' | 'ThreeColumnsStartMinimized' |\n * 'ThreeColumnsEndMinimized';\n */\n changeLayout(newValue: FlexibleColumnLayout): void {\n this.localLayout = newValue;\n }\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum\n consequuntur impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n \n

    Mid Column

    \n
    \n \n Open Column 3\n \n
    \n \n @for (tab of [1, 2, 3, 4]; track tab) {\n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor\n incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud\n exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure\n dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt\n mollit anim id est laborum.\n
    \n
    \n }\n
    \n
    \n \n

    End Column

    \n
    \n @if (localLayout !== 'OneColumnEndFullScreen') {\n \n \n } @else {\n \n }\n
    \n
    \n \n \n}\n" }, + { + "name": "dynamic-page-responsive-example", + "description": "Dynamic Page Responsive", + "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-responsive-example',\n templateUrl: './dynamic-page-responsive-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n BreadcrumbModule,\n ContentDensityDirective,\n LinkComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n MessageToastModule\n ]\n})\nexport class DynamicPageResponsiveExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n compact = true;\n\n constructor(private _messageToastService: MessageToastService) {}\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", + "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum consequuntur\n impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n}\n" + }, { "name": "dynamic-page-dynamic-container-height-example", "description": "Dynamic Page Dynamic Container Height", @@ -34704,12 +34740,6 @@ "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n DynamicPageHeaderSubtitleDirective,\n DynamicPageHeaderTitleDirective,\n DynamicPageModule\n} from '@fundamental-ngx/core/dynamic-page';\nimport { FacetModule } from '@fundamental-ngx/core/facets';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ObjectNumberComponent } from '@fundamental-ngx/core/object-number';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { RatingIndicatorComponent } from '@fundamental-ngx/core/rating-indicator';\nimport { TextComponent } from '@fundamental-ngx/core/text';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-facets-example',\n templateUrl: './dynamic-page-facets-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n .red-subtitle {\n color: red;\n }\n .blue-subtitle {\n color: blue;\n }\n .green-subtitle {\n color: green;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n DynamicPageHeaderTitleDirective,\n DynamicPageHeaderSubtitleDirective,\n BreadcrumbModule,\n LinkComponent,\n FacetModule,\n AvatarComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ContentDensityDirective,\n ToolbarSeparatorComponent,\n FormLabelComponent,\n TextComponent,\n RatingIndicatorComponent,\n ObjectStatusComponent,\n ObjectNumberComponent,\n CdkScrollable,\n BarModule\n ]\n})\nexport class DynamicPageFacetsExampleComponent {\n visible = false;\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n }\n\n closePage(): void {\n this.visible = false;\n }\n}\n", "html": "\n@if (visible) {\n
    \n \n \n \n Lorem ipsum dolor sit amet, consectetur adipiscing elit ({{\n collapsed ? 'collapsed' : 'not collapsed'\n }})\n \n \n Different parts | of the |\n subtitle | with\n {{ collapsed ? 'collapsed' : 'not collapsed' }} header\n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n}\n" }, - { - "name": "dynamic-page-responsive-example", - "description": "Dynamic Page Responsive", - "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-responsive-example',\n templateUrl: './dynamic-page-responsive-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n BreadcrumbModule,\n ContentDensityDirective,\n LinkComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n MessageToastModule\n ]\n})\nexport class DynamicPageResponsiveExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n compact = true;\n\n constructor(private _messageToastService: MessageToastService) {}\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", - "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum consequuntur\n impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n}\n" - }, { "name": "dynamic-page-routing-example", "description": "Dynamic Page Routing", @@ -34756,6 +34786,12 @@ "typescript": "import { Component } from '@angular/core';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\n\nimport { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { FlexibleColumnLayout, FlexibleColumnLayoutModule } from '@fundamental-ngx/core/flexible-column-layout';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\n@Component({\n selector: 'fd-dynamic-page-column-layout-example',\n templateUrl: './dynamic-page-column-layout-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n FlexibleColumnLayoutModule,\n DynamicPageModule,\n BreadcrumbModule,\n LinkComponent,\n ContentDensityDirective,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n FDP_ICON_TAB_BAR,\n MessageToastModule\n ]\n})\nexport class DynamicPageColumnLayoutExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n /**\n * documentation related property\n * sets the initial layout of the component to 'OneColumnStartFullScreen'\n * sets a new layout for the component\n */\n localLayout: FlexibleColumnLayout = 'OneColumnStartFullScreen';\n\n separatorAriaLabel = 'separator';\n\n expandTitle = 'Expand';\n\n collapseTitle = 'Collapse';\n\n constructor(private _messageToastService: MessageToastService) {}\n\n /**\n * this function is reacting to events (button clicks) and\n * updates the local property which sets a new layout for the component.\n * Available values for the layouts include:\n * 'OneColumnStartFullScreen' | 'OneColumnMidFullScreen' | 'OneColumnEndFullScreen' |\n * 'TwoColumnsStartExpanded' | 'TwoColumnsMidExpanded' | 'TwoColumnsEndExpanded' |\n * 'ThreeColumnsMidExpanded' | 'ThreeColumnsEndExpanded' | 'ThreeColumnsStartMinimized' |\n * 'ThreeColumnsEndMinimized';\n */\n changeLayout(newValue: FlexibleColumnLayout): void {\n this.localLayout = newValue;\n }\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum\n consequuntur impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n \n

    Mid Column

    \n
    \n \n Open Column 3\n \n
    \n \n @for (tab of [1, 2, 3, 4]; track tab) {\n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor\n incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud\n exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure\n dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt\n mollit anim id est laborum.\n
    \n
    \n }\n
    \n
    \n \n

    End Column

    \n
    \n @if (localLayout !== 'OneColumnEndFullScreen') {\n \n \n } @else {\n \n }\n
    \n
    \n \n \n}\n" }, + { + "name": "dynamic-page-responsive-example", + "description": "Dynamic Page Responsive", + "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-responsive-example',\n templateUrl: './dynamic-page-responsive-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n BreadcrumbModule,\n ContentDensityDirective,\n LinkComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n MessageToastModule\n ]\n})\nexport class DynamicPageResponsiveExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n compact = true;\n\n constructor(private _messageToastService: MessageToastService) {}\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", + "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum consequuntur\n impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n}\n" + }, { "name": "dynamic-page-dynamic-container-height-example", "description": "Dynamic Page Dynamic Container Height", @@ -34768,12 +34804,6 @@ "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n DynamicPageHeaderSubtitleDirective,\n DynamicPageHeaderTitleDirective,\n DynamicPageModule\n} from '@fundamental-ngx/core/dynamic-page';\nimport { FacetModule } from '@fundamental-ngx/core/facets';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ObjectNumberComponent } from '@fundamental-ngx/core/object-number';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { RatingIndicatorComponent } from '@fundamental-ngx/core/rating-indicator';\nimport { TextComponent } from '@fundamental-ngx/core/text';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-facets-example',\n templateUrl: './dynamic-page-facets-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n .red-subtitle {\n color: red;\n }\n .blue-subtitle {\n color: blue;\n }\n .green-subtitle {\n color: green;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n DynamicPageHeaderTitleDirective,\n DynamicPageHeaderSubtitleDirective,\n BreadcrumbModule,\n LinkComponent,\n FacetModule,\n AvatarComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ContentDensityDirective,\n ToolbarSeparatorComponent,\n FormLabelComponent,\n TextComponent,\n RatingIndicatorComponent,\n ObjectStatusComponent,\n ObjectNumberComponent,\n CdkScrollable,\n BarModule\n ]\n})\nexport class DynamicPageFacetsExampleComponent {\n visible = false;\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n }\n\n closePage(): void {\n this.visible = false;\n }\n}\n", "html": "\n@if (visible) {\n
    \n \n \n \n Lorem ipsum dolor sit amet, consectetur adipiscing elit ({{\n collapsed ? 'collapsed' : 'not collapsed'\n }})\n \n \n Different parts | of the |\n subtitle | with\n {{ collapsed ? 'collapsed' : 'not collapsed' }} header\n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n}\n" }, - { - "name": "dynamic-page-responsive-example", - "description": "Dynamic Page Responsive", - "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-responsive-example',\n templateUrl: './dynamic-page-responsive-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n BreadcrumbModule,\n ContentDensityDirective,\n LinkComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n MessageToastModule\n ]\n})\nexport class DynamicPageResponsiveExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n compact = true;\n\n constructor(private _messageToastService: MessageToastService) {}\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", - "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum consequuntur\n impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n}\n" - }, { "name": "dynamic-page-routing-example", "description": "Dynamic Page Routing", @@ -34833,6 +34863,12 @@ "typescript": "import { Component } from '@angular/core';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\n\nimport { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { FlexibleColumnLayout, FlexibleColumnLayoutModule } from '@fundamental-ngx/core/flexible-column-layout';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\n@Component({\n selector: 'fd-dynamic-page-column-layout-example',\n templateUrl: './dynamic-page-column-layout-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n FlexibleColumnLayoutModule,\n DynamicPageModule,\n BreadcrumbModule,\n LinkComponent,\n ContentDensityDirective,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n FDP_ICON_TAB_BAR,\n MessageToastModule\n ]\n})\nexport class DynamicPageColumnLayoutExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n /**\n * documentation related property\n * sets the initial layout of the component to 'OneColumnStartFullScreen'\n * sets a new layout for the component\n */\n localLayout: FlexibleColumnLayout = 'OneColumnStartFullScreen';\n\n separatorAriaLabel = 'separator';\n\n expandTitle = 'Expand';\n\n collapseTitle = 'Collapse';\n\n constructor(private _messageToastService: MessageToastService) {}\n\n /**\n * this function is reacting to events (button clicks) and\n * updates the local property which sets a new layout for the component.\n * Available values for the layouts include:\n * 'OneColumnStartFullScreen' | 'OneColumnMidFullScreen' | 'OneColumnEndFullScreen' |\n * 'TwoColumnsStartExpanded' | 'TwoColumnsMidExpanded' | 'TwoColumnsEndExpanded' |\n * 'ThreeColumnsMidExpanded' | 'ThreeColumnsEndExpanded' | 'ThreeColumnsStartMinimized' |\n * 'ThreeColumnsEndMinimized';\n */\n changeLayout(newValue: FlexibleColumnLayout): void {\n this.localLayout = newValue;\n }\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum\n consequuntur impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n \n

    Mid Column

    \n
    \n \n Open Column 3\n \n
    \n \n @for (tab of [1, 2, 3, 4]; track tab) {\n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor\n incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud\n exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure\n dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt\n mollit anim id est laborum.\n
    \n
    \n }\n
    \n
    \n \n

    End Column

    \n
    \n @if (localLayout !== 'OneColumnEndFullScreen') {\n \n \n } @else {\n \n }\n
    \n
    \n \n \n}\n" }, + { + "name": "dynamic-page-responsive-example", + "description": "Dynamic Page Responsive", + "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-responsive-example',\n templateUrl: './dynamic-page-responsive-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n BreadcrumbModule,\n ContentDensityDirective,\n LinkComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n MessageToastModule\n ]\n})\nexport class DynamicPageResponsiveExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n compact = true;\n\n constructor(private _messageToastService: MessageToastService) {}\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", + "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum consequuntur\n impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n}\n" + }, { "name": "dynamic-page-dynamic-container-height-example", "description": "Dynamic Page Dynamic Container Height", @@ -34845,12 +34881,6 @@ "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n DynamicPageHeaderSubtitleDirective,\n DynamicPageHeaderTitleDirective,\n DynamicPageModule\n} from '@fundamental-ngx/core/dynamic-page';\nimport { FacetModule } from '@fundamental-ngx/core/facets';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ObjectNumberComponent } from '@fundamental-ngx/core/object-number';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { RatingIndicatorComponent } from '@fundamental-ngx/core/rating-indicator';\nimport { TextComponent } from '@fundamental-ngx/core/text';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-facets-example',\n templateUrl: './dynamic-page-facets-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n .red-subtitle {\n color: red;\n }\n .blue-subtitle {\n color: blue;\n }\n .green-subtitle {\n color: green;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n DynamicPageHeaderTitleDirective,\n DynamicPageHeaderSubtitleDirective,\n BreadcrumbModule,\n LinkComponent,\n FacetModule,\n AvatarComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ContentDensityDirective,\n ToolbarSeparatorComponent,\n FormLabelComponent,\n TextComponent,\n RatingIndicatorComponent,\n ObjectStatusComponent,\n ObjectNumberComponent,\n CdkScrollable,\n BarModule\n ]\n})\nexport class DynamicPageFacetsExampleComponent {\n visible = false;\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n }\n\n closePage(): void {\n this.visible = false;\n }\n}\n", "html": "\n@if (visible) {\n
    \n \n \n \n Lorem ipsum dolor sit amet, consectetur adipiscing elit ({{\n collapsed ? 'collapsed' : 'not collapsed'\n }})\n \n \n Different parts | of the |\n subtitle | with\n {{ collapsed ? 'collapsed' : 'not collapsed' }} header\n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n}\n" }, - { - "name": "dynamic-page-responsive-example", - "description": "Dynamic Page Responsive", - "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-responsive-example',\n templateUrl: './dynamic-page-responsive-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n BreadcrumbModule,\n ContentDensityDirective,\n LinkComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n MessageToastModule\n ]\n})\nexport class DynamicPageResponsiveExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n compact = true;\n\n constructor(private _messageToastService: MessageToastService) {}\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", - "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum consequuntur\n impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n}\n" - }, { "name": "dynamic-page-routing-example", "description": "Dynamic Page Routing", @@ -34897,6 +34927,12 @@ "typescript": "import { Component } from '@angular/core';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\n\nimport { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { FlexibleColumnLayout, FlexibleColumnLayoutModule } from '@fundamental-ngx/core/flexible-column-layout';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\n@Component({\n selector: 'fd-dynamic-page-column-layout-example',\n templateUrl: './dynamic-page-column-layout-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n FlexibleColumnLayoutModule,\n DynamicPageModule,\n BreadcrumbModule,\n LinkComponent,\n ContentDensityDirective,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n FDP_ICON_TAB_BAR,\n MessageToastModule\n ]\n})\nexport class DynamicPageColumnLayoutExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n /**\n * documentation related property\n * sets the initial layout of the component to 'OneColumnStartFullScreen'\n * sets a new layout for the component\n */\n localLayout: FlexibleColumnLayout = 'OneColumnStartFullScreen';\n\n separatorAriaLabel = 'separator';\n\n expandTitle = 'Expand';\n\n collapseTitle = 'Collapse';\n\n constructor(private _messageToastService: MessageToastService) {}\n\n /**\n * this function is reacting to events (button clicks) and\n * updates the local property which sets a new layout for the component.\n * Available values for the layouts include:\n * 'OneColumnStartFullScreen' | 'OneColumnMidFullScreen' | 'OneColumnEndFullScreen' |\n * 'TwoColumnsStartExpanded' | 'TwoColumnsMidExpanded' | 'TwoColumnsEndExpanded' |\n * 'ThreeColumnsMidExpanded' | 'ThreeColumnsEndExpanded' | 'ThreeColumnsStartMinimized' |\n * 'ThreeColumnsEndMinimized';\n */\n changeLayout(newValue: FlexibleColumnLayout): void {\n this.localLayout = newValue;\n }\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum\n consequuntur impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n \n

    Mid Column

    \n
    \n \n Open Column 3\n \n
    \n \n @for (tab of [1, 2, 3, 4]; track tab) {\n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor\n incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud\n exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure\n dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt\n mollit anim id est laborum.\n
    \n
    \n }\n
    \n
    \n \n

    End Column

    \n
    \n @if (localLayout !== 'OneColumnEndFullScreen') {\n \n \n } @else {\n \n }\n
    \n
    \n \n \n}\n" }, + { + "name": "dynamic-page-responsive-example", + "description": "Dynamic Page Responsive", + "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-responsive-example',\n templateUrl: './dynamic-page-responsive-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n BreadcrumbModule,\n ContentDensityDirective,\n LinkComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n MessageToastModule\n ]\n})\nexport class DynamicPageResponsiveExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n compact = true;\n\n constructor(private _messageToastService: MessageToastService) {}\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", + "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum consequuntur\n impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n}\n" + }, { "name": "dynamic-page-dynamic-container-height-example", "description": "Dynamic Page Dynamic Container Height", @@ -34909,12 +34945,6 @@ "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n DynamicPageHeaderSubtitleDirective,\n DynamicPageHeaderTitleDirective,\n DynamicPageModule\n} from '@fundamental-ngx/core/dynamic-page';\nimport { FacetModule } from '@fundamental-ngx/core/facets';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ObjectNumberComponent } from '@fundamental-ngx/core/object-number';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { RatingIndicatorComponent } from '@fundamental-ngx/core/rating-indicator';\nimport { TextComponent } from '@fundamental-ngx/core/text';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-facets-example',\n templateUrl: './dynamic-page-facets-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n .red-subtitle {\n color: red;\n }\n .blue-subtitle {\n color: blue;\n }\n .green-subtitle {\n color: green;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n DynamicPageHeaderTitleDirective,\n DynamicPageHeaderSubtitleDirective,\n BreadcrumbModule,\n LinkComponent,\n FacetModule,\n AvatarComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ContentDensityDirective,\n ToolbarSeparatorComponent,\n FormLabelComponent,\n TextComponent,\n RatingIndicatorComponent,\n ObjectStatusComponent,\n ObjectNumberComponent,\n CdkScrollable,\n BarModule\n ]\n})\nexport class DynamicPageFacetsExampleComponent {\n visible = false;\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n }\n\n closePage(): void {\n this.visible = false;\n }\n}\n", "html": "\n@if (visible) {\n
    \n \n \n \n Lorem ipsum dolor sit amet, consectetur adipiscing elit ({{\n collapsed ? 'collapsed' : 'not collapsed'\n }})\n \n \n Different parts | of the |\n subtitle | with\n {{ collapsed ? 'collapsed' : 'not collapsed' }} header\n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n}\n" }, - { - "name": "dynamic-page-responsive-example", - "description": "Dynamic Page Responsive", - "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-responsive-example',\n templateUrl: './dynamic-page-responsive-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n BreadcrumbModule,\n ContentDensityDirective,\n LinkComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n MessageToastModule\n ]\n})\nexport class DynamicPageResponsiveExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n compact = true;\n\n constructor(private _messageToastService: MessageToastService) {}\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", - "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum consequuntur\n impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n}\n" - }, { "name": "dynamic-page-routing-example", "description": "Dynamic Page Routing", @@ -34975,6 +35005,12 @@ "typescript": "import { Component } from '@angular/core';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\n\nimport { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { FlexibleColumnLayout, FlexibleColumnLayoutModule } from '@fundamental-ngx/core/flexible-column-layout';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\n@Component({\n selector: 'fd-dynamic-page-column-layout-example',\n templateUrl: './dynamic-page-column-layout-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n FlexibleColumnLayoutModule,\n DynamicPageModule,\n BreadcrumbModule,\n LinkComponent,\n ContentDensityDirective,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n FDP_ICON_TAB_BAR,\n MessageToastModule\n ]\n})\nexport class DynamicPageColumnLayoutExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n /**\n * documentation related property\n * sets the initial layout of the component to 'OneColumnStartFullScreen'\n * sets a new layout for the component\n */\n localLayout: FlexibleColumnLayout = 'OneColumnStartFullScreen';\n\n separatorAriaLabel = 'separator';\n\n expandTitle = 'Expand';\n\n collapseTitle = 'Collapse';\n\n constructor(private _messageToastService: MessageToastService) {}\n\n /**\n * this function is reacting to events (button clicks) and\n * updates the local property which sets a new layout for the component.\n * Available values for the layouts include:\n * 'OneColumnStartFullScreen' | 'OneColumnMidFullScreen' | 'OneColumnEndFullScreen' |\n * 'TwoColumnsStartExpanded' | 'TwoColumnsMidExpanded' | 'TwoColumnsEndExpanded' |\n * 'ThreeColumnsMidExpanded' | 'ThreeColumnsEndExpanded' | 'ThreeColumnsStartMinimized' |\n * 'ThreeColumnsEndMinimized';\n */\n changeLayout(newValue: FlexibleColumnLayout): void {\n this.localLayout = newValue;\n }\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum\n consequuntur impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n \n

    Mid Column

    \n
    \n \n Open Column 3\n \n
    \n \n @for (tab of [1, 2, 3, 4]; track tab) {\n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor\n incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud\n exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure\n dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt\n mollit anim id est laborum.\n
    \n
    \n }\n
    \n
    \n \n

    End Column

    \n
    \n @if (localLayout !== 'OneColumnEndFullScreen') {\n \n \n } @else {\n \n }\n
    \n
    \n \n \n}\n" }, + { + "name": "dynamic-page-responsive-example", + "description": "Dynamic Page Responsive", + "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-responsive-example',\n templateUrl: './dynamic-page-responsive-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n BreadcrumbModule,\n ContentDensityDirective,\n LinkComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n MessageToastModule\n ]\n})\nexport class DynamicPageResponsiveExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n compact = true;\n\n constructor(private _messageToastService: MessageToastService) {}\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", + "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum consequuntur\n impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n}\n" + }, { "name": "dynamic-page-dynamic-container-height-example", "description": "Dynamic Page Dynamic Container Height", @@ -34987,12 +35023,6 @@ "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n DynamicPageHeaderSubtitleDirective,\n DynamicPageHeaderTitleDirective,\n DynamicPageModule\n} from '@fundamental-ngx/core/dynamic-page';\nimport { FacetModule } from '@fundamental-ngx/core/facets';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ObjectNumberComponent } from '@fundamental-ngx/core/object-number';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { RatingIndicatorComponent } from '@fundamental-ngx/core/rating-indicator';\nimport { TextComponent } from '@fundamental-ngx/core/text';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-facets-example',\n templateUrl: './dynamic-page-facets-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n .red-subtitle {\n color: red;\n }\n .blue-subtitle {\n color: blue;\n }\n .green-subtitle {\n color: green;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n DynamicPageHeaderTitleDirective,\n DynamicPageHeaderSubtitleDirective,\n BreadcrumbModule,\n LinkComponent,\n FacetModule,\n AvatarComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ContentDensityDirective,\n ToolbarSeparatorComponent,\n FormLabelComponent,\n TextComponent,\n RatingIndicatorComponent,\n ObjectStatusComponent,\n ObjectNumberComponent,\n CdkScrollable,\n BarModule\n ]\n})\nexport class DynamicPageFacetsExampleComponent {\n visible = false;\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n }\n\n closePage(): void {\n this.visible = false;\n }\n}\n", "html": "\n@if (visible) {\n
    \n \n \n \n Lorem ipsum dolor sit amet, consectetur adipiscing elit ({{\n collapsed ? 'collapsed' : 'not collapsed'\n }})\n \n \n Different parts | of the |\n subtitle | with\n {{ collapsed ? 'collapsed' : 'not collapsed' }} header\n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n}\n" }, - { - "name": "dynamic-page-responsive-example", - "description": "Dynamic Page Responsive", - "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-responsive-example',\n templateUrl: './dynamic-page-responsive-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n BreadcrumbModule,\n ContentDensityDirective,\n LinkComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n MessageToastModule\n ]\n})\nexport class DynamicPageResponsiveExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n compact = true;\n\n constructor(private _messageToastService: MessageToastService) {}\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", - "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum consequuntur\n impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n}\n" - }, { "name": "dynamic-page-routing-example", "description": "Dynamic Page Routing", @@ -35082,6 +35112,12 @@ "typescript": "import { Component } from '@angular/core';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\n\nimport { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { FlexibleColumnLayout, FlexibleColumnLayoutModule } from '@fundamental-ngx/core/flexible-column-layout';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\n@Component({\n selector: 'fd-dynamic-page-column-layout-example',\n templateUrl: './dynamic-page-column-layout-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n FlexibleColumnLayoutModule,\n DynamicPageModule,\n BreadcrumbModule,\n LinkComponent,\n ContentDensityDirective,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n FDP_ICON_TAB_BAR,\n MessageToastModule\n ]\n})\nexport class DynamicPageColumnLayoutExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n /**\n * documentation related property\n * sets the initial layout of the component to 'OneColumnStartFullScreen'\n * sets a new layout for the component\n */\n localLayout: FlexibleColumnLayout = 'OneColumnStartFullScreen';\n\n separatorAriaLabel = 'separator';\n\n expandTitle = 'Expand';\n\n collapseTitle = 'Collapse';\n\n constructor(private _messageToastService: MessageToastService) {}\n\n /**\n * this function is reacting to events (button clicks) and\n * updates the local property which sets a new layout for the component.\n * Available values for the layouts include:\n * 'OneColumnStartFullScreen' | 'OneColumnMidFullScreen' | 'OneColumnEndFullScreen' |\n * 'TwoColumnsStartExpanded' | 'TwoColumnsMidExpanded' | 'TwoColumnsEndExpanded' |\n * 'ThreeColumnsMidExpanded' | 'ThreeColumnsEndExpanded' | 'ThreeColumnsStartMinimized' |\n * 'ThreeColumnsEndMinimized';\n */\n changeLayout(newValue: FlexibleColumnLayout): void {\n this.localLayout = newValue;\n }\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum\n consequuntur impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n \n

    Mid Column

    \n
    \n \n Open Column 3\n \n
    \n \n @for (tab of [1, 2, 3, 4]; track tab) {\n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor\n incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud\n exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure\n dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt\n mollit anim id est laborum.\n
    \n
    \n }\n
    \n
    \n \n

    End Column

    \n
    \n @if (localLayout !== 'OneColumnEndFullScreen') {\n \n \n } @else {\n \n }\n
    \n
    \n \n \n}\n" }, + { + "name": "dynamic-page-responsive-example", + "description": "Dynamic Page Responsive", + "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-responsive-example',\n templateUrl: './dynamic-page-responsive-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n BreadcrumbModule,\n ContentDensityDirective,\n LinkComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n MessageToastModule\n ]\n})\nexport class DynamicPageResponsiveExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n compact = true;\n\n constructor(private _messageToastService: MessageToastService) {}\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", + "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum consequuntur\n impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n}\n" + }, { "name": "dynamic-page-dynamic-container-height-example", "description": "Dynamic Page Dynamic Container Height", @@ -35094,12 +35130,6 @@ "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n DynamicPageHeaderSubtitleDirective,\n DynamicPageHeaderTitleDirective,\n DynamicPageModule\n} from '@fundamental-ngx/core/dynamic-page';\nimport { FacetModule } from '@fundamental-ngx/core/facets';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ObjectNumberComponent } from '@fundamental-ngx/core/object-number';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { RatingIndicatorComponent } from '@fundamental-ngx/core/rating-indicator';\nimport { TextComponent } from '@fundamental-ngx/core/text';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-facets-example',\n templateUrl: './dynamic-page-facets-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n .red-subtitle {\n color: red;\n }\n .blue-subtitle {\n color: blue;\n }\n .green-subtitle {\n color: green;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n DynamicPageHeaderTitleDirective,\n DynamicPageHeaderSubtitleDirective,\n BreadcrumbModule,\n LinkComponent,\n FacetModule,\n AvatarComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ContentDensityDirective,\n ToolbarSeparatorComponent,\n FormLabelComponent,\n TextComponent,\n RatingIndicatorComponent,\n ObjectStatusComponent,\n ObjectNumberComponent,\n CdkScrollable,\n BarModule\n ]\n})\nexport class DynamicPageFacetsExampleComponent {\n visible = false;\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n }\n\n closePage(): void {\n this.visible = false;\n }\n}\n", "html": "\n@if (visible) {\n
    \n \n \n \n Lorem ipsum dolor sit amet, consectetur adipiscing elit ({{\n collapsed ? 'collapsed' : 'not collapsed'\n }})\n \n \n Different parts | of the |\n subtitle | with\n {{ collapsed ? 'collapsed' : 'not collapsed' }} header\n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n}\n" }, - { - "name": "dynamic-page-responsive-example", - "description": "Dynamic Page Responsive", - "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-responsive-example',\n templateUrl: './dynamic-page-responsive-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n BreadcrumbModule,\n ContentDensityDirective,\n LinkComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n MessageToastModule\n ]\n})\nexport class DynamicPageResponsiveExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n compact = true;\n\n constructor(private _messageToastService: MessageToastService) {}\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", - "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum consequuntur\n impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n}\n" - }, { "name": "dynamic-page-routing-example", "description": "Dynamic Page Routing", @@ -35160,6 +35190,12 @@ "typescript": "import { Component } from '@angular/core';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\n\nimport { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { FlexibleColumnLayout, FlexibleColumnLayoutModule } from '@fundamental-ngx/core/flexible-column-layout';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\n@Component({\n selector: 'fd-dynamic-page-column-layout-example',\n templateUrl: './dynamic-page-column-layout-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n FlexibleColumnLayoutModule,\n DynamicPageModule,\n BreadcrumbModule,\n LinkComponent,\n ContentDensityDirective,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n FDP_ICON_TAB_BAR,\n MessageToastModule\n ]\n})\nexport class DynamicPageColumnLayoutExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n /**\n * documentation related property\n * sets the initial layout of the component to 'OneColumnStartFullScreen'\n * sets a new layout for the component\n */\n localLayout: FlexibleColumnLayout = 'OneColumnStartFullScreen';\n\n separatorAriaLabel = 'separator';\n\n expandTitle = 'Expand';\n\n collapseTitle = 'Collapse';\n\n constructor(private _messageToastService: MessageToastService) {}\n\n /**\n * this function is reacting to events (button clicks) and\n * updates the local property which sets a new layout for the component.\n * Available values for the layouts include:\n * 'OneColumnStartFullScreen' | 'OneColumnMidFullScreen' | 'OneColumnEndFullScreen' |\n * 'TwoColumnsStartExpanded' | 'TwoColumnsMidExpanded' | 'TwoColumnsEndExpanded' |\n * 'ThreeColumnsMidExpanded' | 'ThreeColumnsEndExpanded' | 'ThreeColumnsStartMinimized' |\n * 'ThreeColumnsEndMinimized';\n */\n changeLayout(newValue: FlexibleColumnLayout): void {\n this.localLayout = newValue;\n }\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum\n consequuntur impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n \n

    Mid Column

    \n
    \n \n Open Column 3\n \n
    \n \n @for (tab of [1, 2, 3, 4]; track tab) {\n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor\n incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud\n exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure\n dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt\n mollit anim id est laborum.\n
    \n
    \n }\n
    \n
    \n \n

    End Column

    \n
    \n @if (localLayout !== 'OneColumnEndFullScreen') {\n \n \n } @else {\n \n }\n
    \n
    \n \n \n}\n" }, + { + "name": "dynamic-page-responsive-example", + "description": "Dynamic Page Responsive", + "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-responsive-example',\n templateUrl: './dynamic-page-responsive-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n BreadcrumbModule,\n ContentDensityDirective,\n LinkComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n MessageToastModule\n ]\n})\nexport class DynamicPageResponsiveExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n compact = true;\n\n constructor(private _messageToastService: MessageToastService) {}\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", + "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum consequuntur\n impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n}\n" + }, { "name": "dynamic-page-dynamic-container-height-example", "description": "Dynamic Page Dynamic Container Height", @@ -35172,12 +35208,6 @@ "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n DynamicPageHeaderSubtitleDirective,\n DynamicPageHeaderTitleDirective,\n DynamicPageModule\n} from '@fundamental-ngx/core/dynamic-page';\nimport { FacetModule } from '@fundamental-ngx/core/facets';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ObjectNumberComponent } from '@fundamental-ngx/core/object-number';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { RatingIndicatorComponent } from '@fundamental-ngx/core/rating-indicator';\nimport { TextComponent } from '@fundamental-ngx/core/text';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-facets-example',\n templateUrl: './dynamic-page-facets-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n .red-subtitle {\n color: red;\n }\n .blue-subtitle {\n color: blue;\n }\n .green-subtitle {\n color: green;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n DynamicPageHeaderTitleDirective,\n DynamicPageHeaderSubtitleDirective,\n BreadcrumbModule,\n LinkComponent,\n FacetModule,\n AvatarComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ContentDensityDirective,\n ToolbarSeparatorComponent,\n FormLabelComponent,\n TextComponent,\n RatingIndicatorComponent,\n ObjectStatusComponent,\n ObjectNumberComponent,\n CdkScrollable,\n BarModule\n ]\n})\nexport class DynamicPageFacetsExampleComponent {\n visible = false;\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n }\n\n closePage(): void {\n this.visible = false;\n }\n}\n", "html": "\n@if (visible) {\n
    \n \n \n \n Lorem ipsum dolor sit amet, consectetur adipiscing elit ({{\n collapsed ? 'collapsed' : 'not collapsed'\n }})\n \n \n Different parts | of the |\n subtitle | with\n {{ collapsed ? 'collapsed' : 'not collapsed' }} header\n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n}\n" }, - { - "name": "dynamic-page-responsive-example", - "description": "Dynamic Page Responsive", - "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-responsive-example',\n templateUrl: './dynamic-page-responsive-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n BreadcrumbModule,\n ContentDensityDirective,\n LinkComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n MessageToastModule\n ]\n})\nexport class DynamicPageResponsiveExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n compact = true;\n\n constructor(private _messageToastService: MessageToastService) {}\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", - "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum consequuntur\n impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n}\n" - }, { "name": "dynamic-page-routing-example", "description": "Dynamic Page Routing", @@ -35302,6 +35332,12 @@ "typescript": "import { Component } from '@angular/core';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\n\nimport { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { FlexibleColumnLayout, FlexibleColumnLayoutModule } from '@fundamental-ngx/core/flexible-column-layout';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\n@Component({\n selector: 'fd-dynamic-page-column-layout-example',\n templateUrl: './dynamic-page-column-layout-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n FlexibleColumnLayoutModule,\n DynamicPageModule,\n BreadcrumbModule,\n LinkComponent,\n ContentDensityDirective,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n FDP_ICON_TAB_BAR,\n MessageToastModule\n ]\n})\nexport class DynamicPageColumnLayoutExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n /**\n * documentation related property\n * sets the initial layout of the component to 'OneColumnStartFullScreen'\n * sets a new layout for the component\n */\n localLayout: FlexibleColumnLayout = 'OneColumnStartFullScreen';\n\n separatorAriaLabel = 'separator';\n\n expandTitle = 'Expand';\n\n collapseTitle = 'Collapse';\n\n constructor(private _messageToastService: MessageToastService) {}\n\n /**\n * this function is reacting to events (button clicks) and\n * updates the local property which sets a new layout for the component.\n * Available values for the layouts include:\n * 'OneColumnStartFullScreen' | 'OneColumnMidFullScreen' | 'OneColumnEndFullScreen' |\n * 'TwoColumnsStartExpanded' | 'TwoColumnsMidExpanded' | 'TwoColumnsEndExpanded' |\n * 'ThreeColumnsMidExpanded' | 'ThreeColumnsEndExpanded' | 'ThreeColumnsStartMinimized' |\n * 'ThreeColumnsEndMinimized';\n */\n changeLayout(newValue: FlexibleColumnLayout): void {\n this.localLayout = newValue;\n }\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum\n consequuntur impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n \n

    Mid Column

    \n
    \n \n Open Column 3\n \n
    \n \n @for (tab of [1, 2, 3, 4]; track tab) {\n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor\n incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud\n exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure\n dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt\n mollit anim id est laborum.\n
    \n
    \n }\n
    \n
    \n \n

    End Column

    \n
    \n @if (localLayout !== 'OneColumnEndFullScreen') {\n \n \n } @else {\n \n }\n
    \n
    \n \n \n}\n" }, + { + "name": "dynamic-page-responsive-example", + "description": "Dynamic Page Responsive", + "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-responsive-example',\n templateUrl: './dynamic-page-responsive-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n BreadcrumbModule,\n ContentDensityDirective,\n LinkComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n MessageToastModule\n ]\n})\nexport class DynamicPageResponsiveExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n compact = true;\n\n constructor(private _messageToastService: MessageToastService) {}\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", + "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum consequuntur\n impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n}\n" + }, { "name": "dynamic-page-dynamic-container-height-example", "description": "Dynamic Page Dynamic Container Height", @@ -35314,12 +35350,6 @@ "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n DynamicPageHeaderSubtitleDirective,\n DynamicPageHeaderTitleDirective,\n DynamicPageModule\n} from '@fundamental-ngx/core/dynamic-page';\nimport { FacetModule } from '@fundamental-ngx/core/facets';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ObjectNumberComponent } from '@fundamental-ngx/core/object-number';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { RatingIndicatorComponent } from '@fundamental-ngx/core/rating-indicator';\nimport { TextComponent } from '@fundamental-ngx/core/text';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-facets-example',\n templateUrl: './dynamic-page-facets-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n .red-subtitle {\n color: red;\n }\n .blue-subtitle {\n color: blue;\n }\n .green-subtitle {\n color: green;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n DynamicPageHeaderTitleDirective,\n DynamicPageHeaderSubtitleDirective,\n BreadcrumbModule,\n LinkComponent,\n FacetModule,\n AvatarComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ContentDensityDirective,\n ToolbarSeparatorComponent,\n FormLabelComponent,\n TextComponent,\n RatingIndicatorComponent,\n ObjectStatusComponent,\n ObjectNumberComponent,\n CdkScrollable,\n BarModule\n ]\n})\nexport class DynamicPageFacetsExampleComponent {\n visible = false;\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n }\n\n closePage(): void {\n this.visible = false;\n }\n}\n", "html": "\n@if (visible) {\n
    \n \n \n \n Lorem ipsum dolor sit amet, consectetur adipiscing elit ({{\n collapsed ? 'collapsed' : 'not collapsed'\n }})\n \n \n Different parts | of the |\n subtitle | with\n {{ collapsed ? 'collapsed' : 'not collapsed' }} header\n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n}\n" }, - { - "name": "dynamic-page-responsive-example", - "description": "Dynamic Page Responsive", - "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-responsive-example',\n templateUrl: './dynamic-page-responsive-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n BreadcrumbModule,\n ContentDensityDirective,\n LinkComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n MessageToastModule\n ]\n})\nexport class DynamicPageResponsiveExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n compact = true;\n\n constructor(private _messageToastService: MessageToastService) {}\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", - "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum consequuntur\n impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n}\n" - }, { "name": "dynamic-page-routing-example", "description": "Dynamic Page Routing", @@ -35373,6 +35403,12 @@ "typescript": "import { Component } from '@angular/core';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\n\nimport { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { FlexibleColumnLayout, FlexibleColumnLayoutModule } from '@fundamental-ngx/core/flexible-column-layout';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\n@Component({\n selector: 'fd-dynamic-page-column-layout-example',\n templateUrl: './dynamic-page-column-layout-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n FlexibleColumnLayoutModule,\n DynamicPageModule,\n BreadcrumbModule,\n LinkComponent,\n ContentDensityDirective,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n FDP_ICON_TAB_BAR,\n MessageToastModule\n ]\n})\nexport class DynamicPageColumnLayoutExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n /**\n * documentation related property\n * sets the initial layout of the component to 'OneColumnStartFullScreen'\n * sets a new layout for the component\n */\n localLayout: FlexibleColumnLayout = 'OneColumnStartFullScreen';\n\n separatorAriaLabel = 'separator';\n\n expandTitle = 'Expand';\n\n collapseTitle = 'Collapse';\n\n constructor(private _messageToastService: MessageToastService) {}\n\n /**\n * this function is reacting to events (button clicks) and\n * updates the local property which sets a new layout for the component.\n * Available values for the layouts include:\n * 'OneColumnStartFullScreen' | 'OneColumnMidFullScreen' | 'OneColumnEndFullScreen' |\n * 'TwoColumnsStartExpanded' | 'TwoColumnsMidExpanded' | 'TwoColumnsEndExpanded' |\n * 'ThreeColumnsMidExpanded' | 'ThreeColumnsEndExpanded' | 'ThreeColumnsStartMinimized' |\n * 'ThreeColumnsEndMinimized';\n */\n changeLayout(newValue: FlexibleColumnLayout): void {\n this.localLayout = newValue;\n }\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum\n consequuntur impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut\n labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco\n laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n \n

    Mid Column

    \n
    \n \n Open Column 3\n \n
    \n \n @for (tab of [1, 2, 3, 4]; track tab) {\n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor\n incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud\n exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure\n dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt\n mollit anim id est laborum.\n
    \n
    \n }\n
    \n
    \n \n

    End Column

    \n
    \n @if (localLayout !== 'OneColumnEndFullScreen') {\n \n \n } @else {\n \n }\n
    \n
    \n \n \n}\n" }, + { + "name": "dynamic-page-responsive-example", + "description": "Dynamic Page Responsive", + "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-responsive-example',\n templateUrl: './dynamic-page-responsive-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n BreadcrumbModule,\n ContentDensityDirective,\n LinkComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n MessageToastModule\n ]\n})\nexport class DynamicPageResponsiveExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n compact = true;\n\n constructor(private _messageToastService: MessageToastService) {}\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", + "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum consequuntur\n impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n}\n" + }, { "name": "dynamic-page-dynamic-container-height-example", "description": "Dynamic Page Dynamic Container Height", @@ -35385,12 +35421,6 @@ "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n DynamicPageHeaderSubtitleDirective,\n DynamicPageHeaderTitleDirective,\n DynamicPageModule\n} from '@fundamental-ngx/core/dynamic-page';\nimport { FacetModule } from '@fundamental-ngx/core/facets';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { ObjectNumberComponent } from '@fundamental-ngx/core/object-number';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { RatingIndicatorComponent } from '@fundamental-ngx/core/rating-indicator';\nimport { TextComponent } from '@fundamental-ngx/core/text';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-facets-example',\n templateUrl: './dynamic-page-facets-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n .red-subtitle {\n color: red;\n }\n .blue-subtitle {\n color: blue;\n }\n .green-subtitle {\n color: green;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n DynamicPageHeaderTitleDirective,\n DynamicPageHeaderSubtitleDirective,\n BreadcrumbModule,\n LinkComponent,\n FacetModule,\n AvatarComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ContentDensityDirective,\n ToolbarSeparatorComponent,\n FormLabelComponent,\n TextComponent,\n RatingIndicatorComponent,\n ObjectStatusComponent,\n ObjectNumberComponent,\n CdkScrollable,\n BarModule\n ]\n})\nexport class DynamicPageFacetsExampleComponent {\n visible = false;\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n }\n\n closePage(): void {\n this.visible = false;\n }\n}\n", "html": "\n@if (visible) {\n
    \n \n \n \n Lorem ipsum dolor sit amet, consectetur adipiscing elit ({{\n collapsed ? 'collapsed' : 'not collapsed'\n }})\n \n \n Different parts | of the |\n subtitle | with\n {{ collapsed ? 'collapsed' : 'not collapsed' }} header\n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n}\n" }, - { - "name": "dynamic-page-responsive-example", - "description": "Dynamic Page Responsive", - "typescript": "import { CdkScrollable } from '@angular/cdk/scrolling';\n\nimport { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ToolbarComponent, ToolbarItemDirective, ToolbarSeparatorComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-dynamic-page-responsive-example',\n templateUrl: './dynamic-page-responsive-example.component.html',\n styles: [\n `\n .overlay {\n height: 100%;\n width: 100%;\n position: fixed;\n z-index: 10;\n top: 0;\n left: 0;\n background-color: rgb(255, 255, 255);\n overflow-x: hidden;\n }\n .fd-dynamic-page-section-example {\n min-height: 20vh;\n }\n `\n ],\n imports: [\n ButtonComponent,\n DynamicPageModule,\n BreadcrumbModule,\n ContentDensityDirective,\n LinkComponent,\n ToolbarComponent,\n ToolbarItemDirective,\n ToolbarSeparatorComponent,\n CdkScrollable,\n BarModule,\n MessageToastModule\n ]\n})\nexport class DynamicPageResponsiveExampleComponent {\n visible = false;\n\n pageTitle = 'Balenciaga Tripple S Trainers';\n\n compact = true;\n\n constructor(private _messageToastService: MessageToastService) {}\n\n onCollapseChange(): void {\n console.log('collapse changed');\n }\n\n openPage(): void {\n this.visible = true;\n this._openToast('Dynamic Page has been opened');\n }\n\n closePage(): void {\n this.visible = false;\n }\n\n handleAction(action: string): void {\n this.closePage();\n this._openToast(action);\n }\n\n private _openToast(content: string): void {\n this._messageToastService.open(content, { duration: 3000 });\n }\n}\n", - "html": "\n@if (visible) {\n
    \n \n \n \n \n \n \n Men\n \n \n Shoes\n \n \n Running Shoes\n \n \n Jogging\n \n \n \n Key Info \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti architecto\n perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur iure. Cum consequuntur\n impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n
    \n \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n}\n" - }, { "name": "dynamic-page-routing-example", "description": "Dynamic Page Routing", @@ -35702,10 +35732,10 @@ "html": "\n \n\n \n\n \n\n" }, { - "name": "feed-input-grow-example", - "description": "Feed Input Grow", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { FeedInputModule } from '@fundamental-ngx/core/feed-input';\nimport { FormControlComponent } from '@fundamental-ngx/core/form';\n\n@Component({\n selector: 'fd-feed-input-grow-example',\n templateUrl: './feed-input-grow-example.component.html',\n imports: [FeedInputModule, AvatarComponent, FormControlComponent]\n})\nexport class FeedInputGrowExampleComponent {}\n", - "html": "\n \n\n \n\n \n\n" + "name": "feed-input-placeholder-example", + "description": "Feed Input Placeholder", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { FeedInputModule } from '@fundamental-ngx/core/feed-input';\nimport { FormControlComponent } from '@fundamental-ngx/core/form';\n\n@Component({\n selector: 'fd-feed-input-placeholder-example',\n templateUrl: './feed-input-placeholder-example.component.html',\n imports: [FeedInputModule, AvatarComponent, FormControlComponent]\n})\nexport class FeedInputPlaceholderExampleComponent {}\n", + "html": "\n \n\n \n\n \n\n" }, { "name": "feed-input-no-avatar-example", @@ -35714,10 +35744,10 @@ "html": "\n \n\n \n\n" }, { - "name": "feed-input-placeholder-example", - "description": "Feed Input Placeholder", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { FeedInputModule } from '@fundamental-ngx/core/feed-input';\nimport { FormControlComponent } from '@fundamental-ngx/core/form';\n\n@Component({\n selector: 'fd-feed-input-placeholder-example',\n templateUrl: './feed-input-placeholder-example.component.html',\n imports: [FeedInputModule, AvatarComponent, FormControlComponent]\n})\nexport class FeedInputPlaceholderExampleComponent {}\n", - "html": "\n \n\n \n\n \n\n" + "name": "feed-input-grow-example", + "description": "Feed Input Grow", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { FeedInputModule } from '@fundamental-ngx/core/feed-input';\nimport { FormControlComponent } from '@fundamental-ngx/core/form';\n\n@Component({\n selector: 'fd-feed-input-grow-example',\n templateUrl: './feed-input-grow-example.component.html',\n imports: [FeedInputModule, AvatarComponent, FormControlComponent]\n})\nexport class FeedInputGrowExampleComponent {}\n", + "html": "\n \n\n \n\n \n\n" } ] }, @@ -35911,18 +35941,6 @@ "sourceFile": "libs/core/feed-list-item/components/item/feed-list-item.component.ts", "source": "typedoc", "examples": [ - { - "name": "fli-action-example", - "description": "Fli Action", - "typescript": "import { Component } from '@angular/core';\nimport { ActionSheetModule } from '@fundamental-ngx/core/action-sheet';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { FeedListItemModule } from '@fundamental-ngx/core/feed-list-item';\n\n@Component({\n selector: 'fd-fli-action-example',\n templateUrl: './fli-action-example.component.html',\n imports: [FeedListItemModule, ButtonComponent, ContentDensityDirective, ActionSheetModule]\n})\nexport class FliActionExampleComponent {\n onClick(): void {\n alert('You custom action');\n }\n}\n", - "html": "\n \n \n \n \n \n\n
    \n\n \n \n \n \n \n \n\n \n
  • \n
  • \n \n
    \n
    \n
    \n \n
    \n" - }, - { - "name": "fli-avatar-example", - "description": "Fli Avatar", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { FeedListItemModule } from '@fundamental-ngx/core/feed-list-item';\n\n@Component({\n selector: 'fd-fli-avatar-example',\n templateUrl: './fli-avatar-example.component.html',\n imports: [FeedListItemModule, AvatarComponent]\n})\nexport class FliAvatarExampleComponent {}\n", - "html": "\n \n \n \n \n \n \n \n \n \n \n\n
    \n\n \n \n \n \n KH\n \n \n \n\n" - }, { "name": "fli-footer-example", "description": "Fli Footer", @@ -35935,6 +35953,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ActionSheetModule } from '@fundamental-ngx/core/action-sheet';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { FeedListItemModule } from '@fundamental-ngx/core/feed-list-item';\n\n@Component({\n selector: 'fd-fli-mobile-example',\n templateUrl: './fli-mobile-example.component.html',\n imports: [FeedListItemModule, AvatarComponent, ActionSheetModule, ButtonComponent, ContentDensityDirective]\n})\nexport class FliMobileExampleComponent {}\n", "html": "
    \n \n \n \n \n \n \n \n \n \n \n\n \n
  • \n
  • \n
  • \n
  • \n
    \n
    \n
    \n \n Aug 20, 2020\n \n Reply link\n \n \n \n
    \n
    \n" }, + { + "name": "fli-action-example", + "description": "Fli Action", + "typescript": "import { Component } from '@angular/core';\nimport { ActionSheetModule } from '@fundamental-ngx/core/action-sheet';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { FeedListItemModule } from '@fundamental-ngx/core/feed-list-item';\n\n@Component({\n selector: 'fd-fli-action-example',\n templateUrl: './fli-action-example.component.html',\n imports: [FeedListItemModule, ButtonComponent, ContentDensityDirective, ActionSheetModule]\n})\nexport class FliActionExampleComponent {\n onClick(): void {\n alert('You custom action');\n }\n}\n", + "html": "\n \n \n \n \n \n\n
    \n\n \n \n \n \n \n \n\n \n
  • \n
  • \n \n
    \n
    \n
    \n \n
    \n" + }, + { + "name": "fli-avatar-example", + "description": "Fli Avatar", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { FeedListItemModule } from '@fundamental-ngx/core/feed-list-item';\n\n@Component({\n selector: 'fd-fli-avatar-example',\n templateUrl: './fli-avatar-example.component.html',\n imports: [FeedListItemModule, AvatarComponent]\n})\nexport class FliAvatarExampleComponent {}\n", + "html": "\n \n \n \n \n \n \n \n \n \n \n\n
    \n\n \n \n \n \n KH\n \n \n \n\n" + }, { "name": "fli-simple-example", "description": "Fli Simple", @@ -36139,17 +36169,17 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FileUploaderModule } from '@fundamental-ngx/core/file-uploader';\n\n@Component({\n selector: 'fd-file-uploader-max-example',\n templateUrl: './file-uploader-max-example.component.html',\n styleUrls: ['./file-uploader-max-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [FileUploaderModule, FormsModule]\n})\nexport class FileUploaderMaxExampleComponent {\n files: File[];\n invalidFiles: File[];\n\n handleFileSelection(files: File[]): void {\n alert(files.length + ' Files selected successfully!!!');\n }\n\n handleInvalidFiles(files: File[]): void {\n alert(files.length + ' Invalid files selected ');\n this.invalidFiles = files;\n }\n}\n", "html": "\n
    \n
    \nFiles Selected:\n
    \n@for (file of files; track file) {\n \n {{ file.name }} \n}\n
    \nInvalid Files:\n
    \n@for (file of invalidFiles; track file) {\n \n {{ file.name }} \n}\n" }, - { - "name": "file-uploader-min-example", - "description": "File Uploader Min", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FileUploaderModule } from '@fundamental-ngx/core/file-uploader';\n\n@Component({\n selector: 'fd-file-uploader-min-example',\n templateUrl: './file-uploader-min-example.component.html',\n styleUrls: ['./file-uploader-min-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [FileUploaderModule, FormsModule]\n})\nexport class FileUploaderMinExampleComponent {\n files: File[];\n invalidFiles: File[];\n\n handleFileSelection(files: File[]): void {\n alert(files.length + ' Files selected successfully!!!');\n }\n\n handleInvalidFiles(files: File[]): void {\n alert(files.length + ' Invalid files selected ');\n this.invalidFiles = files;\n }\n}\n", - "html": "\n\n

    \nFiles Selected:\n
    \n@for (file of files; track file) {\n \n {{ file.name }} \n}\n
    \nInvalid Files:\n
    \n@for (file of invalidFiles; track file) {\n \n {{ file.name }}
    \n
    \n}\n" - }, { "name": "file-uploader-truncation-example", "description": "File Uploader Truncation", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FileUploaderModule } from '@fundamental-ngx/core/file-uploader';\n\n@Component({\n selector: 'fd-file-uploader-truncation-example',\n templateUrl: './file-uploader-truncation-example.component.html',\n styleUrls: ['./file-uploader-truncation-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [FileUploaderModule, FormsModule]\n})\nexport class FileUploaderTruncationExampleComponent {\n files: File[];\n}\n", "html": "\n\n

    \nFiles Selected:\n
    \n@for (file of files; track file) {\n \n {{ file.name }}
    \n
    \n}\n" + }, + { + "name": "file-uploader-min-example", + "description": "File Uploader Min", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FileUploaderModule } from '@fundamental-ngx/core/file-uploader';\n\n@Component({\n selector: 'fd-file-uploader-min-example',\n templateUrl: './file-uploader-min-example.component.html',\n styleUrls: ['./file-uploader-min-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [FileUploaderModule, FormsModule]\n})\nexport class FileUploaderMinExampleComponent {\n files: File[];\n invalidFiles: File[];\n\n handleFileSelection(files: File[]): void {\n alert(files.length + ' Files selected successfully!!!');\n }\n\n handleInvalidFiles(files: File[]): void {\n alert(files.length + ' Invalid files selected ');\n this.invalidFiles = files;\n }\n}\n", + "html": "\n\n

    \nFiles Selected:\n
    \n@for (file of files; track file) {\n \n {{ file.name }} \n}\n
    \nInvalid Files:\n
    \n@for (file of invalidFiles; track file) {\n \n {{ file.name }}
    \n
    \n}\n" } ] }, @@ -36376,17 +36406,17 @@ "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n FD_FLEXIBLE_LAYOUT_CONFIG,\n FlexibleColumnLayout,\n FlexibleColumnLayoutModule,\n FlexibleLayoutConfig\n} from '@fundamental-ngx/core/flexible-column-layout';\n\nconst CustomFlexibleCardLayoutConfig: FlexibleLayoutConfig = {\n layouts: {\n OneColumnStartFullScreen: { start: 100, mid: 0, end: 0 },\n OneColumnMidFullScreen: { start: 0, mid: 100, end: 0 },\n OneColumnEndFullScreen: { start: 0, mid: 0, end: 100 },\n TwoColumnsStartExpanded: { start: 50, mid: 50, end: 0 },\n TwoColumnsMidExpanded: { start: 33, mid: 67, end: 0 },\n TwoColumnsEndExpanded: { start: 0, mid: 33, end: 67 },\n ThreeColumnsMidExpanded: { start: 25, mid: 50, end: 25 },\n ThreeColumnsEndExpanded: { start: 25, mid: 25, end: 50 },\n ThreeColumnsStartMinimized: { start: 0, mid: 50, end: 50 },\n ThreeColumnsEndMinimized: { start: 50, mid: 50, end: 0 }\n }\n};\n\n@Component({\n selector: 'fd-flexible-column-layout-custom-config-example',\n templateUrl: './flexible-column-layout-custom-config-example.component.html',\n styleUrls: ['./flexible-column-layout-custom-config-example.component.scss'],\n providers: [\n {\n provide: FD_FLEXIBLE_LAYOUT_CONFIG,\n useValue: CustomFlexibleCardLayoutConfig\n }\n ],\n imports: [ButtonComponent, FlexibleColumnLayoutModule]\n})\nexport class FlexibleColumnLayoutCustomConfigExampleComponent {\n /**\n * documentation related property\n * provides access to the HTML element with \"overlay\" reference\n */\n @ViewChild('overlay')\n overlay: ElementRef;\n\n /**\n * documentation related property\n * specifies if the doc example is rendered in fullscreen or not\n */\n fullscreen = false;\n\n /**\n * documentation related property\n * sets the initial layout of the component to 'OneColumnStartFullScreen'\n * sets a new layout for the component\n */\n localLayout: FlexibleColumnLayout = 'OneColumnStartFullScreen';\n\n /**\n * this function is reacting to events (button clicks) and\n * updates the local property which sets a new layout for the component.\n * Available values for the layouts include:\n * 'OneColumnStartFullScreen' | 'OneColumnMidFullScreen' | 'OneColumnEndFullScreen' |\n * 'TwoColumnsStartExpanded' | 'TwoColumnsMidExpanded' | 'TwoColumnsEndExpanded' |\n * 'ThreeColumnsMidExpanded' | 'ThreeColumnsEndExpanded' | 'ThreeColumnsStartMinimized' |\n * 'ThreeColumnsEndMinimized';\n */\n changeLayout(newValue: FlexibleColumnLayout): void {\n this.localLayout = newValue;\n }\n\n /**\n * documentation related function\n * opens the example in full screen\n */\n enterFullscreenExample(): void {\n this.fullscreen = true;\n this.overlay.nativeElement.style.width = '100%';\n }\n\n /**\n * documentation related function\n * exits the full screen mode of the example\n */\n exitFullscreenExample(event: Event): void {\n event.stopPropagation();\n this.fullscreen = false;\n this.overlay.nativeElement.style.width = '0%';\n }\n}\n", "html": "\n
    \n @if (fullscreen) {\n
    \n
    \n \n
    \n \n \n \n
    \n

    Start Column

    \n
    \n \n
    \n
    \n
    \n \n
    \n

    Mid Column

    \n
    \n \n
    \n
    \n
    \n \n
    \n

    End Column

    \n
    \n @if (localLayout !== 'OneColumnEndFullScreen') {\n \n }\n @if (localLayout !== 'OneColumnEndFullScreen') {\n \n }\n @if (localLayout === 'OneColumnEndFullScreen') {\n \n }\n
    \n
    \n
    \n
    \n
    \n }\n
    \n" }, - { - "name": "flexible-column-layout-example", - "description": "Flexible Column Layout", - "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { FlexibleColumnLayout, FlexibleColumnLayoutModule } from '@fundamental-ngx/core/flexible-column-layout';\n\n@Component({\n selector: 'fd-flexible-column-layout-example',\n templateUrl: './flexible-column-layout-example.component.html',\n styleUrls: ['flexible-column-layout-example.component.scss'],\n imports: [ButtonComponent, FlexibleColumnLayoutModule]\n})\nexport class FlexibleColumnLayoutExampleComponent {\n /**\n * documentation related property\n * provides access to the HTML element with \"overlay\" reference\n */\n @ViewChild('overlay')\n overlay: ElementRef;\n\n /**\n * documentation related property\n * specifies if the doc example is rendered in fullscreen or not\n */\n fullscreen = false;\n\n /**\n * documentation related property\n * sets the initial layout of the component to 'OneColumnStartFullScreen'\n * sets a new layout for the component\n */\n localLayout: FlexibleColumnLayout = 'OneColumnStartFullScreen';\n\n /**\n * this function is reacting to events (button clicks) and\n * updates the local property which sets a new layout for the component.\n * Available values for the layouts include:\n * 'OneColumnStartFullScreen' | 'OneColumnMidFullScreen' | 'OneColumnEndFullScreen' |\n * 'TwoColumnsStartExpanded' | 'TwoColumnsMidExpanded' | 'TwoColumnsEndExpanded' |\n * 'ThreeColumnsMidExpanded' | 'ThreeColumnsEndExpanded' | 'ThreeColumnsStartMinimized' |\n * 'ThreeColumnsEndMinimized';\n */\n changeLayout(newValue: FlexibleColumnLayout): void {\n this.localLayout = newValue;\n }\n\n /**\n * documentation related function\n * opens the example in full screen\n */\n enterFullscreenExample(): void {\n this.fullscreen = true;\n this.overlay.nativeElement.style.width = '100%';\n }\n\n /**\n * documentation related function\n * exits the full screen mode of the example\n */\n exitFullscreenExample(event: Event): void {\n event.stopPropagation();\n this.fullscreen = false;\n this.overlay.nativeElement.style.width = '0%';\n }\n}\n", - "html": "\n
    \n @if (fullscreen) {\n
    \n
    \n \n
    \n \n \n \n
    \n

    Start Column

    \n
    \n \n
    \n
    \n
    \n \n
    \n

    Mid Column

    \n
    \n \n
    \n
    \n
    \n \n
    \n

    End Column

    \n
    \n @if (localLayout !== 'OneColumnEndFullScreen') {\n \n }\n @if (localLayout !== 'OneColumnEndFullScreen') {\n \n }\n @if (localLayout === 'OneColumnEndFullScreen') {\n \n }\n
    \n
    \n
    \n \n
    \n }\n
    \n" - }, { "name": "flexible-column-layout-dynamic-page-example", "description": "Flexible Column Layout Dynamic Page", "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\n\nimport { CdkScrollable } from '@angular/cdk/overlay';\nimport { NgStyle } from '@angular/common';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { DynamicPageModule } from '@fundamental-ngx/core/dynamic-page';\nimport { FlexibleColumnLayout, FlexibleColumnLayoutModule } from '@fundamental-ngx/core/flexible-column-layout';\nimport { ToolbarComponent } from '@fundamental-ngx/core/toolbar';\n\n@Component({\n selector: 'fd-flexible-column-layout-dynamic-page-example',\n templateUrl: './flexible-column-layout-dynamic-page-example.component.html',\n styleUrls: ['./flexible-column-layout-dynamic-page-example.component.scss'],\n imports: [ButtonComponent, FlexibleColumnLayoutModule, DynamicPageModule, ToolbarComponent, NgStyle, CdkScrollable]\n})\nexport class FlexibleColumnLayoutDynamicPageExampleComponent {\n /**\n * property needed ONLY for the current documentation purposes\n * provides access to the HTML element with \"overlay\" reference\n */\n @ViewChild('overlay')\n overlay: ElementRef;\n\n /**\n * property set by the consuming application (name can vary????????)\n * sets the initial layout of the component to 'OneColumnStartFullScreen'\n * sets a new layout for the component\n */\n localLayout: FlexibleColumnLayout = 'OneColumnStartFullScreen';\n\n /**\n * property set by the consuming application\n * specifies if the control buttons for Enter/Exit Full Screen and Close\n * are visible in the middle sectioon\n */\n showMidColumnControls = this.localLayout.startsWith('Two') || this.localLayout.includes('FullScreen');\n\n /**\n * property set by the consuming application\n * checks if the component layout is in full screen\n */\n isFullScreen = this.localLayout.includes('FullScreen');\n\n /**\n * property needed ONLY for the current documentation purposes\n * specifies if the doc example is rendered in fullscreen or not\n */\n fullscreen = false;\n\n /**\n * function set by the consuming application\n * this function is reacting to events (button clicks) and\n * updates the local property which sets a new layout for the component.\n * Available values for the layouts include:\n * 'OneColumnStartFullScreen' | 'OneColumnMidFullScreen' | 'OneColumnEndFullScreen' |\n * 'TwoColumnsStartExpanded' | 'TwoColumnsMidExpanded' | 'TwoColumnsEndExpanded' |\n * 'ThreeColumnsMidExpanded' | 'ThreeColumnsEndExpanded' | 'ThreeColumnsStartMinimized' |\n * 'ThreeColumnsEndMinimized';\n */\n changeLayout(newValue: FlexibleColumnLayout): void {\n this.localLayout = newValue;\n this.showMidColumnControls = this.localLayout.startsWith('Two') || this.localLayout.includes('FullScreen');\n this.isFullScreen = this.localLayout.includes('FullScreen');\n }\n\n /**\n * function needed ONLY for the current documentation purposes\n * opens the example in full screen\n */\n enterFullscreenExample(): void {\n this.fullscreen = true;\n this.overlay.nativeElement.style.width = '100%';\n }\n\n /**\n * function needed ONLY for the current documentation purposes\n * exits the full screen mode of the example\n */\n exitFullscreenExample(event: Event): void {\n event.stopPropagation();\n this.fullscreen = false;\n this.overlay.nativeElement.style.width = '0%';\n }\n}\n", "html": "\n
    \n @if (fullscreen) {\n
    \n
    \n \n
    \n \n \n \n
    \n

    Start Column

    \n
    \n \n
    \n
    \n
    \n \n \n \n \n \n @if (showMidColumnControls) {\n \n \n \n }\n @if (showMidColumnControls) {\n \n \n \n }\n \n \n \n \n \n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam possimus corrupti\n architecto perspiciatis, delectus necessitatibus incidunt numquam asperiores tenetur\n iure. Cum consequuntur impedit repellendus esse, facere autem optio consequatur nobis?\n \n \n \n \n \n
    \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor\n incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud\n exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure\n dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt\n mollit anim id est laborum.\n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor\n incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud\n exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure\n dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt\n mollit anim id est laborum.\n
    \n
    \n
    \n
    \n \n
    \n }\n\n" + }, + { + "name": "flexible-column-layout-example", + "description": "Flexible Column Layout", + "typescript": "import { Component, ElementRef, ViewChild } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { FlexibleColumnLayout, FlexibleColumnLayoutModule } from '@fundamental-ngx/core/flexible-column-layout';\n\n@Component({\n selector: 'fd-flexible-column-layout-example',\n templateUrl: './flexible-column-layout-example.component.html',\n styleUrls: ['flexible-column-layout-example.component.scss'],\n imports: [ButtonComponent, FlexibleColumnLayoutModule]\n})\nexport class FlexibleColumnLayoutExampleComponent {\n /**\n * documentation related property\n * provides access to the HTML element with \"overlay\" reference\n */\n @ViewChild('overlay')\n overlay: ElementRef;\n\n /**\n * documentation related property\n * specifies if the doc example is rendered in fullscreen or not\n */\n fullscreen = false;\n\n /**\n * documentation related property\n * sets the initial layout of the component to 'OneColumnStartFullScreen'\n * sets a new layout for the component\n */\n localLayout: FlexibleColumnLayout = 'OneColumnStartFullScreen';\n\n /**\n * this function is reacting to events (button clicks) and\n * updates the local property which sets a new layout for the component.\n * Available values for the layouts include:\n * 'OneColumnStartFullScreen' | 'OneColumnMidFullScreen' | 'OneColumnEndFullScreen' |\n * 'TwoColumnsStartExpanded' | 'TwoColumnsMidExpanded' | 'TwoColumnsEndExpanded' |\n * 'ThreeColumnsMidExpanded' | 'ThreeColumnsEndExpanded' | 'ThreeColumnsStartMinimized' |\n * 'ThreeColumnsEndMinimized';\n */\n changeLayout(newValue: FlexibleColumnLayout): void {\n this.localLayout = newValue;\n }\n\n /**\n * documentation related function\n * opens the example in full screen\n */\n enterFullscreenExample(): void {\n this.fullscreen = true;\n this.overlay.nativeElement.style.width = '100%';\n }\n\n /**\n * documentation related function\n * exits the full screen mode of the example\n */\n exitFullscreenExample(event: Event): void {\n event.stopPropagation();\n this.fullscreen = false;\n this.overlay.nativeElement.style.width = '0%';\n }\n}\n", + "html": "\n
    \n @if (fullscreen) {\n
    \n
    \n \n
    \n \n \n \n
    \n

    Start Column

    \n
    \n \n
    \n
    \n
    \n \n
    \n

    Mid Column

    \n
    \n \n
    \n
    \n
    \n \n
    \n

    End Column

    \n
    \n @if (localLayout !== 'OneColumnEndFullScreen') {\n \n }\n @if (localLayout !== 'OneColumnEndFullScreen') {\n \n }\n @if (localLayout === 'OneColumnEndFullScreen') {\n \n }\n
    \n
    \n
    \n \n
    \n }\n
    \n" } ] }, @@ -36750,18 +36780,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n id: number;\n title: string;\n description: string;\n layoutItemPattern?: string;\n}\n\n@Component({\n selector: 'fd-grid-list-layout-example',\n templateUrl: './grid-list-layout-example.component.html',\n styleUrls: ['./grid-list-layout-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListLayoutExampleComponent {\n layoutPattern = 'XL4-L3-M2-S1';\n\n list: GridListItem[] = [\n {\n id: 1,\n title: 'Title 1',\n description: 'Description 1'\n },\n {\n id: 2,\n title: 'Title 2',\n description: 'Description 2',\n layoutItemPattern: 'XL6-L8-M6-S12'\n },\n {\n id: 3,\n title: 'Title 3',\n description: 'Description 3'\n },\n {\n id: 4,\n title: 'Title 4',\n description: 'Description 4'\n },\n {\n id: 5,\n title: 'Title 5',\n description: 'Description 5'\n },\n {\n id: 6,\n title: 'Title 6',\n description: 'Description 6'\n },\n {\n id: 7,\n title: 'Title 7',\n description: 'Description 7'\n }\n ];\n}\n", "html": "\n \n {{ '(' + list.length + ')' }}\n \n @for (item of list; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n
    \n" }, - { - "name": "grid-list-more-example", - "description": "Grid List More", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-more-example',\n templateUrl: './grid-list-more-example.component.html',\n styleUrls: ['./grid-list-more-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListMoreExampleComponent {\n totalItems = 50;\n\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n showMore(): void {\n if (this.list.length === this.totalItems) {\n return;\n }\n\n const newPart: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n this.list.push(...newPart);\n }\n}\n", - "html": "\n \n @for (item of list; track item; let i = $index) {\n \n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n }\n @if (totalItems !== list.length) {\n \n }\n
    \n" - }, { "name": "grid-list-states-example", "description": "Grid List States", "typescript": "import { Component } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListItemOutputEvent, GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\n@Component({\n selector: 'fd-grid-list-states-example',\n templateUrl: './grid-list-states-example.component.html',\n styleUrls: ['./grid-list-states-example.component.scss'],\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListStatesExampleComponent {\n locked(event: GridListItemOutputEvent): void {\n console.log('Locked event', event);\n }\n\n draft(event: GridListItemOutputEvent): void {\n console.log('Draft event', event);\n }\n}\n", "html": "\n \n (7)\n \n\n State: Unread \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n State: Error \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Custom error message \n
    \n\n State: Locked \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Locked button redefined to text \n
    \n\n State: Draft \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Draft button redefined to text \n
    \n
    \n" }, + { + "name": "grid-list-more-example", + "description": "Grid List More", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-more-example',\n templateUrl: './grid-list-more-example.component.html',\n styleUrls: ['./grid-list-more-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListMoreExampleComponent {\n totalItems = 50;\n\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n showMore(): void {\n if (this.list.length === this.totalItems) {\n return;\n }\n\n const newPart: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n this.list.push(...newPart);\n }\n}\n", + "html": "\n \n @for (item of list; track item; let i = $index) {\n \n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n }\n @if (totalItems !== list.length) {\n \n }\n
    \n" + }, { "name": "grid-list-statuses-example", "description": "Grid List Statuses", @@ -36838,100 +36868,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n id: number;\n title: string;\n description: string;\n layoutItemPattern?: string;\n}\n\n@Component({\n selector: 'fd-grid-list-layout-example',\n templateUrl: './grid-list-layout-example.component.html',\n styleUrls: ['./grid-list-layout-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListLayoutExampleComponent {\n layoutPattern = 'XL4-L3-M2-S1';\n\n list: GridListItem[] = [\n {\n id: 1,\n title: 'Title 1',\n description: 'Description 1'\n },\n {\n id: 2,\n title: 'Title 2',\n description: 'Description 2',\n layoutItemPattern: 'XL6-L8-M6-S12'\n },\n {\n id: 3,\n title: 'Title 3',\n description: 'Description 3'\n },\n {\n id: 4,\n title: 'Title 4',\n description: 'Description 4'\n },\n {\n id: 5,\n title: 'Title 5',\n description: 'Description 5'\n },\n {\n id: 6,\n title: 'Title 6',\n description: 'Description 6'\n },\n {\n id: 7,\n title: 'Title 7',\n description: 'Description 7'\n }\n ];\n}\n", "html": "\n \n {{ '(' + list.length + ')' }}\n \n @for (item of list; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n
    \n" }, - { - "name": "grid-list-more-example", - "description": "Grid List More", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-more-example',\n templateUrl: './grid-list-more-example.component.html',\n styleUrls: ['./grid-list-more-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListMoreExampleComponent {\n totalItems = 50;\n\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n showMore(): void {\n if (this.list.length === this.totalItems) {\n return;\n }\n\n const newPart: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n this.list.push(...newPart);\n }\n}\n", - "html": "\n \n @for (item of list; track item; let i = $index) {\n \n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n }\n @if (totalItems !== list.length) {\n \n }\n
    \n" - }, { "name": "grid-list-states-example", "description": "Grid List States", "typescript": "import { Component } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListItemOutputEvent, GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\n@Component({\n selector: 'fd-grid-list-states-example',\n templateUrl: './grid-list-states-example.component.html',\n styleUrls: ['./grid-list-states-example.component.scss'],\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListStatesExampleComponent {\n locked(event: GridListItemOutputEvent): void {\n console.log('Locked event', event);\n }\n\n draft(event: GridListItemOutputEvent): void {\n console.log('Draft event', event);\n }\n}\n", "html": "\n \n (7)\n \n\n State: Unread \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n State: Error \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Custom error message \n
    \n\n State: Locked \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Locked button redefined to text \n
    \n\n State: Draft \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Draft button redefined to text \n
    \n
    \n" }, - { - "name": "grid-list-statuses-example", - "description": "Grid List Statuses", - "typescript": "import { Component } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\n@Component({\n selector: 'fd-grid-list-statuses-example',\n templateUrl: './grid-list-statuses-example.component.html',\n styleUrls: ['./grid-list-statuses-example.component.scss'],\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListStatusesExampleComponent {}\n", - "html": "\n \n (4)\n \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n
    \n" - } - ] - }, - { - "name": "GridListFooterComponent", - "selector": "fd-grid-list-footer", - "library": "@fundamental-ngx/core", - "category": "grid-list", - "description": "As with the list and the responsive table, the grid list displays a set of items. In contrast to both controls, the grid list displays the items not in rows, but in a grid. The grid list is usually used as an alternative view for a list or table. It is ideal for displaying images, charts, object cards, and other content, which profit from more height (but less width). The grid list allows for keyboard focus navigation using the arrow keys. In grid lists with multiple selection enabled, holding Shift while pressing an arrow key will move focus and also mark the newly focused grid list item with the previously focused item's selection state. Holding Shift and pressing either the Home or End keys will apply the focused item's selection state to all items to the beginning or the end of the grid list, respectively. Usage Use the grid list if: Your content is “visual” and profits from the rectangular format of the items. This is true for e.g. images, charts, and object cards. The focus is on items, not on cells. The grid list shows complete items. You want to display a homogeneous set of basic data. You need to sort, group, or filter simple data sets. As an alternative view for tables or lists, if the content profits from the different format. Do not use the grid list if: Your content is not appropriate for a card-like format. For example, do not use the grid list for displaying a wall of text. Use a table instead. The main use case is to select one item from a very small number of items, without viewing additional details. In this case, a select or combo box might be more appropriate. Data needs to be structured in a hierarchical manner. In this case, a tree might be more appropriate. You need an overview of a large amount of data. In this case, use a chart. You want to manage complex datasets that need to be extensively sorted, grouped, filtered, or edited. In this case, use a table.", - "inputs": [], - "outputs": [], - "slots": [], - "methods": [], - "cssProperties": [], - "sourceFile": "libs/core/grid-list/components/grid-list-footer/grid-list-footer.component.ts", - "source": "typedoc", - "examples": [ - { - "name": "grid-list-auto-height-example", - "description": "Grid List Auto Height", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\n\n@Component({\n selector: 'fd-grid-list-auto-height-example',\n templateUrl: './grid-list-auto-height-example.component.html',\n styleUrls: ['./grid-list-auto-height-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, ButtonComponent, ContentDensityDirective, AvatarComponent]\n})\nexport class GridListAutoHeightExampleComponent {\n showAlert(message: string): void {\n alert('Clicked on ' + message);\n }\n}\n", - "html": "\n \n items have equal height set by the tallest item.\n \n \n \n \n \n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    California

    \n

    USA

    \n

    www.example.com

    \n
    Copyright
    \n
    \n
    \n\n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n
    \n
    \n\n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n
    \n
    \n\n \n \n

    John Doe

    \n

    Product Owner

    \n
    \n
    \n
    \nSort\nProducts with items\n\n


    \n\n\n \n \n \n \n \n \n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    California

    \n

    USA

    \n

    www.example.com

    \n
    Copyright
    \n
    \n
    \n\n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n
    \n
    \n\n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n

    \n Lorem ipsum dolor, sit amet consectetur adipisicing elit. Libero vitae, excepturi nostrum nam\n voluptatibus nulla quam quidem obcaecati aut quibusdam, perspiciatis molestiae omnis consequatur et,\n labore beatae aliquid magni eveniet?\n

    \n
    \n
    \n\n \n \n

    John Doe

    \n

    Product Owner

    \n
    \n
    \n
    \nSort\nProducts with items\n" - }, - { - "name": "grid-list-combo-select-example", - "description": "Grid List Combo Select", - "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { RouterLink } from '@angular/router';\nimport { FocusableItemDirective } from '@fundamental-ngx/cdk/utils';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n GridListComponent,\n GridListItemOutputEvent,\n GridListItemType,\n GridListModule,\n GridListSelectionEvent\n} from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { SegmentedButtonComponent } from '@fundamental-ngx/core/segmented-button';\n\ninterface GridListItem {\n id: number;\n title: string;\n description: string;\n type?: GridListItemType;\n counter?: number;\n selected?: boolean;\n}\n\n@Component({\n selector: 'fd-grid-list-combo-select-example',\n templateUrl: './grid-list-combo-select-example.component.html',\n styleUrls: ['./grid-list-combo-select-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n ButtonComponent,\n FormsModule,\n FocusableItemDirective,\n SegmentedButtonComponent,\n GridListModule,\n ContentDensityDirective,\n AvatarComponent,\n LinkComponent,\n RouterLink,\n GridListComponent\n ]\n})\nexport class GridListComboSelectComponent {\n @ViewChild(GridListComponent)\n grid: GridListComponent;\n\n selectionMode = 'None';\n\n list: GridListItem[] = [\n {\n id: 1,\n title: 'Title 1',\n description: 'Description 1'\n },\n {\n id: 2,\n title: 'Title 2',\n description: 'Description 2',\n selected: true\n },\n {\n id: 3,\n title: 'Title 3',\n description: 'Description 3',\n type: 'navigation',\n counter: 15\n },\n {\n id: 4,\n title: 'Title 4',\n description: 'Description 4'\n },\n {\n id: 5,\n title: 'Title 5',\n description: 'Description 5'\n },\n {\n id: 6,\n title: 'Title 6',\n description: 'Description 6'\n }\n ];\n\n navigate(): void {\n alert('Navigation event');\n }\n\n showAlert(message: string): void {\n alert('Clicked on ' + message);\n }\n\n onSelectionChange(event: GridListSelectionEvent): void {\n console.log('Multi-Select: selected items', event);\n }\n\n press(event: GridListItemOutputEvent): void {\n console.log('Press event', event);\n }\n\n detail(event: GridListItemOutputEvent): void {\n console.log('Detail event', event);\n }\n\n navigateGrid(event: GridListItemOutputEvent): void {\n alert('Navigation event value is: ' + event.value);\n }\n\n clearSelection(): void {\n this.grid.clearSelection();\n }\n\n delete(event: GridListItemOutputEvent): void {\n if (event.index !== null && event.index !== undefined) {\n this.list.splice(event.index, 1);\n alert('Deleted item event ' + event.value);\n }\n }\n\n onCardClick(): void {\n alert('Card clicked');\n }\n}\n", - "html": "
    \n \n \n \n \n \n \n \n \n
    \n
    \n @switch (selectionMode) {\n @case ('None') {\n \n {{ '(' + list.length + ')' }}\n \n \n \n \n \n \n @for (item of list; track item) {\n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n
    \n }\n @case ('MultiSelect') {\n \n {{ '(' + list.length + ')' }}\n \n \n @for (item of list; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n
    \n

    \n \n }\n @case ('SingleSelect') {\n \n {{ '(' + list.length + ')' }}\n \n \n @for (item of list; track item) {\n \n Custom Text\n\n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n
    \n }\n @case ('SingleSelectLeft') {\n \n {{ '(' + list.length + ')' }}\n \n \n @for (item of list; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n
    \n }\n @case ('SingleSelectRight') {\n \n {{ '(' + list.length + ')' }}\n \n \n @for (item of list; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n
    \n }\n @case ('Delete') {\n \n {{ '(' + list.length + ')' }}\n \n \n @for (item of list; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n @if (!list.length) {\n
    No items available.
    \n }\n
    \n }\n }\n
    \n" - }, - { - "name": "grid-list-dnd-example", - "description": "Grid List Dnd", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { DragAndDropModule, FdDropEvent } from '@fundamental-ngx/cdk/utils';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { GridListItemOutputEvent, GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n id: number;\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-dnd-example',\n templateUrl: './grid-list-dnd-example.component.html',\n styleUrls: ['./grid-list-dnd-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n GridListModule,\n DragAndDropModule,\n ContentDensityDirective,\n ButtonComponent,\n AvatarComponent,\n LinkComponent,\n RouterLink\n ]\n})\nexport class GridListDndExampleComponent {\n list: GridListItem[] = [\n {\n id: 1,\n title: 'Title 1',\n description: 'Description 1'\n },\n {\n id: 2,\n title: 'Title 2',\n description: 'Description 2'\n },\n {\n id: 3,\n title: 'Title 3',\n description: 'Description 3'\n },\n {\n id: 4,\n title: 'Title 4',\n description: 'Description 4'\n },\n {\n id: 5,\n title: 'Title 5',\n description: 'Description 5'\n },\n {\n id: 6,\n title: 'Title 6',\n description: 'Description 6'\n },\n {\n id: 7,\n title: 'Title 7',\n description: 'Description 7'\n }\n ];\n\n itemsChangeHandle(dropEvent: FdDropEvent): void {\n console.log('Drag and drop event: ', dropEvent);\n this.list = dropEvent.items;\n }\n\n showAlert(message: string): void {\n alert('Clicked on ' + message);\n }\n\n navigate(event: GridListItemOutputEvent): void {\n alert('Navigation event value is: ' + event.value);\n }\n}\n", - "html": "\n \n {{ '(' + list.length + ')' }}\n \n \n \n \n \n \n \n @for (item of list; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n Footer Item \n \n }\n
    \nSort\nProducts with {{ list.length }} items
    \n" - }, - { - "name": "grid-list-focusing-example", - "description": "Grid List Focusing", - "typescript": "import { ChangeDetectionStrategy, Component, QueryList, ViewChildren, ViewEncapsulation } from '@angular/core';\n\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n GridListItemComponent,\n GridListItemOutputEvent,\n GridListItemType,\n GridListModule\n} from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n id: number;\n title: string;\n description: string;\n type?: GridListItemType;\n counter?: number;\n}\n\n@Component({\n selector: 'fd-grid-list-focusing-example',\n templateUrl: './grid-list-focusing-example.component.html',\n styleUrls: ['./grid-list-focusing-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, ButtonComponent, ContentDensityDirective, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListFocusingItemExampleComponent {\n @ViewChildren(GridListItemComponent)\n gridListItems: QueryList>;\n\n list: GridListItem[] = [\n {\n id: 1,\n title: 'Title 1',\n description: 'Description 1'\n },\n {\n id: 2,\n title: 'Title 2',\n description: 'Description 2'\n },\n {\n id: 3,\n title: 'Title 3',\n description: 'Description 3',\n type: 'navigation',\n counter: 15\n },\n {\n id: 4,\n title: 'Title 4',\n description: 'Description 4'\n },\n {\n id: 5,\n title: 'Title 5',\n description: 'Description 5'\n },\n {\n id: 6,\n title: 'Title 6',\n description: 'Description 6'\n }\n ];\n\n navigate(event: GridListItemOutputEvent): void {\n alert('Navigation event');\n console.log(event);\n }\n\n showAlert(message: string): void {\n alert('Clicked on ' + message);\n }\n\n focusFirst(): void {\n this.gridListItems.first?.focus();\n }\n\n focusLast(): void {\n this.gridListItems.last?.focus();\n }\n}\n", - "html": "\n \n {{ '(' + list.length + ')' }}\n \n \n \n \n @for (item of list; track item) {\n \n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n
    \n" - }, - { - "name": "grid-list-footer-example", - "description": "Grid List Footer", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-footer-example',\n templateUrl: './grid-list-footer-example.component.html',\n styleUrls: ['./grid-list-footer-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListFooterExampleComponent {\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n}\n", - "html": "\n \n {{ '(' + list.length + ')' }}\n \n @for (item of list; track item; let i = $index) {\n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n }\n Footer\n
    \n" - }, - { - "name": "grid-list-group-example", - "description": "Grid List Group", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n id: number;\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-group-example',\n templateUrl: './grid-list-group-example.component.html',\n styleUrls: ['./grid-list-group-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListGroupExampleComponent {\n group1: GridListItem[] = [\n {\n id: 1,\n title: 'Title 1',\n description: 'Description 1'\n },\n {\n id: 2,\n title: 'Title 2',\n description: 'Description 2'\n },\n {\n id: 3,\n title: 'Title 3',\n description: 'Description 3'\n },\n {\n id: 4,\n title: 'Title 4',\n description: 'Description 4'\n }\n ];\n\n group2: GridListItem[] = [\n {\n id: 5,\n title: 'Title 5',\n description: 'Description 5'\n },\n {\n id: 6,\n title: 'Title 6',\n description: 'Description 6'\n },\n {\n id: 7,\n title: 'Title 7',\n description: 'Description 7'\n }\n ];\n\n showFilterBur = true;\n\n close(): void {\n this.showFilterBur = false;\n }\n}\n", - "html": "\n \n {{ '(' + (group1.length + group2.length) + ')' }}\n \n @if (showFilterBur) {\n \n Grouped by: Company (Company A, Company B)\n \n }\n Company: Company A \n @for (item of group1; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n }\n Company: Company B \n @for (item of group2; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n }\n
    \n" - }, - { - "name": "grid-list-heading-level-example", - "description": "Grid List Heading Level", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\n\n@Component({\n selector: 'fd-grid-list-heading-level-example',\n templateUrl: './grid-list-heading-level-example.component.html',\n styleUrls: ['./grid-list-heading-level-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [GridListModule, AvatarComponent]\n})\nexport class GridListHeadingLevelExampleComponent {\n list = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n}\n", - "html": "\n \n (5)\n \n @for (item of list; track item) {\n \n \n \n }\n\n" - }, - { - "name": "grid-list-layout-example", - "description": "Grid List Layout", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n id: number;\n title: string;\n description: string;\n layoutItemPattern?: string;\n}\n\n@Component({\n selector: 'fd-grid-list-layout-example',\n templateUrl: './grid-list-layout-example.component.html',\n styleUrls: ['./grid-list-layout-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListLayoutExampleComponent {\n layoutPattern = 'XL4-L3-M2-S1';\n\n list: GridListItem[] = [\n {\n id: 1,\n title: 'Title 1',\n description: 'Description 1'\n },\n {\n id: 2,\n title: 'Title 2',\n description: 'Description 2',\n layoutItemPattern: 'XL6-L8-M6-S12'\n },\n {\n id: 3,\n title: 'Title 3',\n description: 'Description 3'\n },\n {\n id: 4,\n title: 'Title 4',\n description: 'Description 4'\n },\n {\n id: 5,\n title: 'Title 5',\n description: 'Description 5'\n },\n {\n id: 6,\n title: 'Title 6',\n description: 'Description 6'\n },\n {\n id: 7,\n title: 'Title 7',\n description: 'Description 7'\n }\n ];\n}\n", - "html": "\n \n {{ '(' + list.length + ')' }}\n \n @for (item of list; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n
    \n" - }, { "name": "grid-list-more-example", "description": "Grid List More", "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-more-example',\n templateUrl: './grid-list-more-example.component.html',\n styleUrls: ['./grid-list-more-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListMoreExampleComponent {\n totalItems = 50;\n\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n showMore(): void {\n if (this.list.length === this.totalItems) {\n return;\n }\n\n const newPart: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n this.list.push(...newPart);\n }\n}\n", "html": "\n \n @for (item of list; track item; let i = $index) {\n \n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n }\n @if (totalItems !== list.length) {\n \n }\n
    \n" }, - { - "name": "grid-list-states-example", - "description": "Grid List States", - "typescript": "import { Component } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListItemOutputEvent, GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\n@Component({\n selector: 'fd-grid-list-states-example',\n templateUrl: './grid-list-states-example.component.html',\n styleUrls: ['./grid-list-states-example.component.scss'],\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListStatesExampleComponent {\n locked(event: GridListItemOutputEvent): void {\n console.log('Locked event', event);\n }\n\n draft(event: GridListItemOutputEvent): void {\n console.log('Draft event', event);\n }\n}\n", - "html": "\n \n (7)\n \n\n State: Unread \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n State: Error \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Custom error message \n
    \n\n State: Locked \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Locked button redefined to text \n
    \n\n State: Draft \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Draft button redefined to text \n
    \n
    \n" - }, { "name": "grid-list-statuses-example", "description": "Grid List Statuses", @@ -36941,24 +36889,17 @@ ] }, { - "name": "GridListGroupHeaderComponent", - "selector": "fd-grid-list-group-header", + "name": "GridListFooterComponent", + "selector": "fd-grid-list-footer", "library": "@fundamental-ngx/core", "category": "grid-list", "description": "As with the list and the responsive table, the grid list displays a set of items. In contrast to both controls, the grid list displays the items not in rows, but in a grid. The grid list is usually used as an alternative view for a list or table. It is ideal for displaying images, charts, object cards, and other content, which profit from more height (but less width). The grid list allows for keyboard focus navigation using the arrow keys. In grid lists with multiple selection enabled, holding Shift while pressing an arrow key will move focus and also mark the newly focused grid list item with the previously focused item's selection state. Holding Shift and pressing either the Home or End keys will apply the focused item's selection state to all items to the beginning or the end of the grid list, respectively. Usage Use the grid list if: Your content is “visual” and profits from the rectangular format of the items. This is true for e.g. images, charts, and object cards. The focus is on items, not on cells. The grid list shows complete items. You want to display a homogeneous set of basic data. You need to sort, group, or filter simple data sets. As an alternative view for tables or lists, if the content profits from the different format. Do not use the grid list if: Your content is not appropriate for a card-like format. For example, do not use the grid list for displaying a wall of text. Use a table instead. The main use case is to select one item from a very small number of items, without viewing additional details. In this case, a select or combo box might be more appropriate. Data needs to be structured in a hierarchical manner. In this case, a tree might be more appropriate. You need an overview of a large amount of data. In this case, use a chart. You want to manage complex datasets that need to be extensively sorted, grouped, filtered, or edited. In this case, use a table.", - "inputs": [ - { - "name": "ariaLabel", - "type": "Nullable", - "description": "Sets the `aria-label` attribute to the element.", - "required": true - } - ], + "inputs": [], "outputs": [], "slots": [], "methods": [], "cssProperties": [], - "sourceFile": "libs/core/grid-list/components/grid-list-group-header/grid-list-group-header.component.ts", + "sourceFile": "libs/core/grid-list/components/grid-list-footer/grid-list-footer.component.ts", "source": "typedoc", "examples": [ { @@ -37009,18 +36950,107 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n id: number;\n title: string;\n description: string;\n layoutItemPattern?: string;\n}\n\n@Component({\n selector: 'fd-grid-list-layout-example',\n templateUrl: './grid-list-layout-example.component.html',\n styleUrls: ['./grid-list-layout-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListLayoutExampleComponent {\n layoutPattern = 'XL4-L3-M2-S1';\n\n list: GridListItem[] = [\n {\n id: 1,\n title: 'Title 1',\n description: 'Description 1'\n },\n {\n id: 2,\n title: 'Title 2',\n description: 'Description 2',\n layoutItemPattern: 'XL6-L8-M6-S12'\n },\n {\n id: 3,\n title: 'Title 3',\n description: 'Description 3'\n },\n {\n id: 4,\n title: 'Title 4',\n description: 'Description 4'\n },\n {\n id: 5,\n title: 'Title 5',\n description: 'Description 5'\n },\n {\n id: 6,\n title: 'Title 6',\n description: 'Description 6'\n },\n {\n id: 7,\n title: 'Title 7',\n description: 'Description 7'\n }\n ];\n}\n", "html": "\n \n {{ '(' + list.length + ')' }}\n \n @for (item of list; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n
    \n" }, + { + "name": "grid-list-states-example", + "description": "Grid List States", + "typescript": "import { Component } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListItemOutputEvent, GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\n@Component({\n selector: 'fd-grid-list-states-example',\n templateUrl: './grid-list-states-example.component.html',\n styleUrls: ['./grid-list-states-example.component.scss'],\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListStatesExampleComponent {\n locked(event: GridListItemOutputEvent): void {\n console.log('Locked event', event);\n }\n\n draft(event: GridListItemOutputEvent): void {\n console.log('Draft event', event);\n }\n}\n", + "html": "\n \n (7)\n \n\n State: Unread \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n State: Error \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Custom error message \n
    \n\n State: Locked \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Locked button redefined to text \n
    \n\n State: Draft \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Draft button redefined to text \n
    \n
    \n" + }, { "name": "grid-list-more-example", "description": "Grid List More", "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-more-example',\n templateUrl: './grid-list-more-example.component.html',\n styleUrls: ['./grid-list-more-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListMoreExampleComponent {\n totalItems = 50;\n\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n showMore(): void {\n if (this.list.length === this.totalItems) {\n return;\n }\n\n const newPart: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n this.list.push(...newPart);\n }\n}\n", "html": "\n \n @for (item of list; track item; let i = $index) {\n \n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n }\n @if (totalItems !== list.length) {\n \n }\n
    \n" }, + { + "name": "grid-list-statuses-example", + "description": "Grid List Statuses", + "typescript": "import { Component } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\n@Component({\n selector: 'fd-grid-list-statuses-example',\n templateUrl: './grid-list-statuses-example.component.html',\n styleUrls: ['./grid-list-statuses-example.component.scss'],\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListStatusesExampleComponent {}\n", + "html": "\n \n (4)\n \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n
    \n" + } + ] + }, + { + "name": "GridListGroupHeaderComponent", + "selector": "fd-grid-list-group-header", + "library": "@fundamental-ngx/core", + "category": "grid-list", + "description": "As with the list and the responsive table, the grid list displays a set of items. In contrast to both controls, the grid list displays the items not in rows, but in a grid. The grid list is usually used as an alternative view for a list or table. It is ideal for displaying images, charts, object cards, and other content, which profit from more height (but less width). The grid list allows for keyboard focus navigation using the arrow keys. In grid lists with multiple selection enabled, holding Shift while pressing an arrow key will move focus and also mark the newly focused grid list item with the previously focused item's selection state. Holding Shift and pressing either the Home or End keys will apply the focused item's selection state to all items to the beginning or the end of the grid list, respectively. Usage Use the grid list if: Your content is “visual” and profits from the rectangular format of the items. This is true for e.g. images, charts, and object cards. The focus is on items, not on cells. The grid list shows complete items. You want to display a homogeneous set of basic data. You need to sort, group, or filter simple data sets. As an alternative view for tables or lists, if the content profits from the different format. Do not use the grid list if: Your content is not appropriate for a card-like format. For example, do not use the grid list for displaying a wall of text. Use a table instead. The main use case is to select one item from a very small number of items, without viewing additional details. In this case, a select or combo box might be more appropriate. Data needs to be structured in a hierarchical manner. In this case, a tree might be more appropriate. You need an overview of a large amount of data. In this case, use a chart. You want to manage complex datasets that need to be extensively sorted, grouped, filtered, or edited. In this case, use a table.", + "inputs": [ + { + "name": "ariaLabel", + "type": "Nullable", + "description": "Sets the `aria-label` attribute to the element.", + "required": true + } + ], + "outputs": [], + "slots": [], + "methods": [], + "cssProperties": [], + "sourceFile": "libs/core/grid-list/components/grid-list-group-header/grid-list-group-header.component.ts", + "source": "typedoc", + "examples": [ + { + "name": "grid-list-auto-height-example", + "description": "Grid List Auto Height", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\n\n@Component({\n selector: 'fd-grid-list-auto-height-example',\n templateUrl: './grid-list-auto-height-example.component.html',\n styleUrls: ['./grid-list-auto-height-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, ButtonComponent, ContentDensityDirective, AvatarComponent]\n})\nexport class GridListAutoHeightExampleComponent {\n showAlert(message: string): void {\n alert('Clicked on ' + message);\n }\n}\n", + "html": "\n \n items have equal height set by the tallest item.\n \n \n \n \n \n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    California

    \n

    USA

    \n

    www.example.com

    \n
    Copyright
    \n
    \n
    \n\n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n
    \n
    \n\n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n
    \n
    \n\n \n \n

    John Doe

    \n

    Product Owner

    \n
    \n
    \n
    \nSort\nProducts with items\n\n


    \n\n\n \n \n \n \n \n \n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    California

    \n

    USA

    \n

    www.example.com

    \n
    Copyright
    \n
    \n
    \n\n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n
    \n
    \n\n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n

    \n Lorem ipsum dolor, sit amet consectetur adipisicing elit. Libero vitae, excepturi nostrum nam\n voluptatibus nulla quam quidem obcaecati aut quibusdam, perspiciatis molestiae omnis consequatur et,\n labore beatae aliquid magni eveniet?\n

    \n
    \n
    \n\n \n \n

    John Doe

    \n

    Product Owner

    \n
    \n
    \n
    \nSort\nProducts with items\n" + }, + { + "name": "grid-list-combo-select-example", + "description": "Grid List Combo Select", + "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { RouterLink } from '@angular/router';\nimport { FocusableItemDirective } from '@fundamental-ngx/cdk/utils';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n GridListComponent,\n GridListItemOutputEvent,\n GridListItemType,\n GridListModule,\n GridListSelectionEvent\n} from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { SegmentedButtonComponent } from '@fundamental-ngx/core/segmented-button';\n\ninterface GridListItem {\n id: number;\n title: string;\n description: string;\n type?: GridListItemType;\n counter?: number;\n selected?: boolean;\n}\n\n@Component({\n selector: 'fd-grid-list-combo-select-example',\n templateUrl: './grid-list-combo-select-example.component.html',\n styleUrls: ['./grid-list-combo-select-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n ButtonComponent,\n FormsModule,\n FocusableItemDirective,\n SegmentedButtonComponent,\n GridListModule,\n ContentDensityDirective,\n AvatarComponent,\n LinkComponent,\n RouterLink,\n GridListComponent\n ]\n})\nexport class GridListComboSelectComponent {\n @ViewChild(GridListComponent)\n grid: GridListComponent;\n\n selectionMode = 'None';\n\n list: GridListItem[] = [\n {\n id: 1,\n title: 'Title 1',\n description: 'Description 1'\n },\n {\n id: 2,\n title: 'Title 2',\n description: 'Description 2',\n selected: true\n },\n {\n id: 3,\n title: 'Title 3',\n description: 'Description 3',\n type: 'navigation',\n counter: 15\n },\n {\n id: 4,\n title: 'Title 4',\n description: 'Description 4'\n },\n {\n id: 5,\n title: 'Title 5',\n description: 'Description 5'\n },\n {\n id: 6,\n title: 'Title 6',\n description: 'Description 6'\n }\n ];\n\n navigate(): void {\n alert('Navigation event');\n }\n\n showAlert(message: string): void {\n alert('Clicked on ' + message);\n }\n\n onSelectionChange(event: GridListSelectionEvent): void {\n console.log('Multi-Select: selected items', event);\n }\n\n press(event: GridListItemOutputEvent): void {\n console.log('Press event', event);\n }\n\n detail(event: GridListItemOutputEvent): void {\n console.log('Detail event', event);\n }\n\n navigateGrid(event: GridListItemOutputEvent): void {\n alert('Navigation event value is: ' + event.value);\n }\n\n clearSelection(): void {\n this.grid.clearSelection();\n }\n\n delete(event: GridListItemOutputEvent): void {\n if (event.index !== null && event.index !== undefined) {\n this.list.splice(event.index, 1);\n alert('Deleted item event ' + event.value);\n }\n }\n\n onCardClick(): void {\n alert('Card clicked');\n }\n}\n", + "html": "
    \n \n \n \n \n \n \n \n \n
    \n
    \n @switch (selectionMode) {\n @case ('None') {\n \n {{ '(' + list.length + ')' }}\n \n \n \n \n \n \n @for (item of list; track item) {\n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n
    \n }\n @case ('MultiSelect') {\n \n {{ '(' + list.length + ')' }}\n \n \n @for (item of list; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n
    \n

    \n \n }\n @case ('SingleSelect') {\n \n {{ '(' + list.length + ')' }}\n \n \n @for (item of list; track item) {\n \n Custom Text\n\n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n
    \n }\n @case ('SingleSelectLeft') {\n \n {{ '(' + list.length + ')' }}\n \n \n @for (item of list; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n
    \n }\n @case ('SingleSelectRight') {\n \n {{ '(' + list.length + ')' }}\n \n \n @for (item of list; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n
    \n }\n @case ('Delete') {\n \n {{ '(' + list.length + ')' }}\n \n \n @for (item of list; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n @if (!list.length) {\n
    No items available.
    \n }\n
    \n }\n }\n
    \n" + }, + { + "name": "grid-list-dnd-example", + "description": "Grid List Dnd", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { DragAndDropModule, FdDropEvent } from '@fundamental-ngx/cdk/utils';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { GridListItemOutputEvent, GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n id: number;\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-dnd-example',\n templateUrl: './grid-list-dnd-example.component.html',\n styleUrls: ['./grid-list-dnd-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n GridListModule,\n DragAndDropModule,\n ContentDensityDirective,\n ButtonComponent,\n AvatarComponent,\n LinkComponent,\n RouterLink\n ]\n})\nexport class GridListDndExampleComponent {\n list: GridListItem[] = [\n {\n id: 1,\n title: 'Title 1',\n description: 'Description 1'\n },\n {\n id: 2,\n title: 'Title 2',\n description: 'Description 2'\n },\n {\n id: 3,\n title: 'Title 3',\n description: 'Description 3'\n },\n {\n id: 4,\n title: 'Title 4',\n description: 'Description 4'\n },\n {\n id: 5,\n title: 'Title 5',\n description: 'Description 5'\n },\n {\n id: 6,\n title: 'Title 6',\n description: 'Description 6'\n },\n {\n id: 7,\n title: 'Title 7',\n description: 'Description 7'\n }\n ];\n\n itemsChangeHandle(dropEvent: FdDropEvent): void {\n console.log('Drag and drop event: ', dropEvent);\n this.list = dropEvent.items;\n }\n\n showAlert(message: string): void {\n alert('Clicked on ' + message);\n }\n\n navigate(event: GridListItemOutputEvent): void {\n alert('Navigation event value is: ' + event.value);\n }\n}\n", + "html": "\n \n {{ '(' + list.length + ')' }}\n \n \n \n \n \n \n \n @for (item of list; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n Footer Item \n \n }\n
    \nSort\nProducts with {{ list.length }} items
    \n" + }, + { + "name": "grid-list-focusing-example", + "description": "Grid List Focusing", + "typescript": "import { ChangeDetectionStrategy, Component, QueryList, ViewChildren, ViewEncapsulation } from '@angular/core';\n\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n GridListItemComponent,\n GridListItemOutputEvent,\n GridListItemType,\n GridListModule\n} from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n id: number;\n title: string;\n description: string;\n type?: GridListItemType;\n counter?: number;\n}\n\n@Component({\n selector: 'fd-grid-list-focusing-example',\n templateUrl: './grid-list-focusing-example.component.html',\n styleUrls: ['./grid-list-focusing-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, ButtonComponent, ContentDensityDirective, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListFocusingItemExampleComponent {\n @ViewChildren(GridListItemComponent)\n gridListItems: QueryList>;\n\n list: GridListItem[] = [\n {\n id: 1,\n title: 'Title 1',\n description: 'Description 1'\n },\n {\n id: 2,\n title: 'Title 2',\n description: 'Description 2'\n },\n {\n id: 3,\n title: 'Title 3',\n description: 'Description 3',\n type: 'navigation',\n counter: 15\n },\n {\n id: 4,\n title: 'Title 4',\n description: 'Description 4'\n },\n {\n id: 5,\n title: 'Title 5',\n description: 'Description 5'\n },\n {\n id: 6,\n title: 'Title 6',\n description: 'Description 6'\n }\n ];\n\n navigate(event: GridListItemOutputEvent): void {\n alert('Navigation event');\n console.log(event);\n }\n\n showAlert(message: string): void {\n alert('Clicked on ' + message);\n }\n\n focusFirst(): void {\n this.gridListItems.first?.focus();\n }\n\n focusLast(): void {\n this.gridListItems.last?.focus();\n }\n}\n", + "html": "\n \n {{ '(' + list.length + ')' }}\n \n \n \n \n @for (item of list; track item) {\n \n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n
    \n" + }, + { + "name": "grid-list-footer-example", + "description": "Grid List Footer", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-footer-example',\n templateUrl: './grid-list-footer-example.component.html',\n styleUrls: ['./grid-list-footer-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListFooterExampleComponent {\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n}\n", + "html": "\n \n {{ '(' + list.length + ')' }}\n \n @for (item of list; track item; let i = $index) {\n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n }\n Footer\n
    \n" + }, + { + "name": "grid-list-group-example", + "description": "Grid List Group", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n id: number;\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-group-example',\n templateUrl: './grid-list-group-example.component.html',\n styleUrls: ['./grid-list-group-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListGroupExampleComponent {\n group1: GridListItem[] = [\n {\n id: 1,\n title: 'Title 1',\n description: 'Description 1'\n },\n {\n id: 2,\n title: 'Title 2',\n description: 'Description 2'\n },\n {\n id: 3,\n title: 'Title 3',\n description: 'Description 3'\n },\n {\n id: 4,\n title: 'Title 4',\n description: 'Description 4'\n }\n ];\n\n group2: GridListItem[] = [\n {\n id: 5,\n title: 'Title 5',\n description: 'Description 5'\n },\n {\n id: 6,\n title: 'Title 6',\n description: 'Description 6'\n },\n {\n id: 7,\n title: 'Title 7',\n description: 'Description 7'\n }\n ];\n\n showFilterBur = true;\n\n close(): void {\n this.showFilterBur = false;\n }\n}\n", + "html": "\n \n {{ '(' + (group1.length + group2.length) + ')' }}\n \n @if (showFilterBur) {\n \n Grouped by: Company (Company A, Company B)\n \n }\n Company: Company A \n @for (item of group1; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n }\n Company: Company B \n @for (item of group2; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n }\n
    \n" + }, + { + "name": "grid-list-heading-level-example", + "description": "Grid List Heading Level", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\n\n@Component({\n selector: 'fd-grid-list-heading-level-example',\n templateUrl: './grid-list-heading-level-example.component.html',\n styleUrls: ['./grid-list-heading-level-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [GridListModule, AvatarComponent]\n})\nexport class GridListHeadingLevelExampleComponent {\n list = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n}\n", + "html": "\n \n (5)\n \n @for (item of list; track item) {\n \n \n \n }\n\n" + }, + { + "name": "grid-list-layout-example", + "description": "Grid List Layout", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n id: number;\n title: string;\n description: string;\n layoutItemPattern?: string;\n}\n\n@Component({\n selector: 'fd-grid-list-layout-example',\n templateUrl: './grid-list-layout-example.component.html',\n styleUrls: ['./grid-list-layout-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListLayoutExampleComponent {\n layoutPattern = 'XL4-L3-M2-S1';\n\n list: GridListItem[] = [\n {\n id: 1,\n title: 'Title 1',\n description: 'Description 1'\n },\n {\n id: 2,\n title: 'Title 2',\n description: 'Description 2',\n layoutItemPattern: 'XL6-L8-M6-S12'\n },\n {\n id: 3,\n title: 'Title 3',\n description: 'Description 3'\n },\n {\n id: 4,\n title: 'Title 4',\n description: 'Description 4'\n },\n {\n id: 5,\n title: 'Title 5',\n description: 'Description 5'\n },\n {\n id: 6,\n title: 'Title 6',\n description: 'Description 6'\n },\n {\n id: 7,\n title: 'Title 7',\n description: 'Description 7'\n }\n ];\n}\n", + "html": "\n \n {{ '(' + list.length + ')' }}\n \n @for (item of list; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n
    \n" + }, { "name": "grid-list-states-example", "description": "Grid List States", "typescript": "import { Component } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListItemOutputEvent, GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\n@Component({\n selector: 'fd-grid-list-states-example',\n templateUrl: './grid-list-states-example.component.html',\n styleUrls: ['./grid-list-states-example.component.scss'],\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListStatesExampleComponent {\n locked(event: GridListItemOutputEvent): void {\n console.log('Locked event', event);\n }\n\n draft(event: GridListItemOutputEvent): void {\n console.log('Draft event', event);\n }\n}\n", "html": "\n \n (7)\n \n\n State: Unread \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n State: Error \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Custom error message \n
    \n\n State: Locked \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Locked button redefined to text \n
    \n\n State: Draft \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Draft button redefined to text \n
    \n
    \n" }, + { + "name": "grid-list-more-example", + "description": "Grid List More", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-more-example',\n templateUrl: './grid-list-more-example.component.html',\n styleUrls: ['./grid-list-more-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListMoreExampleComponent {\n totalItems = 50;\n\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n showMore(): void {\n if (this.list.length === this.totalItems) {\n return;\n }\n\n const newPart: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n this.list.push(...newPart);\n }\n}\n", + "html": "\n \n @for (item of list; track item; let i = $index) {\n \n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n }\n @if (totalItems !== list.length) {\n \n }\n
    \n" + }, { "name": "grid-list-statuses-example", "description": "Grid List Statuses", @@ -37244,18 +37274,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n id: number;\n title: string;\n description: string;\n layoutItemPattern?: string;\n}\n\n@Component({\n selector: 'fd-grid-list-layout-example',\n templateUrl: './grid-list-layout-example.component.html',\n styleUrls: ['./grid-list-layout-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListLayoutExampleComponent {\n layoutPattern = 'XL4-L3-M2-S1';\n\n list: GridListItem[] = [\n {\n id: 1,\n title: 'Title 1',\n description: 'Description 1'\n },\n {\n id: 2,\n title: 'Title 2',\n description: 'Description 2',\n layoutItemPattern: 'XL6-L8-M6-S12'\n },\n {\n id: 3,\n title: 'Title 3',\n description: 'Description 3'\n },\n {\n id: 4,\n title: 'Title 4',\n description: 'Description 4'\n },\n {\n id: 5,\n title: 'Title 5',\n description: 'Description 5'\n },\n {\n id: 6,\n title: 'Title 6',\n description: 'Description 6'\n },\n {\n id: 7,\n title: 'Title 7',\n description: 'Description 7'\n }\n ];\n}\n", "html": "\n \n {{ '(' + list.length + ')' }}\n \n @for (item of list; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n
    \n" }, - { - "name": "grid-list-more-example", - "description": "Grid List More", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-more-example',\n templateUrl: './grid-list-more-example.component.html',\n styleUrls: ['./grid-list-more-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListMoreExampleComponent {\n totalItems = 50;\n\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n showMore(): void {\n if (this.list.length === this.totalItems) {\n return;\n }\n\n const newPart: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n this.list.push(...newPart);\n }\n}\n", - "html": "\n \n @for (item of list; track item; let i = $index) {\n \n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n }\n @if (totalItems !== list.length) {\n \n }\n
    \n" - }, { "name": "grid-list-states-example", "description": "Grid List States", "typescript": "import { Component } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListItemOutputEvent, GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\n@Component({\n selector: 'fd-grid-list-states-example',\n templateUrl: './grid-list-states-example.component.html',\n styleUrls: ['./grid-list-states-example.component.scss'],\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListStatesExampleComponent {\n locked(event: GridListItemOutputEvent): void {\n console.log('Locked event', event);\n }\n\n draft(event: GridListItemOutputEvent): void {\n console.log('Draft event', event);\n }\n}\n", "html": "\n \n (7)\n \n\n State: Unread \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n State: Error \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Custom error message \n
    \n\n State: Locked \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Locked button redefined to text \n
    \n\n State: Draft \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Draft button redefined to text \n
    \n
    \n" }, + { + "name": "grid-list-more-example", + "description": "Grid List More", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-more-example',\n templateUrl: './grid-list-more-example.component.html',\n styleUrls: ['./grid-list-more-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListMoreExampleComponent {\n totalItems = 50;\n\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n showMore(): void {\n if (this.list.length === this.totalItems) {\n return;\n }\n\n const newPart: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n this.list.push(...newPart);\n }\n}\n", + "html": "\n \n @for (item of list; track item; let i = $index) {\n \n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n }\n @if (totalItems !== list.length) {\n \n }\n
    \n" + }, { "name": "grid-list-statuses-example", "description": "Grid List Statuses", @@ -37326,18 +37356,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n id: number;\n title: string;\n description: string;\n layoutItemPattern?: string;\n}\n\n@Component({\n selector: 'fd-grid-list-layout-example',\n templateUrl: './grid-list-layout-example.component.html',\n styleUrls: ['./grid-list-layout-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListLayoutExampleComponent {\n layoutPattern = 'XL4-L3-M2-S1';\n\n list: GridListItem[] = [\n {\n id: 1,\n title: 'Title 1',\n description: 'Description 1'\n },\n {\n id: 2,\n title: 'Title 2',\n description: 'Description 2',\n layoutItemPattern: 'XL6-L8-M6-S12'\n },\n {\n id: 3,\n title: 'Title 3',\n description: 'Description 3'\n },\n {\n id: 4,\n title: 'Title 4',\n description: 'Description 4'\n },\n {\n id: 5,\n title: 'Title 5',\n description: 'Description 5'\n },\n {\n id: 6,\n title: 'Title 6',\n description: 'Description 6'\n },\n {\n id: 7,\n title: 'Title 7',\n description: 'Description 7'\n }\n ];\n}\n", "html": "\n \n {{ '(' + list.length + ')' }}\n \n @for (item of list; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n
    \n" }, - { - "name": "grid-list-more-example", - "description": "Grid List More", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-more-example',\n templateUrl: './grid-list-more-example.component.html',\n styleUrls: ['./grid-list-more-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListMoreExampleComponent {\n totalItems = 50;\n\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n showMore(): void {\n if (this.list.length === this.totalItems) {\n return;\n }\n\n const newPart: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n this.list.push(...newPart);\n }\n}\n", - "html": "\n \n @for (item of list; track item; let i = $index) {\n \n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n }\n @if (totalItems !== list.length) {\n \n }\n
    \n" - }, { "name": "grid-list-states-example", "description": "Grid List States", "typescript": "import { Component } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListItemOutputEvent, GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\n@Component({\n selector: 'fd-grid-list-states-example',\n templateUrl: './grid-list-states-example.component.html',\n styleUrls: ['./grid-list-states-example.component.scss'],\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListStatesExampleComponent {\n locked(event: GridListItemOutputEvent): void {\n console.log('Locked event', event);\n }\n\n draft(event: GridListItemOutputEvent): void {\n console.log('Draft event', event);\n }\n}\n", "html": "\n \n (7)\n \n\n State: Unread \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n State: Error \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Custom error message \n
    \n\n State: Locked \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Locked button redefined to text \n
    \n\n State: Draft \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Draft button redefined to text \n
    \n
    \n" }, + { + "name": "grid-list-more-example", + "description": "Grid List More", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-more-example',\n templateUrl: './grid-list-more-example.component.html',\n styleUrls: ['./grid-list-more-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListMoreExampleComponent {\n totalItems = 50;\n\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n showMore(): void {\n if (this.list.length === this.totalItems) {\n return;\n }\n\n const newPart: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n this.list.push(...newPart);\n }\n}\n", + "html": "\n \n @for (item of list; track item; let i = $index) {\n \n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n }\n @if (totalItems !== list.length) {\n \n }\n
    \n" + }, { "name": "grid-list-statuses-example", "description": "Grid List Statuses", @@ -37408,18 +37438,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n id: number;\n title: string;\n description: string;\n layoutItemPattern?: string;\n}\n\n@Component({\n selector: 'fd-grid-list-layout-example',\n templateUrl: './grid-list-layout-example.component.html',\n styleUrls: ['./grid-list-layout-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListLayoutExampleComponent {\n layoutPattern = 'XL4-L3-M2-S1';\n\n list: GridListItem[] = [\n {\n id: 1,\n title: 'Title 1',\n description: 'Description 1'\n },\n {\n id: 2,\n title: 'Title 2',\n description: 'Description 2',\n layoutItemPattern: 'XL6-L8-M6-S12'\n },\n {\n id: 3,\n title: 'Title 3',\n description: 'Description 3'\n },\n {\n id: 4,\n title: 'Title 4',\n description: 'Description 4'\n },\n {\n id: 5,\n title: 'Title 5',\n description: 'Description 5'\n },\n {\n id: 6,\n title: 'Title 6',\n description: 'Description 6'\n },\n {\n id: 7,\n title: 'Title 7',\n description: 'Description 7'\n }\n ];\n}\n", "html": "\n \n {{ '(' + list.length + ')' }}\n \n @for (item of list; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n
    \n" }, - { - "name": "grid-list-more-example", - "description": "Grid List More", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-more-example',\n templateUrl: './grid-list-more-example.component.html',\n styleUrls: ['./grid-list-more-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListMoreExampleComponent {\n totalItems = 50;\n\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n showMore(): void {\n if (this.list.length === this.totalItems) {\n return;\n }\n\n const newPart: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n this.list.push(...newPart);\n }\n}\n", - "html": "\n \n @for (item of list; track item; let i = $index) {\n \n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n }\n @if (totalItems !== list.length) {\n \n }\n
    \n" - }, { "name": "grid-list-states-example", "description": "Grid List States", "typescript": "import { Component } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListItemOutputEvent, GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\n@Component({\n selector: 'fd-grid-list-states-example',\n templateUrl: './grid-list-states-example.component.html',\n styleUrls: ['./grid-list-states-example.component.scss'],\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListStatesExampleComponent {\n locked(event: GridListItemOutputEvent): void {\n console.log('Locked event', event);\n }\n\n draft(event: GridListItemOutputEvent): void {\n console.log('Draft event', event);\n }\n}\n", "html": "\n \n (7)\n \n\n State: Unread \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n State: Error \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Custom error message \n
    \n\n State: Locked \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Locked button redefined to text \n
    \n\n State: Draft \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Draft button redefined to text \n
    \n
    \n" }, + { + "name": "grid-list-more-example", + "description": "Grid List More", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-more-example',\n templateUrl: './grid-list-more-example.component.html',\n styleUrls: ['./grid-list-more-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListMoreExampleComponent {\n totalItems = 50;\n\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n showMore(): void {\n if (this.list.length === this.totalItems) {\n return;\n }\n\n const newPart: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n this.list.push(...newPart);\n }\n}\n", + "html": "\n \n @for (item of list; track item; let i = $index) {\n \n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n }\n @if (totalItems !== list.length) {\n \n }\n
    \n" + }, { "name": "grid-list-statuses-example", "description": "Grid List Statuses", @@ -37515,18 +37545,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n id: number;\n title: string;\n description: string;\n layoutItemPattern?: string;\n}\n\n@Component({\n selector: 'fd-grid-list-layout-example',\n templateUrl: './grid-list-layout-example.component.html',\n styleUrls: ['./grid-list-layout-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListLayoutExampleComponent {\n layoutPattern = 'XL4-L3-M2-S1';\n\n list: GridListItem[] = [\n {\n id: 1,\n title: 'Title 1',\n description: 'Description 1'\n },\n {\n id: 2,\n title: 'Title 2',\n description: 'Description 2',\n layoutItemPattern: 'XL6-L8-M6-S12'\n },\n {\n id: 3,\n title: 'Title 3',\n description: 'Description 3'\n },\n {\n id: 4,\n title: 'Title 4',\n description: 'Description 4'\n },\n {\n id: 5,\n title: 'Title 5',\n description: 'Description 5'\n },\n {\n id: 6,\n title: 'Title 6',\n description: 'Description 6'\n },\n {\n id: 7,\n title: 'Title 7',\n description: 'Description 7'\n }\n ];\n}\n", "html": "\n \n {{ '(' + list.length + ')' }}\n \n @for (item of list; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n
    \n" }, - { - "name": "grid-list-more-example", - "description": "Grid List More", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-more-example',\n templateUrl: './grid-list-more-example.component.html',\n styleUrls: ['./grid-list-more-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListMoreExampleComponent {\n totalItems = 50;\n\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n showMore(): void {\n if (this.list.length === this.totalItems) {\n return;\n }\n\n const newPart: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n this.list.push(...newPart);\n }\n}\n", - "html": "\n \n @for (item of list; track item; let i = $index) {\n \n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n }\n @if (totalItems !== list.length) {\n \n }\n
    \n" - }, { "name": "grid-list-states-example", "description": "Grid List States", "typescript": "import { Component } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListItemOutputEvent, GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\n@Component({\n selector: 'fd-grid-list-states-example',\n templateUrl: './grid-list-states-example.component.html',\n styleUrls: ['./grid-list-states-example.component.scss'],\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListStatesExampleComponent {\n locked(event: GridListItemOutputEvent): void {\n console.log('Locked event', event);\n }\n\n draft(event: GridListItemOutputEvent): void {\n console.log('Draft event', event);\n }\n}\n", "html": "\n \n (7)\n \n\n State: Unread \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n State: Error \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Custom error message \n
    \n\n State: Locked \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Locked button redefined to text \n
    \n\n State: Draft \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Draft button redefined to text \n
    \n
    \n" }, + { + "name": "grid-list-more-example", + "description": "Grid List More", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-more-example',\n templateUrl: './grid-list-more-example.component.html',\n styleUrls: ['./grid-list-more-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListMoreExampleComponent {\n totalItems = 50;\n\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n showMore(): void {\n if (this.list.length === this.totalItems) {\n return;\n }\n\n const newPart: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n this.list.push(...newPart);\n }\n}\n", + "html": "\n \n @for (item of list; track item; let i = $index) {\n \n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n }\n @if (totalItems !== list.length) {\n \n }\n
    \n" + }, { "name": "grid-list-statuses-example", "description": "Grid List Statuses", @@ -37610,18 +37640,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n id: number;\n title: string;\n description: string;\n layoutItemPattern?: string;\n}\n\n@Component({\n selector: 'fd-grid-list-layout-example',\n templateUrl: './grid-list-layout-example.component.html',\n styleUrls: ['./grid-list-layout-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListLayoutExampleComponent {\n layoutPattern = 'XL4-L3-M2-S1';\n\n list: GridListItem[] = [\n {\n id: 1,\n title: 'Title 1',\n description: 'Description 1'\n },\n {\n id: 2,\n title: 'Title 2',\n description: 'Description 2',\n layoutItemPattern: 'XL6-L8-M6-S12'\n },\n {\n id: 3,\n title: 'Title 3',\n description: 'Description 3'\n },\n {\n id: 4,\n title: 'Title 4',\n description: 'Description 4'\n },\n {\n id: 5,\n title: 'Title 5',\n description: 'Description 5'\n },\n {\n id: 6,\n title: 'Title 6',\n description: 'Description 6'\n },\n {\n id: 7,\n title: 'Title 7',\n description: 'Description 7'\n }\n ];\n}\n", "html": "\n \n {{ '(' + list.length + ')' }}\n \n @for (item of list; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n
    \n" }, - { - "name": "grid-list-more-example", - "description": "Grid List More", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-more-example',\n templateUrl: './grid-list-more-example.component.html',\n styleUrls: ['./grid-list-more-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListMoreExampleComponent {\n totalItems = 50;\n\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n showMore(): void {\n if (this.list.length === this.totalItems) {\n return;\n }\n\n const newPart: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n this.list.push(...newPart);\n }\n}\n", - "html": "\n \n @for (item of list; track item; let i = $index) {\n \n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n }\n @if (totalItems !== list.length) {\n \n }\n
    \n" - }, { "name": "grid-list-states-example", "description": "Grid List States", "typescript": "import { Component } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListItemOutputEvent, GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\n@Component({\n selector: 'fd-grid-list-states-example',\n templateUrl: './grid-list-states-example.component.html',\n styleUrls: ['./grid-list-states-example.component.scss'],\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListStatesExampleComponent {\n locked(event: GridListItemOutputEvent): void {\n console.log('Locked event', event);\n }\n\n draft(event: GridListItemOutputEvent): void {\n console.log('Draft event', event);\n }\n}\n", "html": "\n \n (7)\n \n\n State: Unread \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n State: Error \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Custom error message \n
    \n\n State: Locked \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Locked button redefined to text \n
    \n\n State: Draft \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Draft button redefined to text \n
    \n
    \n" }, + { + "name": "grid-list-more-example", + "description": "Grid List More", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-more-example',\n templateUrl: './grid-list-more-example.component.html',\n styleUrls: ['./grid-list-more-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListMoreExampleComponent {\n totalItems = 50;\n\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n showMore(): void {\n if (this.list.length === this.totalItems) {\n return;\n }\n\n const newPart: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n this.list.push(...newPart);\n }\n}\n", + "html": "\n \n @for (item of list; track item; let i = $index) {\n \n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n }\n @if (totalItems !== list.length) {\n \n }\n
    \n" + }, { "name": "grid-list-statuses-example", "description": "Grid List Statuses", @@ -37714,18 +37744,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n id: number;\n title: string;\n description: string;\n layoutItemPattern?: string;\n}\n\n@Component({\n selector: 'fd-grid-list-layout-example',\n templateUrl: './grid-list-layout-example.component.html',\n styleUrls: ['./grid-list-layout-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListLayoutExampleComponent {\n layoutPattern = 'XL4-L3-M2-S1';\n\n list: GridListItem[] = [\n {\n id: 1,\n title: 'Title 1',\n description: 'Description 1'\n },\n {\n id: 2,\n title: 'Title 2',\n description: 'Description 2',\n layoutItemPattern: 'XL6-L8-M6-S12'\n },\n {\n id: 3,\n title: 'Title 3',\n description: 'Description 3'\n },\n {\n id: 4,\n title: 'Title 4',\n description: 'Description 4'\n },\n {\n id: 5,\n title: 'Title 5',\n description: 'Description 5'\n },\n {\n id: 6,\n title: 'Title 6',\n description: 'Description 6'\n },\n {\n id: 7,\n title: 'Title 7',\n description: 'Description 7'\n }\n ];\n}\n", "html": "\n \n {{ '(' + list.length + ')' }}\n \n @for (item of list; track item) {\n \n Custom Text \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n \n }\n
    \n" }, - { - "name": "grid-list-more-example", - "description": "Grid List More", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-more-example',\n templateUrl: './grid-list-more-example.component.html',\n styleUrls: ['./grid-list-more-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListMoreExampleComponent {\n totalItems = 50;\n\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n showMore(): void {\n if (this.list.length === this.totalItems) {\n return;\n }\n\n const newPart: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n this.list.push(...newPart);\n }\n}\n", - "html": "\n \n @for (item of list; track item; let i = $index) {\n \n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n }\n @if (totalItems !== list.length) {\n \n }\n
    \n" - }, { "name": "grid-list-states-example", "description": "Grid List States", "typescript": "import { Component } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListItemOutputEvent, GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\n@Component({\n selector: 'fd-grid-list-states-example',\n templateUrl: './grid-list-states-example.component.html',\n styleUrls: ['./grid-list-states-example.component.scss'],\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListStatesExampleComponent {\n locked(event: GridListItemOutputEvent): void {\n console.log('Locked event', event);\n }\n\n draft(event: GridListItemOutputEvent): void {\n console.log('Draft event', event);\n }\n}\n", "html": "\n \n (7)\n \n\n State: Unread \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n State: Error \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Custom error message \n
    \n\n State: Locked \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Locked button redefined to text \n
    \n\n State: Draft \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n\n \n Custom Text \n\n \n\n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n\n Draft button redefined to text \n
    \n
    \n" }, + { + "name": "grid-list-more-example", + "description": "Grid List More", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { GridListModule } from '@fundamental-ngx/core/grid-list';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\n\ninterface GridListItem {\n title: string;\n description: string;\n}\n\n@Component({\n selector: 'fd-grid-list-more-example',\n templateUrl: './grid-list-more-example.component.html',\n styleUrls: ['./grid-list-more-example.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [GridListModule, AvatarComponent, LinkComponent, RouterLink]\n})\nexport class GridListMoreExampleComponent {\n totalItems = 50;\n\n list: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n showMore(): void {\n if (this.list.length === this.totalItems) {\n return;\n }\n\n const newPart: GridListItem[] = Array(5).fill({\n title: 'Title',\n description: 'Description'\n });\n\n this.list.push(...newPart);\n }\n}\n", + "html": "\n \n @for (item of list; track item; let i = $index) {\n \n \n \n \n

    781 Main Street

    \n

    Anytown, SD 57401

    \n

    USA

    \n john_li@example.com\n
    \n
    \n }\n @if (totalItems !== list.length) {\n \n }\n
    \n" + }, { "name": "grid-list-statuses-example", "description": "Grid List Statuses", @@ -39156,12 +39186,6 @@ "typescript": "import { Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-message-box-mobile-example',\n templateUrl: './message-box-mobile-example.component.html',\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class MessageBoxMobileExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n\n constructor(private _messageBoxService: MessageBoxService) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content, {\n mobile: true\n });\n }\n}\n", "html": "\n\n{{ title }}\n{{ content }}\n" }, - { - "name": "object-based-message-box-example", - "description": "Object Based Message Box", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-object-based-message-box-example',\n templateUrl: './object-based-message-box-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class ObjectBasedMessageBoxExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n closeReason = '';\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content);\n\n messageBoxRef.afterClosed.subscribe({\n next: (result) => {\n this.closeReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n error: (error) => {\n this.closeReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n });\n }\n}\n", - "html": "\n\n

    {{ closeReason }}

    \n\n{{ title }}\n{{ content }}\n" - }, { "name": "semantic-types-example", "description": "Semantic Types", @@ -39173,6 +39197,12 @@ "description": "Template Based Message Box", "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, TemplateRef } from '@angular/core';\n\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxModule, MessageBoxService } from '@fundamental-ngx/core/message-box';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-template-based-message-box-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './template-based-message-box-example.component.html',\n imports: [MessageBoxModule, TitleComponent, BarModule, InitialFocusDirective, ButtonComponent]\n})\nexport class TemplateBasedMessageBoxExampleComponent {\n confirmationReason: string;\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(messageBox: TemplateRef): void {\n const messageBoxRef = this._messageBoxService.open(messageBox, {\n focusTrapped: true,\n ariaLabelledBy: 'fd-message-box-template-base-header',\n ariaDescribedBy: 'fd-message-box-template-base-body'\n });\n\n messageBoxRef.afterClosed.subscribe(\n (result) => {\n this.confirmationReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.confirmationReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", "html": "\n \n \n \n

    Fruit facts

    \n
    \n \n

    The World's Most Popular Fruit is the tomato.

    \n
    \n \n \n \n \n \n
    \n
    \n\n\n

    {{ confirmationReason }}

    \n" + }, + { + "name": "object-based-message-box-example", + "description": "Object Based Message Box", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-object-based-message-box-example',\n templateUrl: './object-based-message-box-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class ObjectBasedMessageBoxExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n closeReason = '';\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content);\n\n messageBoxRef.afterClosed.subscribe({\n next: (result) => {\n this.closeReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n error: (error) => {\n this.closeReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n });\n }\n}\n", + "html": "\n\n

    {{ closeReason }}

    \n\n{{ title }}\n{{ content }}\n" } ] }, @@ -39222,12 +39252,6 @@ "typescript": "import { Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-message-box-mobile-example',\n templateUrl: './message-box-mobile-example.component.html',\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class MessageBoxMobileExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n\n constructor(private _messageBoxService: MessageBoxService) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content, {\n mobile: true\n });\n }\n}\n", "html": "\n\n{{ title }}\n{{ content }}\n" }, - { - "name": "object-based-message-box-example", - "description": "Object Based Message Box", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-object-based-message-box-example',\n templateUrl: './object-based-message-box-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class ObjectBasedMessageBoxExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n closeReason = '';\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content);\n\n messageBoxRef.afterClosed.subscribe({\n next: (result) => {\n this.closeReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n error: (error) => {\n this.closeReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n });\n }\n}\n", - "html": "\n\n

    {{ closeReason }}

    \n\n{{ title }}\n{{ content }}\n" - }, { "name": "semantic-types-example", "description": "Semantic Types", @@ -39239,6 +39263,12 @@ "description": "Template Based Message Box", "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, TemplateRef } from '@angular/core';\n\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxModule, MessageBoxService } from '@fundamental-ngx/core/message-box';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-template-based-message-box-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './template-based-message-box-example.component.html',\n imports: [MessageBoxModule, TitleComponent, BarModule, InitialFocusDirective, ButtonComponent]\n})\nexport class TemplateBasedMessageBoxExampleComponent {\n confirmationReason: string;\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(messageBox: TemplateRef): void {\n const messageBoxRef = this._messageBoxService.open(messageBox, {\n focusTrapped: true,\n ariaLabelledBy: 'fd-message-box-template-base-header',\n ariaDescribedBy: 'fd-message-box-template-base-body'\n });\n\n messageBoxRef.afterClosed.subscribe(\n (result) => {\n this.confirmationReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.confirmationReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", "html": "\n \n \n \n

    Fruit facts

    \n
    \n \n

    The World's Most Popular Fruit is the tomato.

    \n
    \n \n \n \n \n \n
    \n
    \n\n\n

    {{ confirmationReason }}

    \n" + }, + { + "name": "object-based-message-box-example", + "description": "Object Based Message Box", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-object-based-message-box-example',\n templateUrl: './object-based-message-box-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class ObjectBasedMessageBoxExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n closeReason = '';\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content);\n\n messageBoxRef.afterClosed.subscribe({\n next: (result) => {\n this.closeReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n error: (error) => {\n this.closeReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n });\n }\n}\n", + "html": "\n\n

    {{ closeReason }}

    \n\n{{ title }}\n{{ content }}\n" } ] }, @@ -39301,11 +39331,90 @@ "typescript": "import { Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-message-box-mobile-example',\n templateUrl: './message-box-mobile-example.component.html',\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class MessageBoxMobileExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n\n constructor(private _messageBoxService: MessageBoxService) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content, {\n mobile: true\n });\n }\n}\n", "html": "\n\n{{ title }}\n{{ content }}\n" }, + { + "name": "semantic-types-example", + "description": "Semantic Types", + "typescript": "import { Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxService, MessageBoxType } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-semantic-types-example',\n templateUrl: './semantic-types-example.component.html',\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class SemanticTypesExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n types = '';\n titleId = '';\n contentId = '';\n\n constructor(private _messageBoxService: MessageBoxService) {}\n\n open(type: MessageBoxType, showSemanticIcon: boolean = true, customSemanticIcon?: string): void {\n this.types = `Message box uses the semantic type \"${type}\" ${\n customSemanticIcon ? 'with custom icon' : 'with default icon'\n }`;\n this.titleId = `fd-message-box-semantic-title-${type}`;\n this.contentId = `fd-message-box-semantic-content-${type}`;\n const messageBoxRef = this._messageBoxService.open(\n {\n title: this.title,\n titleId: this.titleId,\n content: this.content,\n contentId: this.contentId,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n },\n {\n type,\n showSemanticIcon,\n customSemanticIcon,\n ariaLabelledBy: this.titleId,\n ariaDescribedBy: this.contentId\n }\n );\n }\n}\n", + "html": "
    \n \n \n \n \n \n \n \n
    \n\n{{ title }}\n{{ content }}\n{{ types }}\n" + }, + { + "name": "template-based-message-box-example", + "description": "Template Based Message Box", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, TemplateRef } from '@angular/core';\n\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxModule, MessageBoxService } from '@fundamental-ngx/core/message-box';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-template-based-message-box-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './template-based-message-box-example.component.html',\n imports: [MessageBoxModule, TitleComponent, BarModule, InitialFocusDirective, ButtonComponent]\n})\nexport class TemplateBasedMessageBoxExampleComponent {\n confirmationReason: string;\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(messageBox: TemplateRef): void {\n const messageBoxRef = this._messageBoxService.open(messageBox, {\n focusTrapped: true,\n ariaLabelledBy: 'fd-message-box-template-base-header',\n ariaDescribedBy: 'fd-message-box-template-base-body'\n });\n\n messageBoxRef.afterClosed.subscribe(\n (result) => {\n this.confirmationReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.confirmationReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", + "html": "\n \n \n \n

    Fruit facts

    \n
    \n \n

    The World's Most Popular Fruit is the tomato.

    \n
    \n \n \n \n \n \n
    \n
    \n\n\n

    {{ confirmationReason }}

    \n" + }, { "name": "object-based-message-box-example", "description": "Object Based Message Box", "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-object-based-message-box-example',\n templateUrl: './object-based-message-box-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class ObjectBasedMessageBoxExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n closeReason = '';\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content);\n\n messageBoxRef.afterClosed.subscribe({\n next: (result) => {\n this.closeReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n error: (error) => {\n this.closeReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n });\n }\n}\n", "html": "\n\n

    {{ closeReason }}

    \n\n{{ title }}\n{{ content }}\n" + } + ] + }, + { + "name": "MessageBoxDefaultComponent", + "selector": "fd-message-box-default", + "library": "@fundamental-ngx/core", + "category": "message-box", + "description": "Message box component used to create the message box in object based approach", + "inputs": [ + { + "name": "_messageBoxConfig", + "type": "MessageBoxConfig", + "description": "", + "required": true + }, + { + "name": "messageBoxContentId", + "type": "string", + "description": "message box content id\nif not set, a default value is provided", + "required": true + }, + { + "name": "messageBoxTitleId", + "type": "string", + "description": "message box title id\nif not set, a default value is provided", + "required": true + } + ], + "outputs": [], + "slots": [], + "methods": [], + "cssProperties": [], + "sourceFile": "libs/core/message-box/message-box-default/message-box-default.component.ts", + "source": "typedoc", + "examples": [ + { + "name": "complex-template-example", + "description": "Complex Template", + "typescript": "import { Component } from '@angular/core';\n\nimport { MessageBoxService } from '@fundamental-ngx/core/message-box';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxComplexExampleComponent } from './message-box-complex-example.component';\n\n@Component({\n selector: 'fd-complex-template-example',\n template: '',\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class ComplexTemplateExampleComponent {\n constructor(private _messageBoxService: MessageBoxService) {}\n\n open(): void {\n this._messageBoxService.open(MessageBoxComplexExampleComponent, {\n width: '400px',\n ariaLabelledBy: 'fd-message-box-complex-template-header fd-message-box-complex-template-header-2',\n ariaDescribedBy: 'fd-message-box-complex-template-body'\n });\n }\n}\n" + }, + { + "name": "message-box-complex-example", + "description": "Message Box Complex", + "typescript": "import { Component } from '@angular/core';\n\nimport { TemplateDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { MessageBoxModule, MessageBoxRef } from '@fundamental-ngx/core/message-box';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-message-box-complex-example',\n template: `\n \n \n \n
    \n \n \n

    Fruit facts

    \n
    \n
    \n
    \n \n Fact 1 of 12\n \n
    \n
    \n
    \n\n \n

    \n The jackfruit has been determined to be the largest tree fruit in the world. The jackfruit can weigh\n as much as 100 pounds. There have been jackfruit that has grown as tall as 4 feet in height!\n

    \n
    \n\n \n \n
    \n \n \n
    \n
    \n
    \n
    \n `,\n imports: [MessageBoxModule, TemplateDirective, BarModule, TitleComponent]\n})\nexport class MessageBoxComplexExampleComponent {\n constructor(public messageBoxRef: MessageBoxRef) {}\n}\n" + }, + { + "name": "component-based-message-box-example", + "description": "Component Based Message Box", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core';\n\nimport { MessageBoxService } from '@fundamental-ngx/core/message-box';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxExampleComponent } from './message-box-example.component';\n\nexport interface TextData {\n title: string;\n text: string;\n}\n\n@Component({\n selector: 'fd-component-based-message-box-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n

    {{ closeReason }}

    \n `,\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class ComponentBasedMessageBoxExampleComponent {\n closeReason: string;\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n const messageBoxRef = this._messageBoxService.open(MessageBoxExampleComponent, {\n data: {\n title: 'Fruit facts',\n text: \"Coffee beans aren't beans. They are fruit pits.\"\n },\n showSemanticIcon: true,\n customSemanticIcon: 'thumb-up',\n width: '400px',\n ariaLabelledBy: 'fd-message-box-component-base-header',\n ariaDescribedBy: 'fd-message-box-component-base-body'\n });\n\n messageBoxRef.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n" + }, + { + "name": "message-box-example", + "description": "Message Box", + "typescript": "import { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { MessageBoxModule, MessageBoxRef } from '@fundamental-ngx/core/message-box';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\nimport { TextData } from './component-based-message-box-example.component';\n\n@Component({\n template: `\n \n \n

    {{ messageBoxRef.data.title }}

    \n
    \n \n

    \n {{ messageBoxRef.data.text }}\n

    \n
    \n \n \n \n \n \n
    \n `,\n imports: [MessageBoxModule, TitleComponent, BarModule]\n})\nexport class MessageBoxExampleComponent {\n constructor(public messageBoxRef: MessageBoxRef) {}\n}\n" + }, + { + "name": "message-box-position-example", + "description": "Message Box Position", + "typescript": "import { Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-message-box-position-example',\n templateUrl: './message-box-position-example.component.html',\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class MessageBoxPositionExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n\n constructor(private _messageBoxService: MessageBoxService) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content, {\n width: '300px',\n position: { top: '25px' }\n });\n }\n}\n", + "html": "\n\n{{ title }}\n{{ content }}\n" + }, + { + "name": "message-box-mobile-example", + "description": "Message Box Mobile", + "typescript": "import { Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-message-box-mobile-example',\n templateUrl: './message-box-mobile-example.component.html',\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class MessageBoxMobileExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n\n constructor(private _messageBoxService: MessageBoxService) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content, {\n mobile: true\n });\n }\n}\n", + "html": "\n\n{{ title }}\n{{ content }}\n" }, { "name": "semantic-types-example", @@ -39318,91 +39427,12 @@ "description": "Template Based Message Box", "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, TemplateRef } from '@angular/core';\n\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxModule, MessageBoxService } from '@fundamental-ngx/core/message-box';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-template-based-message-box-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './template-based-message-box-example.component.html',\n imports: [MessageBoxModule, TitleComponent, BarModule, InitialFocusDirective, ButtonComponent]\n})\nexport class TemplateBasedMessageBoxExampleComponent {\n confirmationReason: string;\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(messageBox: TemplateRef): void {\n const messageBoxRef = this._messageBoxService.open(messageBox, {\n focusTrapped: true,\n ariaLabelledBy: 'fd-message-box-template-base-header',\n ariaDescribedBy: 'fd-message-box-template-base-body'\n });\n\n messageBoxRef.afterClosed.subscribe(\n (result) => {\n this.confirmationReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.confirmationReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", "html": "\n \n \n \n

    Fruit facts

    \n
    \n \n

    The World's Most Popular Fruit is the tomato.

    \n
    \n \n \n \n \n \n
    \n
    \n\n\n

    {{ confirmationReason }}

    \n" - } - ] - }, - { - "name": "MessageBoxDefaultComponent", - "selector": "fd-message-box-default", - "library": "@fundamental-ngx/core", - "category": "message-box", - "description": "Message box component used to create the message box in object based approach", - "inputs": [ - { - "name": "_messageBoxConfig", - "type": "MessageBoxConfig", - "description": "", - "required": true - }, - { - "name": "messageBoxContentId", - "type": "string", - "description": "message box content id\nif not set, a default value is provided", - "required": true - }, - { - "name": "messageBoxTitleId", - "type": "string", - "description": "message box title id\nif not set, a default value is provided", - "required": true - } - ], - "outputs": [], - "slots": [], - "methods": [], - "cssProperties": [], - "sourceFile": "libs/core/message-box/message-box-default/message-box-default.component.ts", - "source": "typedoc", - "examples": [ - { - "name": "complex-template-example", - "description": "Complex Template", - "typescript": "import { Component } from '@angular/core';\n\nimport { MessageBoxService } from '@fundamental-ngx/core/message-box';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxComplexExampleComponent } from './message-box-complex-example.component';\n\n@Component({\n selector: 'fd-complex-template-example',\n template: '',\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class ComplexTemplateExampleComponent {\n constructor(private _messageBoxService: MessageBoxService) {}\n\n open(): void {\n this._messageBoxService.open(MessageBoxComplexExampleComponent, {\n width: '400px',\n ariaLabelledBy: 'fd-message-box-complex-template-header fd-message-box-complex-template-header-2',\n ariaDescribedBy: 'fd-message-box-complex-template-body'\n });\n }\n}\n" - }, - { - "name": "message-box-complex-example", - "description": "Message Box Complex", - "typescript": "import { Component } from '@angular/core';\n\nimport { TemplateDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { MessageBoxModule, MessageBoxRef } from '@fundamental-ngx/core/message-box';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-message-box-complex-example',\n template: `\n \n \n \n
    \n \n \n

    Fruit facts

    \n
    \n
    \n
    \n \n Fact 1 of 12\n \n
    \n
    \n
    \n\n \n

    \n The jackfruit has been determined to be the largest tree fruit in the world. The jackfruit can weigh\n as much as 100 pounds. There have been jackfruit that has grown as tall as 4 feet in height!\n

    \n
    \n\n \n \n
    \n \n \n
    \n
    \n
    \n
    \n `,\n imports: [MessageBoxModule, TemplateDirective, BarModule, TitleComponent]\n})\nexport class MessageBoxComplexExampleComponent {\n constructor(public messageBoxRef: MessageBoxRef) {}\n}\n" - }, - { - "name": "component-based-message-box-example", - "description": "Component Based Message Box", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core';\n\nimport { MessageBoxService } from '@fundamental-ngx/core/message-box';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxExampleComponent } from './message-box-example.component';\n\nexport interface TextData {\n title: string;\n text: string;\n}\n\n@Component({\n selector: 'fd-component-based-message-box-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n

    {{ closeReason }}

    \n `,\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class ComponentBasedMessageBoxExampleComponent {\n closeReason: string;\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n const messageBoxRef = this._messageBoxService.open(MessageBoxExampleComponent, {\n data: {\n title: 'Fruit facts',\n text: \"Coffee beans aren't beans. They are fruit pits.\"\n },\n showSemanticIcon: true,\n customSemanticIcon: 'thumb-up',\n width: '400px',\n ariaLabelledBy: 'fd-message-box-component-base-header',\n ariaDescribedBy: 'fd-message-box-component-base-body'\n });\n\n messageBoxRef.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n" - }, - { - "name": "message-box-example", - "description": "Message Box", - "typescript": "import { Component } from '@angular/core';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { MessageBoxModule, MessageBoxRef } from '@fundamental-ngx/core/message-box';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\nimport { TextData } from './component-based-message-box-example.component';\n\n@Component({\n template: `\n \n \n

    {{ messageBoxRef.data.title }}

    \n
    \n \n

    \n {{ messageBoxRef.data.text }}\n

    \n
    \n \n \n \n \n \n
    \n `,\n imports: [MessageBoxModule, TitleComponent, BarModule]\n})\nexport class MessageBoxExampleComponent {\n constructor(public messageBoxRef: MessageBoxRef) {}\n}\n" - }, - { - "name": "message-box-position-example", - "description": "Message Box Position", - "typescript": "import { Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-message-box-position-example',\n templateUrl: './message-box-position-example.component.html',\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class MessageBoxPositionExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n\n constructor(private _messageBoxService: MessageBoxService) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content, {\n width: '300px',\n position: { top: '25px' }\n });\n }\n}\n", - "html": "\n\n{{ title }}\n{{ content }}\n" - }, - { - "name": "message-box-mobile-example", - "description": "Message Box Mobile", - "typescript": "import { Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-message-box-mobile-example',\n templateUrl: './message-box-mobile-example.component.html',\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class MessageBoxMobileExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n\n constructor(private _messageBoxService: MessageBoxService) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content, {\n mobile: true\n });\n }\n}\n", - "html": "\n\n{{ title }}\n{{ content }}\n" - }, - { - "name": "object-based-message-box-example", - "description": "Object Based Message Box", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-object-based-message-box-example',\n templateUrl: './object-based-message-box-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class ObjectBasedMessageBoxExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n closeReason = '';\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content);\n\n messageBoxRef.afterClosed.subscribe({\n next: (result) => {\n this.closeReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n error: (error) => {\n this.closeReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n });\n }\n}\n", - "html": "\n\n

    {{ closeReason }}

    \n\n{{ title }}\n{{ content }}\n" - }, - { - "name": "semantic-types-example", - "description": "Semantic Types", - "typescript": "import { Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxService, MessageBoxType } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-semantic-types-example',\n templateUrl: './semantic-types-example.component.html',\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class SemanticTypesExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n types = '';\n titleId = '';\n contentId = '';\n\n constructor(private _messageBoxService: MessageBoxService) {}\n\n open(type: MessageBoxType, showSemanticIcon: boolean = true, customSemanticIcon?: string): void {\n this.types = `Message box uses the semantic type \"${type}\" ${\n customSemanticIcon ? 'with custom icon' : 'with default icon'\n }`;\n this.titleId = `fd-message-box-semantic-title-${type}`;\n this.contentId = `fd-message-box-semantic-content-${type}`;\n const messageBoxRef = this._messageBoxService.open(\n {\n title: this.title,\n titleId: this.titleId,\n content: this.content,\n contentId: this.contentId,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n },\n {\n type,\n showSemanticIcon,\n customSemanticIcon,\n ariaLabelledBy: this.titleId,\n ariaDescribedBy: this.contentId\n }\n );\n }\n}\n", - "html": "
    \n \n \n \n \n \n \n \n
    \n\n{{ title }}\n{{ content }}\n{{ types }}\n" - }, - { - "name": "template-based-message-box-example", - "description": "Template Based Message Box", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, TemplateRef } from '@angular/core';\n\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxModule, MessageBoxService } from '@fundamental-ngx/core/message-box';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-template-based-message-box-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './template-based-message-box-example.component.html',\n imports: [MessageBoxModule, TitleComponent, BarModule, InitialFocusDirective, ButtonComponent]\n})\nexport class TemplateBasedMessageBoxExampleComponent {\n confirmationReason: string;\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(messageBox: TemplateRef): void {\n const messageBoxRef = this._messageBoxService.open(messageBox, {\n focusTrapped: true,\n ariaLabelledBy: 'fd-message-box-template-base-header',\n ariaDescribedBy: 'fd-message-box-template-base-body'\n });\n\n messageBoxRef.afterClosed.subscribe(\n (result) => {\n this.confirmationReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.confirmationReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", - "html": "\n \n \n \n

    Fruit facts

    \n
    \n \n

    The World's Most Popular Fruit is the tomato.

    \n
    \n \n \n \n \n \n
    \n
    \n\n\n

    {{ confirmationReason }}

    \n" + }, + { + "name": "object-based-message-box-example", + "description": "Object Based Message Box", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-object-based-message-box-example',\n templateUrl: './object-based-message-box-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class ObjectBasedMessageBoxExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n closeReason = '';\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content);\n\n messageBoxRef.afterClosed.subscribe({\n next: (result) => {\n this.closeReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n error: (error) => {\n this.closeReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n });\n }\n}\n", + "html": "\n\n

    {{ closeReason }}

    \n\n{{ title }}\n{{ content }}\n" } ] }, @@ -39452,12 +39482,6 @@ "typescript": "import { Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-message-box-mobile-example',\n templateUrl: './message-box-mobile-example.component.html',\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class MessageBoxMobileExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n\n constructor(private _messageBoxService: MessageBoxService) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content, {\n mobile: true\n });\n }\n}\n", "html": "\n\n{{ title }}\n{{ content }}\n" }, - { - "name": "object-based-message-box-example", - "description": "Object Based Message Box", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-object-based-message-box-example',\n templateUrl: './object-based-message-box-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class ObjectBasedMessageBoxExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n closeReason = '';\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content);\n\n messageBoxRef.afterClosed.subscribe({\n next: (result) => {\n this.closeReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n error: (error) => {\n this.closeReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n });\n }\n}\n", - "html": "\n\n

    {{ closeReason }}

    \n\n{{ title }}\n{{ content }}\n" - }, { "name": "semantic-types-example", "description": "Semantic Types", @@ -39469,6 +39493,12 @@ "description": "Template Based Message Box", "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, TemplateRef } from '@angular/core';\n\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxModule, MessageBoxService } from '@fundamental-ngx/core/message-box';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-template-based-message-box-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './template-based-message-box-example.component.html',\n imports: [MessageBoxModule, TitleComponent, BarModule, InitialFocusDirective, ButtonComponent]\n})\nexport class TemplateBasedMessageBoxExampleComponent {\n confirmationReason: string;\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(messageBox: TemplateRef): void {\n const messageBoxRef = this._messageBoxService.open(messageBox, {\n focusTrapped: true,\n ariaLabelledBy: 'fd-message-box-template-base-header',\n ariaDescribedBy: 'fd-message-box-template-base-body'\n });\n\n messageBoxRef.afterClosed.subscribe(\n (result) => {\n this.confirmationReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.confirmationReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", "html": "\n \n \n \n

    Fruit facts

    \n
    \n \n

    The World's Most Popular Fruit is the tomato.

    \n
    \n \n \n \n \n \n
    \n
    \n\n\n

    {{ confirmationReason }}

    \n" + }, + { + "name": "object-based-message-box-example", + "description": "Object Based Message Box", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-object-based-message-box-example',\n templateUrl: './object-based-message-box-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class ObjectBasedMessageBoxExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n closeReason = '';\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content);\n\n messageBoxRef.afterClosed.subscribe({\n next: (result) => {\n this.closeReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n error: (error) => {\n this.closeReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n });\n }\n}\n", + "html": "\n\n

    {{ closeReason }}

    \n\n{{ title }}\n{{ content }}\n" } ] }, @@ -39518,12 +39548,6 @@ "typescript": "import { Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-message-box-mobile-example',\n templateUrl: './message-box-mobile-example.component.html',\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class MessageBoxMobileExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n\n constructor(private _messageBoxService: MessageBoxService) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content, {\n mobile: true\n });\n }\n}\n", "html": "\n\n{{ title }}\n{{ content }}\n" }, - { - "name": "object-based-message-box-example", - "description": "Object Based Message Box", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-object-based-message-box-example',\n templateUrl: './object-based-message-box-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class ObjectBasedMessageBoxExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n closeReason = '';\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content);\n\n messageBoxRef.afterClosed.subscribe({\n next: (result) => {\n this.closeReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n error: (error) => {\n this.closeReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n });\n }\n}\n", - "html": "\n\n

    {{ closeReason }}

    \n\n{{ title }}\n{{ content }}\n" - }, { "name": "semantic-types-example", "description": "Semantic Types", @@ -39535,6 +39559,12 @@ "description": "Template Based Message Box", "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, TemplateRef } from '@angular/core';\n\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxModule, MessageBoxService } from '@fundamental-ngx/core/message-box';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-template-based-message-box-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './template-based-message-box-example.component.html',\n imports: [MessageBoxModule, TitleComponent, BarModule, InitialFocusDirective, ButtonComponent]\n})\nexport class TemplateBasedMessageBoxExampleComponent {\n confirmationReason: string;\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(messageBox: TemplateRef): void {\n const messageBoxRef = this._messageBoxService.open(messageBox, {\n focusTrapped: true,\n ariaLabelledBy: 'fd-message-box-template-base-header',\n ariaDescribedBy: 'fd-message-box-template-base-body'\n });\n\n messageBoxRef.afterClosed.subscribe(\n (result) => {\n this.confirmationReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.confirmationReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", "html": "\n \n \n \n

    Fruit facts

    \n
    \n \n

    The World's Most Popular Fruit is the tomato.

    \n
    \n \n \n \n \n \n
    \n
    \n\n\n

    {{ confirmationReason }}

    \n" + }, + { + "name": "object-based-message-box-example", + "description": "Object Based Message Box", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-object-based-message-box-example',\n templateUrl: './object-based-message-box-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class ObjectBasedMessageBoxExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n closeReason = '';\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content);\n\n messageBoxRef.afterClosed.subscribe({\n next: (result) => {\n this.closeReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n error: (error) => {\n this.closeReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n });\n }\n}\n", + "html": "\n\n

    {{ closeReason }}

    \n\n{{ title }}\n{{ content }}\n" } ] }, @@ -39598,12 +39628,6 @@ "typescript": "import { Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-message-box-mobile-example',\n templateUrl: './message-box-mobile-example.component.html',\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class MessageBoxMobileExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n\n constructor(private _messageBoxService: MessageBoxService) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content, {\n mobile: true\n });\n }\n}\n", "html": "\n\n{{ title }}\n{{ content }}\n" }, - { - "name": "object-based-message-box-example", - "description": "Object Based Message Box", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-object-based-message-box-example',\n templateUrl: './object-based-message-box-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class ObjectBasedMessageBoxExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n closeReason = '';\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content);\n\n messageBoxRef.afterClosed.subscribe({\n next: (result) => {\n this.closeReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n error: (error) => {\n this.closeReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n });\n }\n}\n", - "html": "\n\n

    {{ closeReason }}

    \n\n{{ title }}\n{{ content }}\n" - }, { "name": "semantic-types-example", "description": "Semantic Types", @@ -39615,6 +39639,12 @@ "description": "Template Based Message Box", "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, TemplateRef } from '@angular/core';\n\nimport { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxModule, MessageBoxService } from '@fundamental-ngx/core/message-box';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-template-based-message-box-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './template-based-message-box-example.component.html',\n imports: [MessageBoxModule, TitleComponent, BarModule, InitialFocusDirective, ButtonComponent]\n})\nexport class TemplateBasedMessageBoxExampleComponent {\n confirmationReason: string;\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(messageBox: TemplateRef): void {\n const messageBoxRef = this._messageBoxService.open(messageBox, {\n focusTrapped: true,\n ariaLabelledBy: 'fd-message-box-template-base-header',\n ariaDescribedBy: 'fd-message-box-template-base-body'\n });\n\n messageBoxRef.afterClosed.subscribe(\n (result) => {\n this.confirmationReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.confirmationReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n}\n", "html": "\n \n \n \n

    Fruit facts

    \n
    \n \n

    The World's Most Popular Fruit is the tomato.

    \n
    \n \n \n \n \n \n
    \n
    \n\n\n

    {{ confirmationReason }}

    \n" + }, + { + "name": "object-based-message-box-example", + "description": "Object Based Message Box", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core';\n\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { MessageBoxContent, MessageBoxService } from '@fundamental-ngx/core/message-box';\n\n@Component({\n selector: 'fd-object-based-message-box-example',\n templateUrl: './object-based-message-box-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n // The MessageBoxService is already provided on the MessageBoxModule module.\n // We do it at the component level here, due to the limitations of our example generation script.\n MessageBoxService\n ],\n imports: [ButtonComponent]\n})\nexport class ObjectBasedMessageBoxExampleComponent {\n title = 'Fruit facts';\n content = 'Strawberries have more vitamin C than oranges.';\n closeReason = '';\n\n constructor(\n private _messageBoxService: MessageBoxService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n const content: MessageBoxContent = {\n title: this.title,\n content: this.content,\n approveButton: 'Ok',\n cancelButton: 'Cancel',\n approveButtonCallback: () => messageBoxRef.close('Approved'),\n cancelButtonCallback: () => messageBoxRef.close('Canceled'),\n closeButtonCallback: () => messageBoxRef.dismiss('Dismissed')\n };\n\n const messageBoxRef = this._messageBoxService.open(content);\n\n messageBoxRef.afterClosed.subscribe({\n next: (result) => {\n this.closeReason = 'Message box closed with result: ' + result;\n this._cdr.detectChanges();\n },\n error: (error) => {\n this.closeReason = 'Message box dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n });\n }\n}\n", + "html": "\n\n

    {{ closeReason }}

    \n\n{{ title }}\n{{ content }}\n" } ] }, @@ -40597,16 +40627,10 @@ "html": "
    \n \n \n
    \n

    Selected Item: {{ selectedItems | json }}

    \n" }, { - "name": "multi-combobox-datasource-example", - "description": "Multi Combobox Datasource", - "typescript": "import { JsonPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, inject, OnInit } from '@angular/core';\nimport { FormBuilder, ReactiveFormsModule } from '@angular/forms';\nimport { DataSourceDirective, MatchingStrategy } from '@fundamental-ngx/cdk/data-source';\nimport { CvaDirective } from '@fundamental-ngx/cdk/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { FormItemComponent, FormLabelComponent } from '@fundamental-ngx/core/form';\nimport {\n ArrayMultiComboBoxDataSource,\n MultiComboboxComponent,\n MultiComboboxSelectionChangeEvent\n} from '@fundamental-ngx/core/multi-combobox';\nimport { of } from 'rxjs';\n\n@Component({\n selector: 'fd-multi-combobox-datasource-example',\n templateUrl: './multi-combobox-datasource-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n FormItemComponent,\n FormLabelComponent,\n CvaDirective,\n DataSourceDirective,\n MultiComboboxComponent,\n ButtonComponent,\n JsonPipe,\n ReactiveFormsModule\n ]\n})\nexport class MultiComboboxDatasourceExampleComponent implements OnInit {\n isLimitless = true;\n matchingStategy = MatchingStrategy.CONTAINS;\n\n dataSourceStrings = ['Apple', 'Banana', 'Pineapple', 'Strawberry', 'Broccoli', 'Carrot', 'Jalapeño', 'Spinach'];\n\n dataSource = [\n { id: '1', name: 'Apple', type: 'Fruits' },\n { id: '2', name: 'Pineapple', type: 'Fruits' },\n { id: '3', name: 'Strawberry', type: 'Fruits' },\n { id: '4', name: 'Broccoli', type: 'Vegetables' },\n { id: '5', name: 'Carrot', type: 'Vegetables' },\n { id: '6', name: 'Jalapeño', type: 'Vegetables' },\n { id: '7', name: 'Spinach', type: 'Vegetables' },\n { id: '8', name: 'Ukraine', type: 'Countries' },\n { id: '9', name: 'Georgia', type: 'Countries' },\n { id: '10', name: 'Poland', type: 'Countries' },\n { id: '11', name: 'Finland', type: 'Countries' },\n { id: '12', name: 'Denmark', type: 'Countries' },\n { id: '13', name: 'Sweden', type: 'Countries' },\n { id: '14', name: 'Lietuva', type: 'Countries' },\n { id: '15', name: 'Latvia', type: 'Countries' },\n { id: '16', name: 'Spain', type: 'Countries' },\n { id: '17', name: 'Switzerland', type: 'Countries' },\n { id: '18', name: 'USA', type: 'Countries' },\n { id: '19', name: 'Turkey', type: 'Countries' },\n { id: '20', name: 'Italy', type: 'Countries' },\n { id: '21', name: 'Azerbaijan', type: 'Countries' },\n { id: '22', name: 'Germany', type: 'Countries' },\n { id: '23', name: 'Audi', type: 'Cars' },\n { id: '24', name: 'Mercedes', type: 'Cars' },\n { id: '25', name: 'Tesla', type: 'Cars' },\n { id: '26', name: 'Porsche', type: 'Cars' },\n { id: '27', name: 'Toyota', type: 'Cars' },\n { id: '28', name: 'Ford', type: 'Cars' },\n { id: '29', name: 'Grapes', type: 'Fruits' },\n { id: '30', name: 'Watermelon', type: 'Fruits' },\n { id: '31', name: 'Orange', type: 'Fruits' },\n { id: '32', name: 'Cucumber', type: 'Vegetables' },\n { id: '33', name: 'Lettuce', type: 'Vegetables' },\n { id: '34', name: 'Potato', type: 'Vegetables' },\n { id: '35', name: 'Tomato', type: 'Vegetables' },\n { id: '36', name: 'China', type: 'Countries' },\n { id: '37', name: 'Japan', type: 'Countries' },\n { id: '38', name: 'Brazil', type: 'Countries' },\n { id: '39', name: 'Russia', type: 'Countries' },\n { id: '40', name: 'India', type: 'Countries' },\n { id: '41', name: 'Mexico', type: 'Countries' },\n { id: '42', name: 'Egypt', type: 'Countries' },\n { id: '43', name: 'Australia', type: 'Countries' },\n { id: '44', name: 'Netherlands', type: 'Countries' },\n { id: '45', name: 'Belgium', type: 'Countries' },\n { id: '46', name: 'UK', type: 'Countries' },\n { id: '47', name: 'France', type: 'Countries' },\n { id: '48', name: 'South Korea', type: 'Countries' },\n { id: '49', name: 'Malaysia', type: 'Countries' },\n { id: '50', name: 'Singapore', type: 'Countries' },\n { id: '51', name: 'Honda', type: 'Cars' },\n { id: '52', name: 'BMW', type: 'Cars' },\n { id: '53', name: 'Lamborghini', type: 'Cars' },\n { id: '54', name: 'Ferrari', type: 'Cars' },\n { id: '55', name: 'Chevrolet', type: 'Cars' },\n { id: '56', name: 'Mazda', type: 'Cars' },\n { id: '57', name: 'Cherry', type: 'Fruits' },\n { id: '58', name: 'Mango', type: 'Fruits' },\n { id: '59', name: 'Pear', type: 'Fruits' },\n { id: '60', name: 'Avocado', type: 'Fruits' },\n { id: '61', name: 'Cabbage', type: 'Vegetables' },\n { id: '62', name: 'Onion', type: 'Vegetables' },\n { id: '63', name: 'Garlic', type: 'Vegetables' },\n { id: '64', name: 'Pepper', type: 'Vegetables' },\n { id: '65', name: 'Germany', type: 'Countries' },\n { id: '66', name: 'France', type: 'Countries' },\n { id: '67', name: 'Spain', type: 'Countries' },\n { id: '68', name: 'Italy', type: 'Countries' },\n { id: '69', name: 'UK', type: 'Countries' },\n { id: '70', name: 'USA', type: 'Countries' },\n { id: '71', name: 'China', type: 'Countries' },\n { id: '72', name: 'Japan', type: 'Countries' },\n { id: '73', name: 'Brazil', type: 'Countries' },\n { id: '74', name: 'Russia', type: 'Countries' },\n { id: '75', name: 'India', type: 'Countries' },\n { id: '76', name: 'Mexico', type: 'Countries' },\n { id: '77', name: 'Egypt', type: 'Countries' },\n { id: '78', name: 'Australia', type: 'Countries' },\n { id: '79', name: 'Netherlands', type: 'Countries' },\n { id: '80', name: 'Belgium', type: 'Countries' },\n { id: '81', name: 'South Korea', type: 'Countries' },\n { id: '82', name: 'Malaysia', type: 'Countries' },\n { id: '83', name: 'Singapore', type: 'Countries' },\n { id: '84', name: 'Honda', type: 'Cars' },\n { id: '85', name: 'BMW', type: 'Cars' },\n { id: '86', name: 'Lamborghini', type: 'Cars' },\n { id: '87', name: 'Ferrari', type: 'Cars' },\n { id: '88', name: 'Chevrolet', type: 'Cars' },\n { id: '89', name: 'Mazda', type: 'Cars' },\n { id: '90', name: 'Grapes', type: 'Fruits' },\n { id: '91', name: 'Watermelon', type: 'Fruits' },\n { id: '92', name: 'Orange', type: 'Fruits' },\n { id: '93', name: 'Cucumber', type: 'Vegetables' },\n { id: '94', name: 'Lettuce', type: 'Vegetables' },\n { id: '95', name: 'Potato', type: 'Vegetables' },\n { id: '96', name: 'Tomato', type: 'Vegetables' },\n { id: '97', name: 'Ukraine', type: 'Countries' },\n { id: '98', name: 'Georgia', type: 'Countries' },\n { id: '99', name: 'Poland', type: 'Countries' },\n { id: '100', name: 'Finland', type: 'Countries' }\n ];\n dataSourceOf = of(this.dataSource);\n ds = new ArrayMultiComboBoxDataSource(this.dataSource);\n dsl = new ArrayMultiComboBoxDataSource(this.dataSource);\n\n selectedItems1 = [this.dataSourceStrings[1]];\n selectedItems2 = [this.dataSource[1]];\n selectedItems3 = [];\n selectedItems4 = [];\n selectedItems5 = [\n this.dataSourceStrings[1],\n this.dataSourceStrings[2],\n this.dataSourceStrings[3],\n this.dataSourceStrings[4]\n ];\n selectedItems6 = [];\n\n fb = inject(FormBuilder);\n\n formGroup = this.fb.group({ multiGroupComboBox: [[]] }, { updateOn: 'blur' });\n\n ngOnInit(): void {\n this.formGroup.get('multiGroupComboBox')?.valueChanges.subscribe(() => {\n console.log('value change event is triggered now -> ', this.formGroup.get('multiGroupComboBox')?.value);\n });\n }\n\n onSelect1(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems1 = item.selectedItems;\n }\n\n onSelect2(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems2 = item.selectedItems;\n }\n\n onSelect3(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems3 = item.selectedItems;\n }\n\n onSelect4(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems4 = item.selectedItems;\n }\n\n onSelect5(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems5 = item.selectedItems;\n }\n\n onSelect6(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems6 = item.selectedItems;\n }\n}\n", - "html": "
    \n
    \n \n \n
    \n
    \n\n

    Selected: {{ selectedItems1 }}

    \n\n
    \n
    \n\n

    Selected: {{ selectedItems2 | json }}

    \n\n
    \n \n \n
    \n\n

    Selected: {{ selectedItems3 | json }}

    \n\n
    \n \n \n
    \n\n

    Selected: {{ selectedItems4 | json }}

    \n\n
    \n \n \n
    \n\n

    Limitless: {{ isLimitless }}

    \n

    Selected: {{ selectedItems6 | json }}

    \n\n\n
    \n \n \n
    \n

    Selected: {{ selectedItems5 }}

    \n" - }, - { - "name": "multi-combobox-dynamic-datasource-example", - "description": "Multi Combobox Dynamic Datasource", - "typescript": "import { JsonPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { DataSourceDirective } from '@fundamental-ngx/cdk/data-source';\nimport { CvaDirective } from '@fundamental-ngx/cdk/forms';\nimport { FocusableItemDirective } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { FormItemComponent, FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { MultiComboboxComponent, MultiComboboxSelectionChangeEvent } from '@fundamental-ngx/core/multi-combobox';\nimport { SegmentedButtonComponent } from '@fundamental-ngx/core/segmented-button';\n\ninterface ExampleItem {\n name: string;\n type: string;\n}\n\nconst DATASETS: Record = {\n fruits: [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Grapes', type: 'Fruits' },\n { name: 'Orange', type: 'Fruits' }\n ],\n vegetables: [\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' },\n { name: 'Potato', type: 'Vegetables' },\n { name: 'Tomato', type: 'Vegetables' }\n ]\n};\n\n@Component({\n selector: 'fd-multi-combobox-dynamic-datasource-example',\n templateUrl: './multi-combobox-dynamic-datasource-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n FormItemComponent,\n FormLabelComponent,\n FormsModule,\n CvaDirective,\n DataSourceDirective,\n MultiComboboxComponent,\n SegmentedButtonComponent,\n ButtonComponent,\n FocusableItemDirective,\n JsonPipe\n ]\n})\nexport class MultiComboboxDynamicDatasourceExampleComponent {\n dataSource = signal([]);\n selectedItems: ExampleItem[] = [];\n activeDataset = signal('');\n\n constructor() {\n // Simulate async data load (e.g. HTTP request)\n setTimeout(() => {\n this.dataSource.set(DATASETS['fruits']);\n this.activeDataset.set('fruits');\n }, 500);\n }\n\n switchDataset(key: string): void {\n this.dataSource.set(DATASETS[key]);\n this.activeDataset.set(key);\n this.selectedItems = [];\n }\n\n onSelect(event: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems = event.selectedItems;\n }\n}\n", - "html": "

    Active dataset: {{ activeDataset() || 'loading...' }}

    \n\n\n \n \n\n\n

    \n\n
    \n \n \n
    \n\n

    Selected: {{ selectedItems | json }}

    \n" + "name": "multi-combobox-group-example", + "description": "Multi Combobox Group", + "typescript": "import { JsonPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, inject, OnInit } from '@angular/core';\nimport { FormBuilder, ReactiveFormsModule } from '@angular/forms';\nimport { DataSourceDirective } from '@fundamental-ngx/cdk/data-source';\nimport { CvaDirective } from '@fundamental-ngx/cdk/forms';\nimport { FormItemComponent, FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { MultiComboboxComponent, MultiComboboxSelectionChangeEvent } from '@fundamental-ngx/core/multi-combobox';\n\n@Component({\n selector: 'fd-multi-combobox-group-example',\n templateUrl: './multi-combobox-group-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n FormItemComponent,\n FormLabelComponent,\n CvaDirective,\n DataSourceDirective,\n MultiComboboxComponent,\n JsonPipe,\n ReactiveFormsModule\n ]\n})\nexport class MultiComboboxGroupExampleComponent implements OnInit {\n dataSource = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n ];\n\n selectedItems = [this.dataSource[1]];\n selectedItems1 = [];\n\n fb = inject(FormBuilder);\n\n formGroup = this.fb.group({ multiGroupComboBox: [[]] }, { updateOn: 'blur' });\n\n ngOnInit(): void {\n this.formGroup.get('multiGroupComboBox')?.valueChanges.subscribe(() => {\n console.log('value change event is triggered now -> ', this.formGroup.get('multiGroupComboBox')?.value);\n });\n }\n\n onSelect(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems = item.selectedItems;\n }\n\n onSelect1(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems1 = item.selectedItems;\n }\n}\n", + "html": "
    \n
    \n \n \n
    \n

    Selected: {{ selectedItems | json }}

    \n
    \n\n
    \n \n \n
    \n\n

    Selected: {{ selectedItems1 | json }}

    \n" }, { "name": "multi-combobox-forms-example", @@ -40615,10 +40639,16 @@ "html": "
    \n
    \n \n \n
    \n

    Selected Item: {{ selectedItems | json }}

    \n

    Form Selected Item: {{ customForm.getRawValue() | json }}

    \n

    Dirty: {{ customForm.controls.field.dirty }}

    \n

    Touched: {{ customForm.controls.field.touched }}

    \n

    Pristine: {{ customForm.controls.field.pristine }}

    \n
    \n" }, { - "name": "multi-combobox-group-example", - "description": "Multi Combobox Group", - "typescript": "import { JsonPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, inject, OnInit } from '@angular/core';\nimport { FormBuilder, ReactiveFormsModule } from '@angular/forms';\nimport { DataSourceDirective } from '@fundamental-ngx/cdk/data-source';\nimport { CvaDirective } from '@fundamental-ngx/cdk/forms';\nimport { FormItemComponent, FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { MultiComboboxComponent, MultiComboboxSelectionChangeEvent } from '@fundamental-ngx/core/multi-combobox';\n\n@Component({\n selector: 'fd-multi-combobox-group-example',\n templateUrl: './multi-combobox-group-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n FormItemComponent,\n FormLabelComponent,\n CvaDirective,\n DataSourceDirective,\n MultiComboboxComponent,\n JsonPipe,\n ReactiveFormsModule\n ]\n})\nexport class MultiComboboxGroupExampleComponent implements OnInit {\n dataSource = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n ];\n\n selectedItems = [this.dataSource[1]];\n selectedItems1 = [];\n\n fb = inject(FormBuilder);\n\n formGroup = this.fb.group({ multiGroupComboBox: [[]] }, { updateOn: 'blur' });\n\n ngOnInit(): void {\n this.formGroup.get('multiGroupComboBox')?.valueChanges.subscribe(() => {\n console.log('value change event is triggered now -> ', this.formGroup.get('multiGroupComboBox')?.value);\n });\n }\n\n onSelect(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems = item.selectedItems;\n }\n\n onSelect1(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems1 = item.selectedItems;\n }\n}\n", - "html": "
    \n
    \n \n \n
    \n

    Selected: {{ selectedItems | json }}

    \n
    \n\n
    \n \n \n
    \n\n

    Selected: {{ selectedItems1 | json }}

    \n" + "name": "multi-combobox-dynamic-datasource-example", + "description": "Multi Combobox Dynamic Datasource", + "typescript": "import { JsonPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { DataSourceDirective } from '@fundamental-ngx/cdk/data-source';\nimport { CvaDirective } from '@fundamental-ngx/cdk/forms';\nimport { FocusableItemDirective } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { FormItemComponent, FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { MultiComboboxComponent, MultiComboboxSelectionChangeEvent } from '@fundamental-ngx/core/multi-combobox';\nimport { SegmentedButtonComponent } from '@fundamental-ngx/core/segmented-button';\n\ninterface ExampleItem {\n name: string;\n type: string;\n}\n\nconst DATASETS: Record = {\n fruits: [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Grapes', type: 'Fruits' },\n { name: 'Orange', type: 'Fruits' }\n ],\n vegetables: [\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' },\n { name: 'Potato', type: 'Vegetables' },\n { name: 'Tomato', type: 'Vegetables' }\n ]\n};\n\n@Component({\n selector: 'fd-multi-combobox-dynamic-datasource-example',\n templateUrl: './multi-combobox-dynamic-datasource-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n FormItemComponent,\n FormLabelComponent,\n FormsModule,\n CvaDirective,\n DataSourceDirective,\n MultiComboboxComponent,\n SegmentedButtonComponent,\n ButtonComponent,\n FocusableItemDirective,\n JsonPipe\n ]\n})\nexport class MultiComboboxDynamicDatasourceExampleComponent {\n dataSource = signal([]);\n selectedItems: ExampleItem[] = [];\n activeDataset = signal('');\n\n constructor() {\n // Simulate async data load (e.g. HTTP request)\n setTimeout(() => {\n this.dataSource.set(DATASETS['fruits']);\n this.activeDataset.set('fruits');\n }, 500);\n }\n\n switchDataset(key: string): void {\n this.dataSource.set(DATASETS[key]);\n this.activeDataset.set(key);\n this.selectedItems = [];\n }\n\n onSelect(event: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems = event.selectedItems;\n }\n}\n", + "html": "

    Active dataset: {{ activeDataset() || 'loading...' }}

    \n\n\n \n \n\n\n

    \n\n
    \n \n \n
    \n\n

    Selected: {{ selectedItems | json }}

    \n" + }, + { + "name": "multi-combobox-datasource-example", + "description": "Multi Combobox Datasource", + "typescript": "import { JsonPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, inject, OnInit } from '@angular/core';\nimport { FormBuilder, ReactiveFormsModule } from '@angular/forms';\nimport { DataSourceDirective, MatchingStrategy } from '@fundamental-ngx/cdk/data-source';\nimport { CvaDirective } from '@fundamental-ngx/cdk/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { FormItemComponent, FormLabelComponent } from '@fundamental-ngx/core/form';\nimport {\n ArrayMultiComboBoxDataSource,\n MultiComboboxComponent,\n MultiComboboxSelectionChangeEvent\n} from '@fundamental-ngx/core/multi-combobox';\nimport { of } from 'rxjs';\n\n@Component({\n selector: 'fd-multi-combobox-datasource-example',\n templateUrl: './multi-combobox-datasource-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n FormItemComponent,\n FormLabelComponent,\n CvaDirective,\n DataSourceDirective,\n MultiComboboxComponent,\n ButtonComponent,\n JsonPipe,\n ReactiveFormsModule\n ]\n})\nexport class MultiComboboxDatasourceExampleComponent implements OnInit {\n isLimitless = true;\n matchingStategy = MatchingStrategy.CONTAINS;\n\n dataSourceStrings = ['Apple', 'Banana', 'Pineapple', 'Strawberry', 'Broccoli', 'Carrot', 'Jalapeño', 'Spinach'];\n\n dataSource = [\n { id: '1', name: 'Apple', type: 'Fruits' },\n { id: '2', name: 'Pineapple', type: 'Fruits' },\n { id: '3', name: 'Strawberry', type: 'Fruits' },\n { id: '4', name: 'Broccoli', type: 'Vegetables' },\n { id: '5', name: 'Carrot', type: 'Vegetables' },\n { id: '6', name: 'Jalapeño', type: 'Vegetables' },\n { id: '7', name: 'Spinach', type: 'Vegetables' },\n { id: '8', name: 'Ukraine', type: 'Countries' },\n { id: '9', name: 'Georgia', type: 'Countries' },\n { id: '10', name: 'Poland', type: 'Countries' },\n { id: '11', name: 'Finland', type: 'Countries' },\n { id: '12', name: 'Denmark', type: 'Countries' },\n { id: '13', name: 'Sweden', type: 'Countries' },\n { id: '14', name: 'Lietuva', type: 'Countries' },\n { id: '15', name: 'Latvia', type: 'Countries' },\n { id: '16', name: 'Spain', type: 'Countries' },\n { id: '17', name: 'Switzerland', type: 'Countries' },\n { id: '18', name: 'USA', type: 'Countries' },\n { id: '19', name: 'Turkey', type: 'Countries' },\n { id: '20', name: 'Italy', type: 'Countries' },\n { id: '21', name: 'Azerbaijan', type: 'Countries' },\n { id: '22', name: 'Germany', type: 'Countries' },\n { id: '23', name: 'Audi', type: 'Cars' },\n { id: '24', name: 'Mercedes', type: 'Cars' },\n { id: '25', name: 'Tesla', type: 'Cars' },\n { id: '26', name: 'Porsche', type: 'Cars' },\n { id: '27', name: 'Toyota', type: 'Cars' },\n { id: '28', name: 'Ford', type: 'Cars' },\n { id: '29', name: 'Grapes', type: 'Fruits' },\n { id: '30', name: 'Watermelon', type: 'Fruits' },\n { id: '31', name: 'Orange', type: 'Fruits' },\n { id: '32', name: 'Cucumber', type: 'Vegetables' },\n { id: '33', name: 'Lettuce', type: 'Vegetables' },\n { id: '34', name: 'Potato', type: 'Vegetables' },\n { id: '35', name: 'Tomato', type: 'Vegetables' },\n { id: '36', name: 'China', type: 'Countries' },\n { id: '37', name: 'Japan', type: 'Countries' },\n { id: '38', name: 'Brazil', type: 'Countries' },\n { id: '39', name: 'Russia', type: 'Countries' },\n { id: '40', name: 'India', type: 'Countries' },\n { id: '41', name: 'Mexico', type: 'Countries' },\n { id: '42', name: 'Egypt', type: 'Countries' },\n { id: '43', name: 'Australia', type: 'Countries' },\n { id: '44', name: 'Netherlands', type: 'Countries' },\n { id: '45', name: 'Belgium', type: 'Countries' },\n { id: '46', name: 'UK', type: 'Countries' },\n { id: '47', name: 'France', type: 'Countries' },\n { id: '48', name: 'South Korea', type: 'Countries' },\n { id: '49', name: 'Malaysia', type: 'Countries' },\n { id: '50', name: 'Singapore', type: 'Countries' },\n { id: '51', name: 'Honda', type: 'Cars' },\n { id: '52', name: 'BMW', type: 'Cars' },\n { id: '53', name: 'Lamborghini', type: 'Cars' },\n { id: '54', name: 'Ferrari', type: 'Cars' },\n { id: '55', name: 'Chevrolet', type: 'Cars' },\n { id: '56', name: 'Mazda', type: 'Cars' },\n { id: '57', name: 'Cherry', type: 'Fruits' },\n { id: '58', name: 'Mango', type: 'Fruits' },\n { id: '59', name: 'Pear', type: 'Fruits' },\n { id: '60', name: 'Avocado', type: 'Fruits' },\n { id: '61', name: 'Cabbage', type: 'Vegetables' },\n { id: '62', name: 'Onion', type: 'Vegetables' },\n { id: '63', name: 'Garlic', type: 'Vegetables' },\n { id: '64', name: 'Pepper', type: 'Vegetables' },\n { id: '65', name: 'Germany', type: 'Countries' },\n { id: '66', name: 'France', type: 'Countries' },\n { id: '67', name: 'Spain', type: 'Countries' },\n { id: '68', name: 'Italy', type: 'Countries' },\n { id: '69', name: 'UK', type: 'Countries' },\n { id: '70', name: 'USA', type: 'Countries' },\n { id: '71', name: 'China', type: 'Countries' },\n { id: '72', name: 'Japan', type: 'Countries' },\n { id: '73', name: 'Brazil', type: 'Countries' },\n { id: '74', name: 'Russia', type: 'Countries' },\n { id: '75', name: 'India', type: 'Countries' },\n { id: '76', name: 'Mexico', type: 'Countries' },\n { id: '77', name: 'Egypt', type: 'Countries' },\n { id: '78', name: 'Australia', type: 'Countries' },\n { id: '79', name: 'Netherlands', type: 'Countries' },\n { id: '80', name: 'Belgium', type: 'Countries' },\n { id: '81', name: 'South Korea', type: 'Countries' },\n { id: '82', name: 'Malaysia', type: 'Countries' },\n { id: '83', name: 'Singapore', type: 'Countries' },\n { id: '84', name: 'Honda', type: 'Cars' },\n { id: '85', name: 'BMW', type: 'Cars' },\n { id: '86', name: 'Lamborghini', type: 'Cars' },\n { id: '87', name: 'Ferrari', type: 'Cars' },\n { id: '88', name: 'Chevrolet', type: 'Cars' },\n { id: '89', name: 'Mazda', type: 'Cars' },\n { id: '90', name: 'Grapes', type: 'Fruits' },\n { id: '91', name: 'Watermelon', type: 'Fruits' },\n { id: '92', name: 'Orange', type: 'Fruits' },\n { id: '93', name: 'Cucumber', type: 'Vegetables' },\n { id: '94', name: 'Lettuce', type: 'Vegetables' },\n { id: '95', name: 'Potato', type: 'Vegetables' },\n { id: '96', name: 'Tomato', type: 'Vegetables' },\n { id: '97', name: 'Ukraine', type: 'Countries' },\n { id: '98', name: 'Georgia', type: 'Countries' },\n { id: '99', name: 'Poland', type: 'Countries' },\n { id: '100', name: 'Finland', type: 'Countries' }\n ];\n dataSourceOf = of(this.dataSource);\n ds = new ArrayMultiComboBoxDataSource(this.dataSource);\n dsl = new ArrayMultiComboBoxDataSource(this.dataSource);\n\n selectedItems1 = [this.dataSourceStrings[1]];\n selectedItems2 = [this.dataSource[1]];\n selectedItems3 = [];\n selectedItems4 = [];\n selectedItems5 = [\n this.dataSourceStrings[1],\n this.dataSourceStrings[2],\n this.dataSourceStrings[3],\n this.dataSourceStrings[4]\n ];\n selectedItems6 = [];\n\n fb = inject(FormBuilder);\n\n formGroup = this.fb.group({ multiGroupComboBox: [[]] }, { updateOn: 'blur' });\n\n ngOnInit(): void {\n this.formGroup.get('multiGroupComboBox')?.valueChanges.subscribe(() => {\n console.log('value change event is triggered now -> ', this.formGroup.get('multiGroupComboBox')?.value);\n });\n }\n\n onSelect1(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems1 = item.selectedItems;\n }\n\n onSelect2(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems2 = item.selectedItems;\n }\n\n onSelect3(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems3 = item.selectedItems;\n }\n\n onSelect4(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems4 = item.selectedItems;\n }\n\n onSelect5(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems5 = item.selectedItems;\n }\n\n onSelect6(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems6 = item.selectedItems;\n }\n}\n", + "html": "
    \n
    \n \n \n
    \n
    \n\n

    Selected: {{ selectedItems1 }}

    \n\n
    \n
    \n\n

    Selected: {{ selectedItems2 | json }}

    \n\n
    \n \n \n
    \n\n

    Selected: {{ selectedItems3 | json }}

    \n\n
    \n \n \n
    \n\n

    Selected: {{ selectedItems4 | json }}

    \n\n
    \n \n \n
    \n\n

    Limitless: {{ isLimitless }}

    \n

    Selected: {{ selectedItems6 | json }}

    \n\n\n
    \n \n \n
    \n

    Selected: {{ selectedItems5 }}

    \n" }, { "name": "multi-combobox-inside-dialog-example", @@ -40626,18 +40656,18 @@ "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, TemplateRef } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport {\n ButtonBarComponent,\n ListComponent,\n ListItemComponent,\n MultiComboboxComponent,\n MultiComboboxSelectionChangeEvent\n} from '@fundamental-ngx/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\n\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService,\n DialogTemplateDirective\n} from '@fundamental-ngx/core/dialog';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-multi-combobox-inside-dialog-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './multi-combobox-inside-dialog-example.component.html',\n imports: [\n TitleComponent,\n DialogTemplateDirective,\n DialogFooterComponent,\n ButtonComponent,\n DialogComponent,\n ButtonBarComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n FormsModule,\n MultiComboboxComponent,\n ListComponent,\n ListItemComponent\n ]\n})\nexport class MultiComboboxInsideDialogExampleComponent {\n dataSourceStrings = ['Apple', 'Banana', 'Pineapple', 'Strawberry', 'Broccoli', 'Carrot', 'Jalapeño', 'Spinach'];\n selectedItems = [this.dataSourceStrings[1]];\n confirmationReason: string;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openDialog(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n width: '550px',\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result: string) => {\n this.confirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error: string) => {\n this.confirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n onSelect(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems = item.selectedItems;\n }\n}\n", "html": "\n \n \n

    Multi Combobox in a dialog

    \n
    \n\n \n
    \n \n \n
    \n

    Selected Items:

    \n
      \n @for (item of selectedItems; track $index) {\n
    • \n {{ item }}\n
    • \n }\n
    \n
    \n\n \n \n\n \n \n
    \n
    \n\n\n

    {{ confirmationReason }}

    \n" }, - { - "name": "multi-combobox-loading-example", - "description": "Multi Combobox Loading", - "typescript": "import { JsonPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { DataProvider, DataSourceDirective } from '@fundamental-ngx/cdk/data-source';\nimport { CvaDirective } from '@fundamental-ngx/cdk/forms';\nimport { BusyIndicatorComponent } from '@fundamental-ngx/core/busy-indicator';\nimport {\n FdMultiComboBoxDataSource,\n MultiComboboxComponent,\n MultiComboboxSelectionChangeEvent\n} from '@fundamental-ngx/core/multi-combobox';\nimport { Observable } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\nconst OPTIONS = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n];\n\n@Component({\n selector: 'fd-multi-combobox-loading-example',\n templateUrl: './multi-combobox-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [BusyIndicatorComponent, CvaDirective, DataSourceDirective, MultiComboboxComponent, JsonPipe]\n})\nexport class MultiComboboxLoadingExampleComponent {\n dataSource = new FdMultiComboBoxDataSource(new DelayedDataProvider(OPTIONS));\n\n selectedItems = [];\n loading = false;\n\n onSelect(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems = item.selectedItems;\n }\n\n dataRequested(): void {\n this.loading = true;\n }\n dataReceived(): void {\n this.loading = false;\n }\n}\n\n// Simulating real http request by adding 300ms delay to the DataProvider's \"fetch\" method\nclass DelayedDataProvider extends DataProvider {\n fetch(params: Map): Observable {\n return super.fetch(params).pipe(delay(300));\n }\n}\n", - "html": "\n \n\n\n

    Selected: {{ selectedItems | json }}

    \n" - }, { "name": "multi-combobox-mobile-example", "description": "Multi Combobox Mobile", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { JsonPipe } from '@angular/common';\nimport { DataSourceDirective } from '@fundamental-ngx/cdk/data-source';\nimport { CvaDirective } from '@fundamental-ngx/cdk/forms';\nimport { FormItemComponent, FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { MobileModeConfig } from '@fundamental-ngx/core/mobile-mode';\nimport { MultiComboboxComponent, MultiComboboxSelectionChangeEvent } from '@fundamental-ngx/core/multi-combobox';\n\n@Component({\n selector: 'fd-multi-combobox-mobile-example',\n templateUrl: './multi-combobox-mobile-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n FormItemComponent,\n FormLabelComponent,\n CvaDirective,\n DataSourceDirective,\n MultiComboboxComponent,\n JsonPipe\n ]\n})\nexport class MultiComboboxMobileExampleComponent {\n dataSource = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n ];\n\n selectedItems = [];\n\n mobileConfig: MobileModeConfig = {\n title: 'Title',\n approveButtonText: 'Save',\n cancelButtonText: 'Cancel',\n hasCloseButton: true\n };\n\n onSelect(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems = item.selectedItems;\n }\n}\n", "html": "

    Mobile Mode Combobox:

    \n\n
    \n \n \n
    \n

    Selected: {{ selectedItems | json }}

    \n" }, + { + "name": "multi-combobox-loading-example", + "description": "Multi Combobox Loading", + "typescript": "import { JsonPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { DataProvider, DataSourceDirective } from '@fundamental-ngx/cdk/data-source';\nimport { CvaDirective } from '@fundamental-ngx/cdk/forms';\nimport { BusyIndicatorComponent } from '@fundamental-ngx/core/busy-indicator';\nimport {\n FdMultiComboBoxDataSource,\n MultiComboboxComponent,\n MultiComboboxSelectionChangeEvent\n} from '@fundamental-ngx/core/multi-combobox';\nimport { Observable } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\nconst OPTIONS = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n];\n\n@Component({\n selector: 'fd-multi-combobox-loading-example',\n templateUrl: './multi-combobox-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [BusyIndicatorComponent, CvaDirective, DataSourceDirective, MultiComboboxComponent, JsonPipe]\n})\nexport class MultiComboboxLoadingExampleComponent {\n dataSource = new FdMultiComboBoxDataSource(new DelayedDataProvider(OPTIONS));\n\n selectedItems = [];\n loading = false;\n\n onSelect(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems = item.selectedItems;\n }\n\n dataRequested(): void {\n this.loading = true;\n }\n dataReceived(): void {\n this.loading = false;\n }\n}\n\n// Simulating real http request by adding 300ms delay to the DataProvider's \"fetch\" method\nclass DelayedDataProvider extends DataProvider {\n fetch(params: Map): Observable {\n return super.fetch(params).pipe(delay(300));\n }\n}\n", + "html": "\n \n\n\n

    Selected: {{ selectedItems | json }}

    \n" + }, { "name": "multi-combobox-states-example", "description": "Multi Combobox States", @@ -40686,16 +40716,10 @@ "html": "
    \n \n \n
    \n

    Selected Item: {{ selectedItems | json }}

    \n" }, { - "name": "multi-combobox-datasource-example", - "description": "Multi Combobox Datasource", - "typescript": "import { JsonPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, inject, OnInit } from '@angular/core';\nimport { FormBuilder, ReactiveFormsModule } from '@angular/forms';\nimport { DataSourceDirective, MatchingStrategy } from '@fundamental-ngx/cdk/data-source';\nimport { CvaDirective } from '@fundamental-ngx/cdk/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { FormItemComponent, FormLabelComponent } from '@fundamental-ngx/core/form';\nimport {\n ArrayMultiComboBoxDataSource,\n MultiComboboxComponent,\n MultiComboboxSelectionChangeEvent\n} from '@fundamental-ngx/core/multi-combobox';\nimport { of } from 'rxjs';\n\n@Component({\n selector: 'fd-multi-combobox-datasource-example',\n templateUrl: './multi-combobox-datasource-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n FormItemComponent,\n FormLabelComponent,\n CvaDirective,\n DataSourceDirective,\n MultiComboboxComponent,\n ButtonComponent,\n JsonPipe,\n ReactiveFormsModule\n ]\n})\nexport class MultiComboboxDatasourceExampleComponent implements OnInit {\n isLimitless = true;\n matchingStategy = MatchingStrategy.CONTAINS;\n\n dataSourceStrings = ['Apple', 'Banana', 'Pineapple', 'Strawberry', 'Broccoli', 'Carrot', 'Jalapeño', 'Spinach'];\n\n dataSource = [\n { id: '1', name: 'Apple', type: 'Fruits' },\n { id: '2', name: 'Pineapple', type: 'Fruits' },\n { id: '3', name: 'Strawberry', type: 'Fruits' },\n { id: '4', name: 'Broccoli', type: 'Vegetables' },\n { id: '5', name: 'Carrot', type: 'Vegetables' },\n { id: '6', name: 'Jalapeño', type: 'Vegetables' },\n { id: '7', name: 'Spinach', type: 'Vegetables' },\n { id: '8', name: 'Ukraine', type: 'Countries' },\n { id: '9', name: 'Georgia', type: 'Countries' },\n { id: '10', name: 'Poland', type: 'Countries' },\n { id: '11', name: 'Finland', type: 'Countries' },\n { id: '12', name: 'Denmark', type: 'Countries' },\n { id: '13', name: 'Sweden', type: 'Countries' },\n { id: '14', name: 'Lietuva', type: 'Countries' },\n { id: '15', name: 'Latvia', type: 'Countries' },\n { id: '16', name: 'Spain', type: 'Countries' },\n { id: '17', name: 'Switzerland', type: 'Countries' },\n { id: '18', name: 'USA', type: 'Countries' },\n { id: '19', name: 'Turkey', type: 'Countries' },\n { id: '20', name: 'Italy', type: 'Countries' },\n { id: '21', name: 'Azerbaijan', type: 'Countries' },\n { id: '22', name: 'Germany', type: 'Countries' },\n { id: '23', name: 'Audi', type: 'Cars' },\n { id: '24', name: 'Mercedes', type: 'Cars' },\n { id: '25', name: 'Tesla', type: 'Cars' },\n { id: '26', name: 'Porsche', type: 'Cars' },\n { id: '27', name: 'Toyota', type: 'Cars' },\n { id: '28', name: 'Ford', type: 'Cars' },\n { id: '29', name: 'Grapes', type: 'Fruits' },\n { id: '30', name: 'Watermelon', type: 'Fruits' },\n { id: '31', name: 'Orange', type: 'Fruits' },\n { id: '32', name: 'Cucumber', type: 'Vegetables' },\n { id: '33', name: 'Lettuce', type: 'Vegetables' },\n { id: '34', name: 'Potato', type: 'Vegetables' },\n { id: '35', name: 'Tomato', type: 'Vegetables' },\n { id: '36', name: 'China', type: 'Countries' },\n { id: '37', name: 'Japan', type: 'Countries' },\n { id: '38', name: 'Brazil', type: 'Countries' },\n { id: '39', name: 'Russia', type: 'Countries' },\n { id: '40', name: 'India', type: 'Countries' },\n { id: '41', name: 'Mexico', type: 'Countries' },\n { id: '42', name: 'Egypt', type: 'Countries' },\n { id: '43', name: 'Australia', type: 'Countries' },\n { id: '44', name: 'Netherlands', type: 'Countries' },\n { id: '45', name: 'Belgium', type: 'Countries' },\n { id: '46', name: 'UK', type: 'Countries' },\n { id: '47', name: 'France', type: 'Countries' },\n { id: '48', name: 'South Korea', type: 'Countries' },\n { id: '49', name: 'Malaysia', type: 'Countries' },\n { id: '50', name: 'Singapore', type: 'Countries' },\n { id: '51', name: 'Honda', type: 'Cars' },\n { id: '52', name: 'BMW', type: 'Cars' },\n { id: '53', name: 'Lamborghini', type: 'Cars' },\n { id: '54', name: 'Ferrari', type: 'Cars' },\n { id: '55', name: 'Chevrolet', type: 'Cars' },\n { id: '56', name: 'Mazda', type: 'Cars' },\n { id: '57', name: 'Cherry', type: 'Fruits' },\n { id: '58', name: 'Mango', type: 'Fruits' },\n { id: '59', name: 'Pear', type: 'Fruits' },\n { id: '60', name: 'Avocado', type: 'Fruits' },\n { id: '61', name: 'Cabbage', type: 'Vegetables' },\n { id: '62', name: 'Onion', type: 'Vegetables' },\n { id: '63', name: 'Garlic', type: 'Vegetables' },\n { id: '64', name: 'Pepper', type: 'Vegetables' },\n { id: '65', name: 'Germany', type: 'Countries' },\n { id: '66', name: 'France', type: 'Countries' },\n { id: '67', name: 'Spain', type: 'Countries' },\n { id: '68', name: 'Italy', type: 'Countries' },\n { id: '69', name: 'UK', type: 'Countries' },\n { id: '70', name: 'USA', type: 'Countries' },\n { id: '71', name: 'China', type: 'Countries' },\n { id: '72', name: 'Japan', type: 'Countries' },\n { id: '73', name: 'Brazil', type: 'Countries' },\n { id: '74', name: 'Russia', type: 'Countries' },\n { id: '75', name: 'India', type: 'Countries' },\n { id: '76', name: 'Mexico', type: 'Countries' },\n { id: '77', name: 'Egypt', type: 'Countries' },\n { id: '78', name: 'Australia', type: 'Countries' },\n { id: '79', name: 'Netherlands', type: 'Countries' },\n { id: '80', name: 'Belgium', type: 'Countries' },\n { id: '81', name: 'South Korea', type: 'Countries' },\n { id: '82', name: 'Malaysia', type: 'Countries' },\n { id: '83', name: 'Singapore', type: 'Countries' },\n { id: '84', name: 'Honda', type: 'Cars' },\n { id: '85', name: 'BMW', type: 'Cars' },\n { id: '86', name: 'Lamborghini', type: 'Cars' },\n { id: '87', name: 'Ferrari', type: 'Cars' },\n { id: '88', name: 'Chevrolet', type: 'Cars' },\n { id: '89', name: 'Mazda', type: 'Cars' },\n { id: '90', name: 'Grapes', type: 'Fruits' },\n { id: '91', name: 'Watermelon', type: 'Fruits' },\n { id: '92', name: 'Orange', type: 'Fruits' },\n { id: '93', name: 'Cucumber', type: 'Vegetables' },\n { id: '94', name: 'Lettuce', type: 'Vegetables' },\n { id: '95', name: 'Potato', type: 'Vegetables' },\n { id: '96', name: 'Tomato', type: 'Vegetables' },\n { id: '97', name: 'Ukraine', type: 'Countries' },\n { id: '98', name: 'Georgia', type: 'Countries' },\n { id: '99', name: 'Poland', type: 'Countries' },\n { id: '100', name: 'Finland', type: 'Countries' }\n ];\n dataSourceOf = of(this.dataSource);\n ds = new ArrayMultiComboBoxDataSource(this.dataSource);\n dsl = new ArrayMultiComboBoxDataSource(this.dataSource);\n\n selectedItems1 = [this.dataSourceStrings[1]];\n selectedItems2 = [this.dataSource[1]];\n selectedItems3 = [];\n selectedItems4 = [];\n selectedItems5 = [\n this.dataSourceStrings[1],\n this.dataSourceStrings[2],\n this.dataSourceStrings[3],\n this.dataSourceStrings[4]\n ];\n selectedItems6 = [];\n\n fb = inject(FormBuilder);\n\n formGroup = this.fb.group({ multiGroupComboBox: [[]] }, { updateOn: 'blur' });\n\n ngOnInit(): void {\n this.formGroup.get('multiGroupComboBox')?.valueChanges.subscribe(() => {\n console.log('value change event is triggered now -> ', this.formGroup.get('multiGroupComboBox')?.value);\n });\n }\n\n onSelect1(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems1 = item.selectedItems;\n }\n\n onSelect2(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems2 = item.selectedItems;\n }\n\n onSelect3(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems3 = item.selectedItems;\n }\n\n onSelect4(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems4 = item.selectedItems;\n }\n\n onSelect5(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems5 = item.selectedItems;\n }\n\n onSelect6(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems6 = item.selectedItems;\n }\n}\n", - "html": "
    \n
    \n \n \n
    \n
    \n\n

    Selected: {{ selectedItems1 }}

    \n\n
    \n
    \n\n

    Selected: {{ selectedItems2 | json }}

    \n\n
    \n \n \n
    \n\n

    Selected: {{ selectedItems3 | json }}

    \n\n
    \n \n \n
    \n\n

    Selected: {{ selectedItems4 | json }}

    \n\n
    \n \n \n
    \n\n

    Limitless: {{ isLimitless }}

    \n

    Selected: {{ selectedItems6 | json }}

    \n\n\n
    \n \n \n
    \n

    Selected: {{ selectedItems5 }}

    \n" - }, - { - "name": "multi-combobox-dynamic-datasource-example", - "description": "Multi Combobox Dynamic Datasource", - "typescript": "import { JsonPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { DataSourceDirective } from '@fundamental-ngx/cdk/data-source';\nimport { CvaDirective } from '@fundamental-ngx/cdk/forms';\nimport { FocusableItemDirective } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { FormItemComponent, FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { MultiComboboxComponent, MultiComboboxSelectionChangeEvent } from '@fundamental-ngx/core/multi-combobox';\nimport { SegmentedButtonComponent } from '@fundamental-ngx/core/segmented-button';\n\ninterface ExampleItem {\n name: string;\n type: string;\n}\n\nconst DATASETS: Record = {\n fruits: [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Grapes', type: 'Fruits' },\n { name: 'Orange', type: 'Fruits' }\n ],\n vegetables: [\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' },\n { name: 'Potato', type: 'Vegetables' },\n { name: 'Tomato', type: 'Vegetables' }\n ]\n};\n\n@Component({\n selector: 'fd-multi-combobox-dynamic-datasource-example',\n templateUrl: './multi-combobox-dynamic-datasource-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n FormItemComponent,\n FormLabelComponent,\n FormsModule,\n CvaDirective,\n DataSourceDirective,\n MultiComboboxComponent,\n SegmentedButtonComponent,\n ButtonComponent,\n FocusableItemDirective,\n JsonPipe\n ]\n})\nexport class MultiComboboxDynamicDatasourceExampleComponent {\n dataSource = signal([]);\n selectedItems: ExampleItem[] = [];\n activeDataset = signal('');\n\n constructor() {\n // Simulate async data load (e.g. HTTP request)\n setTimeout(() => {\n this.dataSource.set(DATASETS['fruits']);\n this.activeDataset.set('fruits');\n }, 500);\n }\n\n switchDataset(key: string): void {\n this.dataSource.set(DATASETS[key]);\n this.activeDataset.set(key);\n this.selectedItems = [];\n }\n\n onSelect(event: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems = event.selectedItems;\n }\n}\n", - "html": "

    Active dataset: {{ activeDataset() || 'loading...' }}

    \n\n\n \n \n\n\n

    \n\n
    \n \n \n
    \n\n

    Selected: {{ selectedItems | json }}

    \n" + "name": "multi-combobox-group-example", + "description": "Multi Combobox Group", + "typescript": "import { JsonPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, inject, OnInit } from '@angular/core';\nimport { FormBuilder, ReactiveFormsModule } from '@angular/forms';\nimport { DataSourceDirective } from '@fundamental-ngx/cdk/data-source';\nimport { CvaDirective } from '@fundamental-ngx/cdk/forms';\nimport { FormItemComponent, FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { MultiComboboxComponent, MultiComboboxSelectionChangeEvent } from '@fundamental-ngx/core/multi-combobox';\n\n@Component({\n selector: 'fd-multi-combobox-group-example',\n templateUrl: './multi-combobox-group-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n FormItemComponent,\n FormLabelComponent,\n CvaDirective,\n DataSourceDirective,\n MultiComboboxComponent,\n JsonPipe,\n ReactiveFormsModule\n ]\n})\nexport class MultiComboboxGroupExampleComponent implements OnInit {\n dataSource = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n ];\n\n selectedItems = [this.dataSource[1]];\n selectedItems1 = [];\n\n fb = inject(FormBuilder);\n\n formGroup = this.fb.group({ multiGroupComboBox: [[]] }, { updateOn: 'blur' });\n\n ngOnInit(): void {\n this.formGroup.get('multiGroupComboBox')?.valueChanges.subscribe(() => {\n console.log('value change event is triggered now -> ', this.formGroup.get('multiGroupComboBox')?.value);\n });\n }\n\n onSelect(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems = item.selectedItems;\n }\n\n onSelect1(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems1 = item.selectedItems;\n }\n}\n", + "html": "
    \n
    \n \n \n
    \n

    Selected: {{ selectedItems | json }}

    \n
    \n\n
    \n \n \n
    \n\n

    Selected: {{ selectedItems1 | json }}

    \n" }, { "name": "multi-combobox-forms-example", @@ -40704,10 +40728,16 @@ "html": "
    \n
    \n \n \n
    \n

    Selected Item: {{ selectedItems | json }}

    \n

    Form Selected Item: {{ customForm.getRawValue() | json }}

    \n

    Dirty: {{ customForm.controls.field.dirty }}

    \n

    Touched: {{ customForm.controls.field.touched }}

    \n

    Pristine: {{ customForm.controls.field.pristine }}

    \n
    \n" }, { - "name": "multi-combobox-group-example", - "description": "Multi Combobox Group", - "typescript": "import { JsonPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, inject, OnInit } from '@angular/core';\nimport { FormBuilder, ReactiveFormsModule } from '@angular/forms';\nimport { DataSourceDirective } from '@fundamental-ngx/cdk/data-source';\nimport { CvaDirective } from '@fundamental-ngx/cdk/forms';\nimport { FormItemComponent, FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { MultiComboboxComponent, MultiComboboxSelectionChangeEvent } from '@fundamental-ngx/core/multi-combobox';\n\n@Component({\n selector: 'fd-multi-combobox-group-example',\n templateUrl: './multi-combobox-group-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n FormItemComponent,\n FormLabelComponent,\n CvaDirective,\n DataSourceDirective,\n MultiComboboxComponent,\n JsonPipe,\n ReactiveFormsModule\n ]\n})\nexport class MultiComboboxGroupExampleComponent implements OnInit {\n dataSource = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n ];\n\n selectedItems = [this.dataSource[1]];\n selectedItems1 = [];\n\n fb = inject(FormBuilder);\n\n formGroup = this.fb.group({ multiGroupComboBox: [[]] }, { updateOn: 'blur' });\n\n ngOnInit(): void {\n this.formGroup.get('multiGroupComboBox')?.valueChanges.subscribe(() => {\n console.log('value change event is triggered now -> ', this.formGroup.get('multiGroupComboBox')?.value);\n });\n }\n\n onSelect(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems = item.selectedItems;\n }\n\n onSelect1(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems1 = item.selectedItems;\n }\n}\n", - "html": "
    \n
    \n \n \n
    \n

    Selected: {{ selectedItems | json }}

    \n
    \n\n
    \n \n \n
    \n\n

    Selected: {{ selectedItems1 | json }}

    \n" + "name": "multi-combobox-dynamic-datasource-example", + "description": "Multi Combobox Dynamic Datasource", + "typescript": "import { JsonPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { DataSourceDirective } from '@fundamental-ngx/cdk/data-source';\nimport { CvaDirective } from '@fundamental-ngx/cdk/forms';\nimport { FocusableItemDirective } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { FormItemComponent, FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { MultiComboboxComponent, MultiComboboxSelectionChangeEvent } from '@fundamental-ngx/core/multi-combobox';\nimport { SegmentedButtonComponent } from '@fundamental-ngx/core/segmented-button';\n\ninterface ExampleItem {\n name: string;\n type: string;\n}\n\nconst DATASETS: Record = {\n fruits: [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Grapes', type: 'Fruits' },\n { name: 'Orange', type: 'Fruits' }\n ],\n vegetables: [\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' },\n { name: 'Potato', type: 'Vegetables' },\n { name: 'Tomato', type: 'Vegetables' }\n ]\n};\n\n@Component({\n selector: 'fd-multi-combobox-dynamic-datasource-example',\n templateUrl: './multi-combobox-dynamic-datasource-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n FormItemComponent,\n FormLabelComponent,\n FormsModule,\n CvaDirective,\n DataSourceDirective,\n MultiComboboxComponent,\n SegmentedButtonComponent,\n ButtonComponent,\n FocusableItemDirective,\n JsonPipe\n ]\n})\nexport class MultiComboboxDynamicDatasourceExampleComponent {\n dataSource = signal([]);\n selectedItems: ExampleItem[] = [];\n activeDataset = signal('');\n\n constructor() {\n // Simulate async data load (e.g. HTTP request)\n setTimeout(() => {\n this.dataSource.set(DATASETS['fruits']);\n this.activeDataset.set('fruits');\n }, 500);\n }\n\n switchDataset(key: string): void {\n this.dataSource.set(DATASETS[key]);\n this.activeDataset.set(key);\n this.selectedItems = [];\n }\n\n onSelect(event: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems = event.selectedItems;\n }\n}\n", + "html": "

    Active dataset: {{ activeDataset() || 'loading...' }}

    \n\n\n \n \n\n\n

    \n\n
    \n \n \n
    \n\n

    Selected: {{ selectedItems | json }}

    \n" + }, + { + "name": "multi-combobox-datasource-example", + "description": "Multi Combobox Datasource", + "typescript": "import { JsonPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, inject, OnInit } from '@angular/core';\nimport { FormBuilder, ReactiveFormsModule } from '@angular/forms';\nimport { DataSourceDirective, MatchingStrategy } from '@fundamental-ngx/cdk/data-source';\nimport { CvaDirective } from '@fundamental-ngx/cdk/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { FormItemComponent, FormLabelComponent } from '@fundamental-ngx/core/form';\nimport {\n ArrayMultiComboBoxDataSource,\n MultiComboboxComponent,\n MultiComboboxSelectionChangeEvent\n} from '@fundamental-ngx/core/multi-combobox';\nimport { of } from 'rxjs';\n\n@Component({\n selector: 'fd-multi-combobox-datasource-example',\n templateUrl: './multi-combobox-datasource-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n FormItemComponent,\n FormLabelComponent,\n CvaDirective,\n DataSourceDirective,\n MultiComboboxComponent,\n ButtonComponent,\n JsonPipe,\n ReactiveFormsModule\n ]\n})\nexport class MultiComboboxDatasourceExampleComponent implements OnInit {\n isLimitless = true;\n matchingStategy = MatchingStrategy.CONTAINS;\n\n dataSourceStrings = ['Apple', 'Banana', 'Pineapple', 'Strawberry', 'Broccoli', 'Carrot', 'Jalapeño', 'Spinach'];\n\n dataSource = [\n { id: '1', name: 'Apple', type: 'Fruits' },\n { id: '2', name: 'Pineapple', type: 'Fruits' },\n { id: '3', name: 'Strawberry', type: 'Fruits' },\n { id: '4', name: 'Broccoli', type: 'Vegetables' },\n { id: '5', name: 'Carrot', type: 'Vegetables' },\n { id: '6', name: 'Jalapeño', type: 'Vegetables' },\n { id: '7', name: 'Spinach', type: 'Vegetables' },\n { id: '8', name: 'Ukraine', type: 'Countries' },\n { id: '9', name: 'Georgia', type: 'Countries' },\n { id: '10', name: 'Poland', type: 'Countries' },\n { id: '11', name: 'Finland', type: 'Countries' },\n { id: '12', name: 'Denmark', type: 'Countries' },\n { id: '13', name: 'Sweden', type: 'Countries' },\n { id: '14', name: 'Lietuva', type: 'Countries' },\n { id: '15', name: 'Latvia', type: 'Countries' },\n { id: '16', name: 'Spain', type: 'Countries' },\n { id: '17', name: 'Switzerland', type: 'Countries' },\n { id: '18', name: 'USA', type: 'Countries' },\n { id: '19', name: 'Turkey', type: 'Countries' },\n { id: '20', name: 'Italy', type: 'Countries' },\n { id: '21', name: 'Azerbaijan', type: 'Countries' },\n { id: '22', name: 'Germany', type: 'Countries' },\n { id: '23', name: 'Audi', type: 'Cars' },\n { id: '24', name: 'Mercedes', type: 'Cars' },\n { id: '25', name: 'Tesla', type: 'Cars' },\n { id: '26', name: 'Porsche', type: 'Cars' },\n { id: '27', name: 'Toyota', type: 'Cars' },\n { id: '28', name: 'Ford', type: 'Cars' },\n { id: '29', name: 'Grapes', type: 'Fruits' },\n { id: '30', name: 'Watermelon', type: 'Fruits' },\n { id: '31', name: 'Orange', type: 'Fruits' },\n { id: '32', name: 'Cucumber', type: 'Vegetables' },\n { id: '33', name: 'Lettuce', type: 'Vegetables' },\n { id: '34', name: 'Potato', type: 'Vegetables' },\n { id: '35', name: 'Tomato', type: 'Vegetables' },\n { id: '36', name: 'China', type: 'Countries' },\n { id: '37', name: 'Japan', type: 'Countries' },\n { id: '38', name: 'Brazil', type: 'Countries' },\n { id: '39', name: 'Russia', type: 'Countries' },\n { id: '40', name: 'India', type: 'Countries' },\n { id: '41', name: 'Mexico', type: 'Countries' },\n { id: '42', name: 'Egypt', type: 'Countries' },\n { id: '43', name: 'Australia', type: 'Countries' },\n { id: '44', name: 'Netherlands', type: 'Countries' },\n { id: '45', name: 'Belgium', type: 'Countries' },\n { id: '46', name: 'UK', type: 'Countries' },\n { id: '47', name: 'France', type: 'Countries' },\n { id: '48', name: 'South Korea', type: 'Countries' },\n { id: '49', name: 'Malaysia', type: 'Countries' },\n { id: '50', name: 'Singapore', type: 'Countries' },\n { id: '51', name: 'Honda', type: 'Cars' },\n { id: '52', name: 'BMW', type: 'Cars' },\n { id: '53', name: 'Lamborghini', type: 'Cars' },\n { id: '54', name: 'Ferrari', type: 'Cars' },\n { id: '55', name: 'Chevrolet', type: 'Cars' },\n { id: '56', name: 'Mazda', type: 'Cars' },\n { id: '57', name: 'Cherry', type: 'Fruits' },\n { id: '58', name: 'Mango', type: 'Fruits' },\n { id: '59', name: 'Pear', type: 'Fruits' },\n { id: '60', name: 'Avocado', type: 'Fruits' },\n { id: '61', name: 'Cabbage', type: 'Vegetables' },\n { id: '62', name: 'Onion', type: 'Vegetables' },\n { id: '63', name: 'Garlic', type: 'Vegetables' },\n { id: '64', name: 'Pepper', type: 'Vegetables' },\n { id: '65', name: 'Germany', type: 'Countries' },\n { id: '66', name: 'France', type: 'Countries' },\n { id: '67', name: 'Spain', type: 'Countries' },\n { id: '68', name: 'Italy', type: 'Countries' },\n { id: '69', name: 'UK', type: 'Countries' },\n { id: '70', name: 'USA', type: 'Countries' },\n { id: '71', name: 'China', type: 'Countries' },\n { id: '72', name: 'Japan', type: 'Countries' },\n { id: '73', name: 'Brazil', type: 'Countries' },\n { id: '74', name: 'Russia', type: 'Countries' },\n { id: '75', name: 'India', type: 'Countries' },\n { id: '76', name: 'Mexico', type: 'Countries' },\n { id: '77', name: 'Egypt', type: 'Countries' },\n { id: '78', name: 'Australia', type: 'Countries' },\n { id: '79', name: 'Netherlands', type: 'Countries' },\n { id: '80', name: 'Belgium', type: 'Countries' },\n { id: '81', name: 'South Korea', type: 'Countries' },\n { id: '82', name: 'Malaysia', type: 'Countries' },\n { id: '83', name: 'Singapore', type: 'Countries' },\n { id: '84', name: 'Honda', type: 'Cars' },\n { id: '85', name: 'BMW', type: 'Cars' },\n { id: '86', name: 'Lamborghini', type: 'Cars' },\n { id: '87', name: 'Ferrari', type: 'Cars' },\n { id: '88', name: 'Chevrolet', type: 'Cars' },\n { id: '89', name: 'Mazda', type: 'Cars' },\n { id: '90', name: 'Grapes', type: 'Fruits' },\n { id: '91', name: 'Watermelon', type: 'Fruits' },\n { id: '92', name: 'Orange', type: 'Fruits' },\n { id: '93', name: 'Cucumber', type: 'Vegetables' },\n { id: '94', name: 'Lettuce', type: 'Vegetables' },\n { id: '95', name: 'Potato', type: 'Vegetables' },\n { id: '96', name: 'Tomato', type: 'Vegetables' },\n { id: '97', name: 'Ukraine', type: 'Countries' },\n { id: '98', name: 'Georgia', type: 'Countries' },\n { id: '99', name: 'Poland', type: 'Countries' },\n { id: '100', name: 'Finland', type: 'Countries' }\n ];\n dataSourceOf = of(this.dataSource);\n ds = new ArrayMultiComboBoxDataSource(this.dataSource);\n dsl = new ArrayMultiComboBoxDataSource(this.dataSource);\n\n selectedItems1 = [this.dataSourceStrings[1]];\n selectedItems2 = [this.dataSource[1]];\n selectedItems3 = [];\n selectedItems4 = [];\n selectedItems5 = [\n this.dataSourceStrings[1],\n this.dataSourceStrings[2],\n this.dataSourceStrings[3],\n this.dataSourceStrings[4]\n ];\n selectedItems6 = [];\n\n fb = inject(FormBuilder);\n\n formGroup = this.fb.group({ multiGroupComboBox: [[]] }, { updateOn: 'blur' });\n\n ngOnInit(): void {\n this.formGroup.get('multiGroupComboBox')?.valueChanges.subscribe(() => {\n console.log('value change event is triggered now -> ', this.formGroup.get('multiGroupComboBox')?.value);\n });\n }\n\n onSelect1(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems1 = item.selectedItems;\n }\n\n onSelect2(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems2 = item.selectedItems;\n }\n\n onSelect3(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems3 = item.selectedItems;\n }\n\n onSelect4(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems4 = item.selectedItems;\n }\n\n onSelect5(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems5 = item.selectedItems;\n }\n\n onSelect6(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems6 = item.selectedItems;\n }\n}\n", + "html": "
    \n
    \n \n \n
    \n
    \n\n

    Selected: {{ selectedItems1 }}

    \n\n
    \n
    \n\n

    Selected: {{ selectedItems2 | json }}

    \n\n
    \n \n \n
    \n\n

    Selected: {{ selectedItems3 | json }}

    \n\n
    \n \n \n
    \n\n

    Selected: {{ selectedItems4 | json }}

    \n\n
    \n \n \n
    \n\n

    Limitless: {{ isLimitless }}

    \n

    Selected: {{ selectedItems6 | json }}

    \n\n\n
    \n \n \n
    \n

    Selected: {{ selectedItems5 }}

    \n" }, { "name": "multi-combobox-inside-dialog-example", @@ -40715,18 +40745,18 @@ "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, TemplateRef } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport {\n ButtonBarComponent,\n ListComponent,\n ListItemComponent,\n MultiComboboxComponent,\n MultiComboboxSelectionChangeEvent\n} from '@fundamental-ngx/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\n\nimport {\n DialogBodyComponent,\n DialogComponent,\n DialogFooterComponent,\n DialogHeaderComponent,\n DialogService,\n DialogTemplateDirective\n} from '@fundamental-ngx/core/dialog';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-multi-combobox-inside-dialog-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './multi-combobox-inside-dialog-example.component.html',\n imports: [\n TitleComponent,\n DialogTemplateDirective,\n DialogFooterComponent,\n ButtonComponent,\n DialogComponent,\n ButtonBarComponent,\n DialogBodyComponent,\n DialogHeaderComponent,\n FormsModule,\n MultiComboboxComponent,\n ListComponent,\n ListItemComponent\n ]\n})\nexport class MultiComboboxInsideDialogExampleComponent {\n dataSourceStrings = ['Apple', 'Banana', 'Pineapple', 'Strawberry', 'Broccoli', 'Carrot', 'Jalapeño', 'Spinach'];\n selectedItems = [this.dataSourceStrings[1]];\n confirmationReason: string;\n\n constructor(\n private _dialogService: DialogService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n openDialog(dialog: TemplateRef): void {\n const dialogRef = this._dialogService.open(dialog, {\n width: '550px',\n focusTrapped: true\n });\n\n dialogRef.afterClosed.subscribe(\n (result: string) => {\n this.confirmationReason = 'Dialog closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error: string) => {\n this.confirmationReason = 'Dialog dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n onSelect(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems = item.selectedItems;\n }\n}\n", "html": "\n \n \n

    Multi Combobox in a dialog

    \n
    \n\n \n
    \n \n \n
    \n

    Selected Items:

    \n
      \n @for (item of selectedItems; track $index) {\n
    • \n {{ item }}\n
    • \n }\n
    \n
    \n\n \n \n\n \n \n
    \n
    \n\n\n

    {{ confirmationReason }}

    \n" }, - { - "name": "multi-combobox-loading-example", - "description": "Multi Combobox Loading", - "typescript": "import { JsonPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { DataProvider, DataSourceDirective } from '@fundamental-ngx/cdk/data-source';\nimport { CvaDirective } from '@fundamental-ngx/cdk/forms';\nimport { BusyIndicatorComponent } from '@fundamental-ngx/core/busy-indicator';\nimport {\n FdMultiComboBoxDataSource,\n MultiComboboxComponent,\n MultiComboboxSelectionChangeEvent\n} from '@fundamental-ngx/core/multi-combobox';\nimport { Observable } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\nconst OPTIONS = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n];\n\n@Component({\n selector: 'fd-multi-combobox-loading-example',\n templateUrl: './multi-combobox-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [BusyIndicatorComponent, CvaDirective, DataSourceDirective, MultiComboboxComponent, JsonPipe]\n})\nexport class MultiComboboxLoadingExampleComponent {\n dataSource = new FdMultiComboBoxDataSource(new DelayedDataProvider(OPTIONS));\n\n selectedItems = [];\n loading = false;\n\n onSelect(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems = item.selectedItems;\n }\n\n dataRequested(): void {\n this.loading = true;\n }\n dataReceived(): void {\n this.loading = false;\n }\n}\n\n// Simulating real http request by adding 300ms delay to the DataProvider's \"fetch\" method\nclass DelayedDataProvider extends DataProvider {\n fetch(params: Map): Observable {\n return super.fetch(params).pipe(delay(300));\n }\n}\n", - "html": "\n \n\n\n

    Selected: {{ selectedItems | json }}

    \n" - }, { "name": "multi-combobox-mobile-example", "description": "Multi Combobox Mobile", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { JsonPipe } from '@angular/common';\nimport { DataSourceDirective } from '@fundamental-ngx/cdk/data-source';\nimport { CvaDirective } from '@fundamental-ngx/cdk/forms';\nimport { FormItemComponent, FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { MobileModeConfig } from '@fundamental-ngx/core/mobile-mode';\nimport { MultiComboboxComponent, MultiComboboxSelectionChangeEvent } from '@fundamental-ngx/core/multi-combobox';\n\n@Component({\n selector: 'fd-multi-combobox-mobile-example',\n templateUrl: './multi-combobox-mobile-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n FormItemComponent,\n FormLabelComponent,\n CvaDirective,\n DataSourceDirective,\n MultiComboboxComponent,\n JsonPipe\n ]\n})\nexport class MultiComboboxMobileExampleComponent {\n dataSource = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n ];\n\n selectedItems = [];\n\n mobileConfig: MobileModeConfig = {\n title: 'Title',\n approveButtonText: 'Save',\n cancelButtonText: 'Cancel',\n hasCloseButton: true\n };\n\n onSelect(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems = item.selectedItems;\n }\n}\n", "html": "

    Mobile Mode Combobox:

    \n\n
    \n \n \n
    \n

    Selected: {{ selectedItems | json }}

    \n" }, + { + "name": "multi-combobox-loading-example", + "description": "Multi Combobox Loading", + "typescript": "import { JsonPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { DataProvider, DataSourceDirective } from '@fundamental-ngx/cdk/data-source';\nimport { CvaDirective } from '@fundamental-ngx/cdk/forms';\nimport { BusyIndicatorComponent } from '@fundamental-ngx/core/busy-indicator';\nimport {\n FdMultiComboBoxDataSource,\n MultiComboboxComponent,\n MultiComboboxSelectionChangeEvent\n} from '@fundamental-ngx/core/multi-combobox';\nimport { Observable } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\nconst OPTIONS = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n];\n\n@Component({\n selector: 'fd-multi-combobox-loading-example',\n templateUrl: './multi-combobox-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [BusyIndicatorComponent, CvaDirective, DataSourceDirective, MultiComboboxComponent, JsonPipe]\n})\nexport class MultiComboboxLoadingExampleComponent {\n dataSource = new FdMultiComboBoxDataSource(new DelayedDataProvider(OPTIONS));\n\n selectedItems = [];\n loading = false;\n\n onSelect(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems = item.selectedItems;\n }\n\n dataRequested(): void {\n this.loading = true;\n }\n dataReceived(): void {\n this.loading = false;\n }\n}\n\n// Simulating real http request by adding 300ms delay to the DataProvider's \"fetch\" method\nclass DelayedDataProvider extends DataProvider {\n fetch(params: Map): Observable {\n return super.fetch(params).pipe(delay(300));\n }\n}\n", + "html": "\n \n\n\n

    Selected: {{ selectedItems | json }}

    \n" + }, { "name": "multi-combobox-states-example", "description": "Multi Combobox States", @@ -41120,6 +41150,12 @@ "typescript": "import { JsonPipe } from '@angular/common';\nimport { Component } from '@angular/core';\nimport { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';\nimport { FieldsetComponent, FormItemComponent, FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { MultiInputComponent } from '@fundamental-ngx/core/multi-input';\n\n@Component({\n selector: 'fd-multi-input-form-example',\n templateUrl: './multi-input-form-example.component.html',\n imports: [\n FormsModule,\n ReactiveFormsModule,\n FieldsetComponent,\n FormItemComponent,\n FormLabelComponent,\n MultiInputComponent,\n JsonPipe\n ]\n})\nexport class MultiInputFormExampleComponent {\n customForm = new FormGroup({\n selectedValues: new FormControl({ value: ['Apple', 'Banana'], disabled: false }),\n disabledSelectedValues: new FormControl({ value: ['Pineapple', 'Tomato'], disabled: true })\n });\n\n isValid(): boolean {\n const value = this.customForm.get('selectedValues')?.value;\n return value != null && value.length > 0;\n }\n}\n", "html": "
    \n
    \n
    \n \n \n \n
    \n \n Enabled Multi-Input Value: {{ customForm.controls.selectedValues.value | json }}
    \n Enabled Multi-Input Touched: {{ customForm.controls.selectedValues.touched }}
    \n Enabled Multi-Input Dirty: {{ customForm.controls.selectedValues.dirty }}
    \n Enabled Multi-Input Valid: {{ customForm.controls.selectedValues.valid }}
    \n
    \n \n \n \n
    \n Disabled Multi-Input Value: {{ customForm.controls.disabledSelectedValues.value | json }}\n
    \n\n" }, + { + "name": "multi-input-mobile-example", + "description": "Multi Input Mobile", + "typescript": "import { JsonPipe } from '@angular/common';\nimport { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { MobileModeConfig } from '@fundamental-ngx/core/mobile-mode';\nimport { MultiInputComponent } from '@fundamental-ngx/core/multi-input';\n\n@Component({\n selector: 'fd-multi-input-mobile-example',\n templateUrl: './multi-input-mobile-example.component.html',\n imports: [FormLabelComponent, MultiInputComponent, FormsModule, JsonPipe]\n})\nexport class MultiInputMobileExampleComponent {\n selectedValues: any[] = [];\n\n secondConfig: MobileModeConfig = {\n approveButtonText: 'Approve',\n cancelButtonText: 'Cancel',\n hasCloseButton: true,\n dialogConfig: {\n ariaLabel: 'Select fruits dialog'\n }\n };\n\n values: any[] = ['Apple', 'Banana', 'Pineapple', 'Tomato', 'Kiwi', 'Strawberry', 'Blueberry', 'Orange'];\n}\n", + "html": "\n\n\nSelected: {{ selectedValues | json }}\n" + }, { "name": "multi-input-includes-example", "description": "Multi Input Includes", @@ -41127,21 +41163,15 @@ "html": "\n\nSelected: {{ selected | json }}\n" }, { - "name": "multi-input-mobile-example", - "description": "Multi Input Mobile", - "typescript": "import { JsonPipe } from '@angular/common';\nimport { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { MobileModeConfig } from '@fundamental-ngx/core/mobile-mode';\nimport { MultiInputComponent } from '@fundamental-ngx/core/multi-input';\n\n@Component({\n selector: 'fd-multi-input-mobile-example',\n templateUrl: './multi-input-mobile-example.component.html',\n imports: [FormLabelComponent, MultiInputComponent, FormsModule, JsonPipe]\n})\nexport class MultiInputMobileExampleComponent {\n selectedValues: any[] = [];\n\n secondConfig: MobileModeConfig = {\n approveButtonText: 'Approve',\n cancelButtonText: 'Cancel',\n hasCloseButton: true,\n dialogConfig: {\n ariaLabel: 'Select fruits dialog'\n }\n };\n\n values: any[] = ['Apple', 'Banana', 'Pineapple', 'Tomato', 'Kiwi', 'Strawberry', 'Blueberry', 'Orange'];\n}\n", - "html": "\n\n\nSelected: {{ selectedValues | json }}\n" + "name": "multi-input-option-item-example", + "description": "Multi Input Option Item", + "typescript": "import { Component } from '@angular/core';\nimport { MultiInputComponent, OptionItem } from '@fundamental-ngx/core/multi-input';\n\ninterface Item {\n value: string;\n label: string;\n}\n\n@Component({\n selector: 'fd-multi-input-option-item-example',\n template: `\n \n \n `,\n imports: [MultiInputComponent]\n})\nexport class MultiInputOptionItemExampleComponent {\n selected = [\n 'apple_value',\n 'banana_value',\n 'pineapple_value',\n 'tomato_value',\n 'kiwi_value',\n 'strawberry_value',\n 'blueberry_value'\n ];\n\n objectValues: OptionItem[] = [\n { label: 'Apple', value: 'apple_value' },\n { label: 'Banana', value: 'banana_value' },\n { label: 'Pineapple', value: 'pineapple_value' },\n { label: 'Tomato', value: 'tomato_value' },\n { label: 'Kiwi', value: 'kiwi_value' },\n { label: 'Strawberry', value: 'strawberry_value' },\n { label: 'Blueberry', value: 'blueberry_value' },\n { label: 'Orange', value: 'orange_value' }\n ].map((item, index) => ({\n id: index,\n ...item,\n item\n }));\n constructor() {}\n}\n" }, { "name": "multi-input-new-tokens-example", "description": "Multi Input New Tokens", "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { MultiInputComponent } from '@fundamental-ngx/core/multi-input';\n\n@Component({\n selector: 'fd-multi-input-new-tokens-example',\n templateUrl: './multi-input-new-tokens-example.component.html',\n imports: [MultiInputComponent, FormsModule]\n})\nexport class MultiInputNewTokensExampleComponent {\n values: Item[] = [\n { name: 'Apple' },\n { name: 'Banana' },\n { name: 'Pineapple' },\n { name: 'Tomato' },\n { name: 'Kiwi' },\n { name: 'Strawberry' },\n { name: 'Blueberry' },\n { name: 'Orange' }\n ];\n\n selected: Item[] = [];\n\n displayFunc(obj: Item): string {\n return obj.name;\n }\n\n parseFunc(value: string): Item {\n return { name: value };\n }\n\n validateFunc(value: string): boolean {\n return value?.length >= 3;\n }\n\n valueFn(obj: Item): string {\n return obj.name;\n }\n}\n\ninterface Item {\n name: string;\n}\n", "html": "\nSelected: [\n@for (item of selected; track item; let i = $index) {\n {{ i === selected.length - 1 ? item.name : item.name + ',' }}\n}\n]\n" - }, - { - "name": "multi-input-option-item-example", - "description": "Multi Input Option Item", - "typescript": "import { Component } from '@angular/core';\nimport { MultiInputComponent, OptionItem } from '@fundamental-ngx/core/multi-input';\n\ninterface Item {\n value: string;\n label: string;\n}\n\n@Component({\n selector: 'fd-multi-input-option-item-example',\n template: `\n \n \n `,\n imports: [MultiInputComponent]\n})\nexport class MultiInputOptionItemExampleComponent {\n selected = [\n 'apple_value',\n 'banana_value',\n 'pineapple_value',\n 'tomato_value',\n 'kiwi_value',\n 'strawberry_value',\n 'blueberry_value'\n ];\n\n objectValues: OptionItem[] = [\n { label: 'Apple', value: 'apple_value' },\n { label: 'Banana', value: 'banana_value' },\n { label: 'Pineapple', value: 'pineapple_value' },\n { label: 'Tomato', value: 'tomato_value' },\n { label: 'Kiwi', value: 'kiwi_value' },\n { label: 'Strawberry', value: 'strawberry_value' },\n { label: 'Blueberry', value: 'blueberry_value' },\n { label: 'Orange', value: 'orange_value' }\n ].map((item, index) => ({\n id: index,\n ...item,\n item\n }));\n constructor() {}\n}\n" } ] }, @@ -41227,6 +41257,12 @@ "typescript": "import { JsonPipe } from '@angular/common';\nimport { Component } from '@angular/core';\nimport { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';\nimport { FieldsetComponent, FormItemComponent, FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { MultiInputComponent } from '@fundamental-ngx/core/multi-input';\n\n@Component({\n selector: 'fd-multi-input-form-example',\n templateUrl: './multi-input-form-example.component.html',\n imports: [\n FormsModule,\n ReactiveFormsModule,\n FieldsetComponent,\n FormItemComponent,\n FormLabelComponent,\n MultiInputComponent,\n JsonPipe\n ]\n})\nexport class MultiInputFormExampleComponent {\n customForm = new FormGroup({\n selectedValues: new FormControl({ value: ['Apple', 'Banana'], disabled: false }),\n disabledSelectedValues: new FormControl({ value: ['Pineapple', 'Tomato'], disabled: true })\n });\n\n isValid(): boolean {\n const value = this.customForm.get('selectedValues')?.value;\n return value != null && value.length > 0;\n }\n}\n", "html": "
    \n
    \n
    \n \n \n \n
    \n \n Enabled Multi-Input Value: {{ customForm.controls.selectedValues.value | json }}
    \n Enabled Multi-Input Touched: {{ customForm.controls.selectedValues.touched }}
    \n Enabled Multi-Input Dirty: {{ customForm.controls.selectedValues.dirty }}
    \n Enabled Multi-Input Valid: {{ customForm.controls.selectedValues.valid }}
    \n
    \n \n \n \n
    \n Disabled Multi-Input Value: {{ customForm.controls.disabledSelectedValues.value | json }}\n
    \n\n" }, + { + "name": "multi-input-mobile-example", + "description": "Multi Input Mobile", + "typescript": "import { JsonPipe } from '@angular/common';\nimport { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { MobileModeConfig } from '@fundamental-ngx/core/mobile-mode';\nimport { MultiInputComponent } from '@fundamental-ngx/core/multi-input';\n\n@Component({\n selector: 'fd-multi-input-mobile-example',\n templateUrl: './multi-input-mobile-example.component.html',\n imports: [FormLabelComponent, MultiInputComponent, FormsModule, JsonPipe]\n})\nexport class MultiInputMobileExampleComponent {\n selectedValues: any[] = [];\n\n secondConfig: MobileModeConfig = {\n approveButtonText: 'Approve',\n cancelButtonText: 'Cancel',\n hasCloseButton: true,\n dialogConfig: {\n ariaLabel: 'Select fruits dialog'\n }\n };\n\n values: any[] = ['Apple', 'Banana', 'Pineapple', 'Tomato', 'Kiwi', 'Strawberry', 'Blueberry', 'Orange'];\n}\n", + "html": "\n\n\nSelected: {{ selectedValues | json }}\n" + }, { "name": "multi-input-includes-example", "description": "Multi Input Includes", @@ -41234,21 +41270,15 @@ "html": "\n\nSelected: {{ selected | json }}\n" }, { - "name": "multi-input-mobile-example", - "description": "Multi Input Mobile", - "typescript": "import { JsonPipe } from '@angular/common';\nimport { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { MobileModeConfig } from '@fundamental-ngx/core/mobile-mode';\nimport { MultiInputComponent } from '@fundamental-ngx/core/multi-input';\n\n@Component({\n selector: 'fd-multi-input-mobile-example',\n templateUrl: './multi-input-mobile-example.component.html',\n imports: [FormLabelComponent, MultiInputComponent, FormsModule, JsonPipe]\n})\nexport class MultiInputMobileExampleComponent {\n selectedValues: any[] = [];\n\n secondConfig: MobileModeConfig = {\n approveButtonText: 'Approve',\n cancelButtonText: 'Cancel',\n hasCloseButton: true,\n dialogConfig: {\n ariaLabel: 'Select fruits dialog'\n }\n };\n\n values: any[] = ['Apple', 'Banana', 'Pineapple', 'Tomato', 'Kiwi', 'Strawberry', 'Blueberry', 'Orange'];\n}\n", - "html": "\n\n\nSelected: {{ selectedValues | json }}\n" + "name": "multi-input-option-item-example", + "description": "Multi Input Option Item", + "typescript": "import { Component } from '@angular/core';\nimport { MultiInputComponent, OptionItem } from '@fundamental-ngx/core/multi-input';\n\ninterface Item {\n value: string;\n label: string;\n}\n\n@Component({\n selector: 'fd-multi-input-option-item-example',\n template: `\n \n \n `,\n imports: [MultiInputComponent]\n})\nexport class MultiInputOptionItemExampleComponent {\n selected = [\n 'apple_value',\n 'banana_value',\n 'pineapple_value',\n 'tomato_value',\n 'kiwi_value',\n 'strawberry_value',\n 'blueberry_value'\n ];\n\n objectValues: OptionItem[] = [\n { label: 'Apple', value: 'apple_value' },\n { label: 'Banana', value: 'banana_value' },\n { label: 'Pineapple', value: 'pineapple_value' },\n { label: 'Tomato', value: 'tomato_value' },\n { label: 'Kiwi', value: 'kiwi_value' },\n { label: 'Strawberry', value: 'strawberry_value' },\n { label: 'Blueberry', value: 'blueberry_value' },\n { label: 'Orange', value: 'orange_value' }\n ].map((item, index) => ({\n id: index,\n ...item,\n item\n }));\n constructor() {}\n}\n" }, { "name": "multi-input-new-tokens-example", "description": "Multi Input New Tokens", "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { MultiInputComponent } from '@fundamental-ngx/core/multi-input';\n\n@Component({\n selector: 'fd-multi-input-new-tokens-example',\n templateUrl: './multi-input-new-tokens-example.component.html',\n imports: [MultiInputComponent, FormsModule]\n})\nexport class MultiInputNewTokensExampleComponent {\n values: Item[] = [\n { name: 'Apple' },\n { name: 'Banana' },\n { name: 'Pineapple' },\n { name: 'Tomato' },\n { name: 'Kiwi' },\n { name: 'Strawberry' },\n { name: 'Blueberry' },\n { name: 'Orange' }\n ];\n\n selected: Item[] = [];\n\n displayFunc(obj: Item): string {\n return obj.name;\n }\n\n parseFunc(value: string): Item {\n return { name: value };\n }\n\n validateFunc(value: string): boolean {\n return value?.length >= 3;\n }\n\n valueFn(obj: Item): string {\n return obj.name;\n }\n}\n\ninterface Item {\n name: string;\n}\n", "html": "\nSelected: [\n@for (item of selected; track item; let i = $index) {\n {{ i === selected.length - 1 ? item.name : item.name + ',' }}\n}\n]\n" - }, - { - "name": "multi-input-option-item-example", - "description": "Multi Input Option Item", - "typescript": "import { Component } from '@angular/core';\nimport { MultiInputComponent, OptionItem } from '@fundamental-ngx/core/multi-input';\n\ninterface Item {\n value: string;\n label: string;\n}\n\n@Component({\n selector: 'fd-multi-input-option-item-example',\n template: `\n \n \n `,\n imports: [MultiInputComponent]\n})\nexport class MultiInputOptionItemExampleComponent {\n selected = [\n 'apple_value',\n 'banana_value',\n 'pineapple_value',\n 'tomato_value',\n 'kiwi_value',\n 'strawberry_value',\n 'blueberry_value'\n ];\n\n objectValues: OptionItem[] = [\n { label: 'Apple', value: 'apple_value' },\n { label: 'Banana', value: 'banana_value' },\n { label: 'Pineapple', value: 'pineapple_value' },\n { label: 'Tomato', value: 'tomato_value' },\n { label: 'Kiwi', value: 'kiwi_value' },\n { label: 'Strawberry', value: 'strawberry_value' },\n { label: 'Blueberry', value: 'blueberry_value' },\n { label: 'Orange', value: 'orange_value' }\n ].map((item, index) => ({\n id: index,\n ...item,\n item\n }));\n constructor() {}\n}\n" } ] }, @@ -41365,17 +41395,17 @@ "sourceFile": "libs/core/notification/notification/notification.component.ts", "source": "typedoc", "examples": [ - { - "name": "notification-component-as-content-example", - "description": "Notification Component As Content", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" - }, { "name": "notification-group-example", "description": "Notification Group", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { NgTemplateOutlet } from '@angular/common';\nimport { TitleComponent } from '@fundamental-ngx/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { MessageStripModule } from '@fundamental-ngx/core/message-strip';\nimport { NotificationModule } from '@fundamental-ngx/core/notification';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ToolbarModule } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\nexport type Notification = {\n avatar: string;\n title: string;\n unread: boolean;\n paragraph: string;\n footerContent1: string;\n footerContent2: string;\n actionButton: string;\n};\n\n@Component({\n selector: 'fd-notification-group-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './notification-group-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n NotificationModule,\n FDP_ICON_TAB_BAR,\n NgTemplateOutlet,\n AvatarComponent,\n MessageStripModule,\n ToolbarModule,\n ObjectStatusComponent,\n IconComponent,\n TitleComponent\n ]\n})\nexport class NotificationGroupExampleComponent {\n expandedByDate = true;\n expandedByType1 = true;\n expandedByType2 = false;\n expandedByPriority = true;\n\n notifications: Notification[] = [\n {\n avatar: 'batch-payments',\n title: 'Your leave request has been accepted',\n unread: false,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'customer',\n title: 'Your leave request has been accepted',\n unread: true,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n }\n ];\n\n notificationsWarning: Notification[] = [\n {\n avatar: 'work-history',\n title: 'Approve order #1234',\n unread: true,\n paragraph: 'Adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'sap-box',\n title: 'Approve order #5678',\n unread: true,\n paragraph: 'Consectetur adipiscing elit tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '2 days ago',\n actionButton: 'Accept'\n }\n ];\n}\n", "html": "
    \n \n \n \n \n \n
    \n \n

    Notifications (30)

    \n \n \n \n \n
    \n
    \n A dismissible warning message strip. \n
    \n
      \n \n \n \n \n Today\n \n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n \n More\n \n
      \n\n \n \n \n Yesterday\n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n
      \n
    \n
    \n
    \n
    \n
    \n" }, + { + "name": "notification-component-as-content-example", + "description": "Notification Component As Content", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" + }, { "name": "notification-options-example", "description": "Notification Options", @@ -41404,17 +41434,17 @@ "sourceFile": "libs/core/notification/notification-actions/notification-actions.component.ts", "source": "typedoc", "examples": [ - { - "name": "notification-component-as-content-example", - "description": "Notification Component As Content", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" - }, { "name": "notification-group-example", "description": "Notification Group", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { NgTemplateOutlet } from '@angular/common';\nimport { TitleComponent } from '@fundamental-ngx/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { MessageStripModule } from '@fundamental-ngx/core/message-strip';\nimport { NotificationModule } from '@fundamental-ngx/core/notification';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ToolbarModule } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\nexport type Notification = {\n avatar: string;\n title: string;\n unread: boolean;\n paragraph: string;\n footerContent1: string;\n footerContent2: string;\n actionButton: string;\n};\n\n@Component({\n selector: 'fd-notification-group-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './notification-group-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n NotificationModule,\n FDP_ICON_TAB_BAR,\n NgTemplateOutlet,\n AvatarComponent,\n MessageStripModule,\n ToolbarModule,\n ObjectStatusComponent,\n IconComponent,\n TitleComponent\n ]\n})\nexport class NotificationGroupExampleComponent {\n expandedByDate = true;\n expandedByType1 = true;\n expandedByType2 = false;\n expandedByPriority = true;\n\n notifications: Notification[] = [\n {\n avatar: 'batch-payments',\n title: 'Your leave request has been accepted',\n unread: false,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'customer',\n title: 'Your leave request has been accepted',\n unread: true,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n }\n ];\n\n notificationsWarning: Notification[] = [\n {\n avatar: 'work-history',\n title: 'Approve order #1234',\n unread: true,\n paragraph: 'Adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'sap-box',\n title: 'Approve order #5678',\n unread: true,\n paragraph: 'Consectetur adipiscing elit tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '2 days ago',\n actionButton: 'Accept'\n }\n ];\n}\n", "html": "
    \n \n \n \n \n \n
    \n \n

    Notifications (30)

    \n \n \n \n \n
    \n
    \n A dismissible warning message strip. \n
    \n
      \n \n \n \n \n Today\n \n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n \n More\n \n
      \n\n \n \n \n Yesterday\n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n
      \n
    \n
    \n
    \n
    \n
    \n" }, + { + "name": "notification-component-as-content-example", + "description": "Notification Component As Content", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" + }, { "name": "notification-options-example", "description": "Notification Options", @@ -41443,17 +41473,17 @@ "sourceFile": "libs/core/notification/notification-body/notification-body.component.ts", "source": "typedoc", "examples": [ - { - "name": "notification-component-as-content-example", - "description": "Notification Component As Content", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" - }, { "name": "notification-group-example", "description": "Notification Group", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { NgTemplateOutlet } from '@angular/common';\nimport { TitleComponent } from '@fundamental-ngx/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { MessageStripModule } from '@fundamental-ngx/core/message-strip';\nimport { NotificationModule } from '@fundamental-ngx/core/notification';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ToolbarModule } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\nexport type Notification = {\n avatar: string;\n title: string;\n unread: boolean;\n paragraph: string;\n footerContent1: string;\n footerContent2: string;\n actionButton: string;\n};\n\n@Component({\n selector: 'fd-notification-group-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './notification-group-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n NotificationModule,\n FDP_ICON_TAB_BAR,\n NgTemplateOutlet,\n AvatarComponent,\n MessageStripModule,\n ToolbarModule,\n ObjectStatusComponent,\n IconComponent,\n TitleComponent\n ]\n})\nexport class NotificationGroupExampleComponent {\n expandedByDate = true;\n expandedByType1 = true;\n expandedByType2 = false;\n expandedByPriority = true;\n\n notifications: Notification[] = [\n {\n avatar: 'batch-payments',\n title: 'Your leave request has been accepted',\n unread: false,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'customer',\n title: 'Your leave request has been accepted',\n unread: true,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n }\n ];\n\n notificationsWarning: Notification[] = [\n {\n avatar: 'work-history',\n title: 'Approve order #1234',\n unread: true,\n paragraph: 'Adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'sap-box',\n title: 'Approve order #5678',\n unread: true,\n paragraph: 'Consectetur adipiscing elit tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '2 days ago',\n actionButton: 'Accept'\n }\n ];\n}\n", "html": "
    \n \n \n \n \n \n
    \n \n

    Notifications (30)

    \n \n \n \n \n
    \n
    \n A dismissible warning message strip. \n
    \n
      \n \n \n \n \n Today\n \n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n \n More\n \n
      \n\n \n \n \n Yesterday\n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n
      \n
    \n
    \n
    \n
    \n
    \n" }, + { + "name": "notification-component-as-content-example", + "description": "Notification Component As Content", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" + }, { "name": "notification-options-example", "description": "Notification Options", @@ -41482,17 +41512,17 @@ "sourceFile": "libs/core/notification/notification-content/notification-content.component.ts", "source": "typedoc", "examples": [ - { - "name": "notification-component-as-content-example", - "description": "Notification Component As Content", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" - }, { "name": "notification-group-example", "description": "Notification Group", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { NgTemplateOutlet } from '@angular/common';\nimport { TitleComponent } from '@fundamental-ngx/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { MessageStripModule } from '@fundamental-ngx/core/message-strip';\nimport { NotificationModule } from '@fundamental-ngx/core/notification';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ToolbarModule } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\nexport type Notification = {\n avatar: string;\n title: string;\n unread: boolean;\n paragraph: string;\n footerContent1: string;\n footerContent2: string;\n actionButton: string;\n};\n\n@Component({\n selector: 'fd-notification-group-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './notification-group-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n NotificationModule,\n FDP_ICON_TAB_BAR,\n NgTemplateOutlet,\n AvatarComponent,\n MessageStripModule,\n ToolbarModule,\n ObjectStatusComponent,\n IconComponent,\n TitleComponent\n ]\n})\nexport class NotificationGroupExampleComponent {\n expandedByDate = true;\n expandedByType1 = true;\n expandedByType2 = false;\n expandedByPriority = true;\n\n notifications: Notification[] = [\n {\n avatar: 'batch-payments',\n title: 'Your leave request has been accepted',\n unread: false,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'customer',\n title: 'Your leave request has been accepted',\n unread: true,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n }\n ];\n\n notificationsWarning: Notification[] = [\n {\n avatar: 'work-history',\n title: 'Approve order #1234',\n unread: true,\n paragraph: 'Adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'sap-box',\n title: 'Approve order #5678',\n unread: true,\n paragraph: 'Consectetur adipiscing elit tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '2 days ago',\n actionButton: 'Accept'\n }\n ];\n}\n", "html": "
    \n \n \n \n \n \n
    \n \n

    Notifications (30)

    \n \n \n \n \n
    \n
    \n A dismissible warning message strip. \n
    \n
      \n \n \n \n \n Today\n \n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n \n More\n \n
      \n\n \n \n \n Yesterday\n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n
      \n
    \n
    \n
    \n
    \n
    \n" }, + { + "name": "notification-component-as-content-example", + "description": "Notification Component As Content", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" + }, { "name": "notification-options-example", "description": "Notification Options", @@ -41552,17 +41582,17 @@ "sourceFile": "libs/core/notification/notification-footer/notification-footer.component.ts", "source": "typedoc", "examples": [ - { - "name": "notification-component-as-content-example", - "description": "Notification Component As Content", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" - }, { "name": "notification-group-example", "description": "Notification Group", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { NgTemplateOutlet } from '@angular/common';\nimport { TitleComponent } from '@fundamental-ngx/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { MessageStripModule } from '@fundamental-ngx/core/message-strip';\nimport { NotificationModule } from '@fundamental-ngx/core/notification';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ToolbarModule } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\nexport type Notification = {\n avatar: string;\n title: string;\n unread: boolean;\n paragraph: string;\n footerContent1: string;\n footerContent2: string;\n actionButton: string;\n};\n\n@Component({\n selector: 'fd-notification-group-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './notification-group-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n NotificationModule,\n FDP_ICON_TAB_BAR,\n NgTemplateOutlet,\n AvatarComponent,\n MessageStripModule,\n ToolbarModule,\n ObjectStatusComponent,\n IconComponent,\n TitleComponent\n ]\n})\nexport class NotificationGroupExampleComponent {\n expandedByDate = true;\n expandedByType1 = true;\n expandedByType2 = false;\n expandedByPriority = true;\n\n notifications: Notification[] = [\n {\n avatar: 'batch-payments',\n title: 'Your leave request has been accepted',\n unread: false,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'customer',\n title: 'Your leave request has been accepted',\n unread: true,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n }\n ];\n\n notificationsWarning: Notification[] = [\n {\n avatar: 'work-history',\n title: 'Approve order #1234',\n unread: true,\n paragraph: 'Adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'sap-box',\n title: 'Approve order #5678',\n unread: true,\n paragraph: 'Consectetur adipiscing elit tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '2 days ago',\n actionButton: 'Accept'\n }\n ];\n}\n", "html": "
    \n \n \n \n \n \n
    \n \n

    Notifications (30)

    \n \n \n \n \n
    \n
    \n A dismissible warning message strip. \n
    \n
      \n \n \n \n \n Today\n \n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n \n More\n \n
      \n\n \n \n \n Yesterday\n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n
      \n
    \n
    \n
    \n
    \n
    \n" }, + { + "name": "notification-component-as-content-example", + "description": "Notification Component As Content", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" + }, { "name": "notification-options-example", "description": "Notification Options", @@ -41604,17 +41634,17 @@ "sourceFile": "libs/core/notification/notification-group/notification-group.component.ts", "source": "typedoc", "examples": [ - { - "name": "notification-component-as-content-example", - "description": "Notification Component As Content", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" - }, { "name": "notification-group-example", "description": "Notification Group", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { NgTemplateOutlet } from '@angular/common';\nimport { TitleComponent } from '@fundamental-ngx/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { MessageStripModule } from '@fundamental-ngx/core/message-strip';\nimport { NotificationModule } from '@fundamental-ngx/core/notification';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ToolbarModule } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\nexport type Notification = {\n avatar: string;\n title: string;\n unread: boolean;\n paragraph: string;\n footerContent1: string;\n footerContent2: string;\n actionButton: string;\n};\n\n@Component({\n selector: 'fd-notification-group-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './notification-group-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n NotificationModule,\n FDP_ICON_TAB_BAR,\n NgTemplateOutlet,\n AvatarComponent,\n MessageStripModule,\n ToolbarModule,\n ObjectStatusComponent,\n IconComponent,\n TitleComponent\n ]\n})\nexport class NotificationGroupExampleComponent {\n expandedByDate = true;\n expandedByType1 = true;\n expandedByType2 = false;\n expandedByPriority = true;\n\n notifications: Notification[] = [\n {\n avatar: 'batch-payments',\n title: 'Your leave request has been accepted',\n unread: false,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'customer',\n title: 'Your leave request has been accepted',\n unread: true,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n }\n ];\n\n notificationsWarning: Notification[] = [\n {\n avatar: 'work-history',\n title: 'Approve order #1234',\n unread: true,\n paragraph: 'Adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'sap-box',\n title: 'Approve order #5678',\n unread: true,\n paragraph: 'Consectetur adipiscing elit tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '2 days ago',\n actionButton: 'Accept'\n }\n ];\n}\n", "html": "
    \n \n \n \n \n \n
    \n \n

    Notifications (30)

    \n \n \n \n \n
    \n
    \n A dismissible warning message strip. \n
    \n
      \n \n \n \n \n Today\n \n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n \n More\n \n
      \n\n \n \n \n Yesterday\n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n
      \n
    \n
    \n
    \n
    \n
    \n" }, + { + "name": "notification-component-as-content-example", + "description": "Notification Component As Content", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" + }, { "name": "notification-options-example", "description": "Notification Options", @@ -41643,17 +41673,17 @@ "sourceFile": "libs/core/notification/notification-group-growing-item/notification-group-growing-item.component.ts", "source": "typedoc", "examples": [ - { - "name": "notification-component-as-content-example", - "description": "Notification Component As Content", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" - }, { "name": "notification-group-example", "description": "Notification Group", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { NgTemplateOutlet } from '@angular/common';\nimport { TitleComponent } from '@fundamental-ngx/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { MessageStripModule } from '@fundamental-ngx/core/message-strip';\nimport { NotificationModule } from '@fundamental-ngx/core/notification';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ToolbarModule } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\nexport type Notification = {\n avatar: string;\n title: string;\n unread: boolean;\n paragraph: string;\n footerContent1: string;\n footerContent2: string;\n actionButton: string;\n};\n\n@Component({\n selector: 'fd-notification-group-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './notification-group-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n NotificationModule,\n FDP_ICON_TAB_BAR,\n NgTemplateOutlet,\n AvatarComponent,\n MessageStripModule,\n ToolbarModule,\n ObjectStatusComponent,\n IconComponent,\n TitleComponent\n ]\n})\nexport class NotificationGroupExampleComponent {\n expandedByDate = true;\n expandedByType1 = true;\n expandedByType2 = false;\n expandedByPriority = true;\n\n notifications: Notification[] = [\n {\n avatar: 'batch-payments',\n title: 'Your leave request has been accepted',\n unread: false,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'customer',\n title: 'Your leave request has been accepted',\n unread: true,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n }\n ];\n\n notificationsWarning: Notification[] = [\n {\n avatar: 'work-history',\n title: 'Approve order #1234',\n unread: true,\n paragraph: 'Adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'sap-box',\n title: 'Approve order #5678',\n unread: true,\n paragraph: 'Consectetur adipiscing elit tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '2 days ago',\n actionButton: 'Accept'\n }\n ];\n}\n", "html": "
    \n \n \n \n \n \n
    \n \n

    Notifications (30)

    \n \n \n \n \n
    \n
    \n A dismissible warning message strip. \n
    \n
      \n \n \n \n \n Today\n \n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n \n More\n \n
      \n\n \n \n \n Yesterday\n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n
      \n
    \n
    \n
    \n
    \n
    \n" }, + { + "name": "notification-component-as-content-example", + "description": "Notification Component As Content", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" + }, { "name": "notification-options-example", "description": "Notification Options", @@ -41689,17 +41719,17 @@ "sourceFile": "libs/core/notification/notification-group-header/notification-group-header.component.ts", "source": "typedoc", "examples": [ - { - "name": "notification-component-as-content-example", - "description": "Notification Component As Content", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" - }, { "name": "notification-group-example", "description": "Notification Group", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { NgTemplateOutlet } from '@angular/common';\nimport { TitleComponent } from '@fundamental-ngx/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { MessageStripModule } from '@fundamental-ngx/core/message-strip';\nimport { NotificationModule } from '@fundamental-ngx/core/notification';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ToolbarModule } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\nexport type Notification = {\n avatar: string;\n title: string;\n unread: boolean;\n paragraph: string;\n footerContent1: string;\n footerContent2: string;\n actionButton: string;\n};\n\n@Component({\n selector: 'fd-notification-group-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './notification-group-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n NotificationModule,\n FDP_ICON_TAB_BAR,\n NgTemplateOutlet,\n AvatarComponent,\n MessageStripModule,\n ToolbarModule,\n ObjectStatusComponent,\n IconComponent,\n TitleComponent\n ]\n})\nexport class NotificationGroupExampleComponent {\n expandedByDate = true;\n expandedByType1 = true;\n expandedByType2 = false;\n expandedByPriority = true;\n\n notifications: Notification[] = [\n {\n avatar: 'batch-payments',\n title: 'Your leave request has been accepted',\n unread: false,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'customer',\n title: 'Your leave request has been accepted',\n unread: true,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n }\n ];\n\n notificationsWarning: Notification[] = [\n {\n avatar: 'work-history',\n title: 'Approve order #1234',\n unread: true,\n paragraph: 'Adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'sap-box',\n title: 'Approve order #5678',\n unread: true,\n paragraph: 'Consectetur adipiscing elit tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '2 days ago',\n actionButton: 'Accept'\n }\n ];\n}\n", "html": "
    \n \n \n \n \n \n
    \n \n

    Notifications (30)

    \n \n \n \n \n
    \n
    \n A dismissible warning message strip. \n
    \n
      \n \n \n \n \n Today\n \n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n \n More\n \n
      \n\n \n \n \n Yesterday\n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n
      \n
    \n
    \n
    \n
    \n
    \n" }, + { + "name": "notification-component-as-content-example", + "description": "Notification Component As Content", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" + }, { "name": "notification-options-example", "description": "Notification Options", @@ -41741,17 +41771,17 @@ "sourceFile": "libs/core/notification/notification-group-list/notification-group-list.component.ts", "source": "typedoc", "examples": [ - { - "name": "notification-component-as-content-example", - "description": "Notification Component As Content", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" - }, { "name": "notification-group-example", "description": "Notification Group", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { NgTemplateOutlet } from '@angular/common';\nimport { TitleComponent } from '@fundamental-ngx/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { MessageStripModule } from '@fundamental-ngx/core/message-strip';\nimport { NotificationModule } from '@fundamental-ngx/core/notification';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ToolbarModule } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\nexport type Notification = {\n avatar: string;\n title: string;\n unread: boolean;\n paragraph: string;\n footerContent1: string;\n footerContent2: string;\n actionButton: string;\n};\n\n@Component({\n selector: 'fd-notification-group-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './notification-group-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n NotificationModule,\n FDP_ICON_TAB_BAR,\n NgTemplateOutlet,\n AvatarComponent,\n MessageStripModule,\n ToolbarModule,\n ObjectStatusComponent,\n IconComponent,\n TitleComponent\n ]\n})\nexport class NotificationGroupExampleComponent {\n expandedByDate = true;\n expandedByType1 = true;\n expandedByType2 = false;\n expandedByPriority = true;\n\n notifications: Notification[] = [\n {\n avatar: 'batch-payments',\n title: 'Your leave request has been accepted',\n unread: false,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'customer',\n title: 'Your leave request has been accepted',\n unread: true,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n }\n ];\n\n notificationsWarning: Notification[] = [\n {\n avatar: 'work-history',\n title: 'Approve order #1234',\n unread: true,\n paragraph: 'Adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'sap-box',\n title: 'Approve order #5678',\n unread: true,\n paragraph: 'Consectetur adipiscing elit tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '2 days ago',\n actionButton: 'Accept'\n }\n ];\n}\n", "html": "
    \n \n \n \n \n \n
    \n \n

    Notifications (30)

    \n \n \n \n \n
    \n
    \n A dismissible warning message strip. \n
    \n
      \n \n \n \n \n Today\n \n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n \n More\n \n
      \n\n \n \n \n Yesterday\n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n
      \n
    \n
    \n
    \n
    \n
    \n" }, + { + "name": "notification-component-as-content-example", + "description": "Notification Component As Content", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" + }, { "name": "notification-options-example", "description": "Notification Options", @@ -41787,17 +41817,17 @@ "sourceFile": "libs/core/notification/notification-header/notification-header.component.ts", "source": "typedoc", "examples": [ - { - "name": "notification-component-as-content-example", - "description": "Notification Component As Content", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" - }, { "name": "notification-group-example", "description": "Notification Group", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { NgTemplateOutlet } from '@angular/common';\nimport { TitleComponent } from '@fundamental-ngx/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { MessageStripModule } from '@fundamental-ngx/core/message-strip';\nimport { NotificationModule } from '@fundamental-ngx/core/notification';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ToolbarModule } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\nexport type Notification = {\n avatar: string;\n title: string;\n unread: boolean;\n paragraph: string;\n footerContent1: string;\n footerContent2: string;\n actionButton: string;\n};\n\n@Component({\n selector: 'fd-notification-group-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './notification-group-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n NotificationModule,\n FDP_ICON_TAB_BAR,\n NgTemplateOutlet,\n AvatarComponent,\n MessageStripModule,\n ToolbarModule,\n ObjectStatusComponent,\n IconComponent,\n TitleComponent\n ]\n})\nexport class NotificationGroupExampleComponent {\n expandedByDate = true;\n expandedByType1 = true;\n expandedByType2 = false;\n expandedByPriority = true;\n\n notifications: Notification[] = [\n {\n avatar: 'batch-payments',\n title: 'Your leave request has been accepted',\n unread: false,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'customer',\n title: 'Your leave request has been accepted',\n unread: true,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n }\n ];\n\n notificationsWarning: Notification[] = [\n {\n avatar: 'work-history',\n title: 'Approve order #1234',\n unread: true,\n paragraph: 'Adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'sap-box',\n title: 'Approve order #5678',\n unread: true,\n paragraph: 'Consectetur adipiscing elit tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '2 days ago',\n actionButton: 'Accept'\n }\n ];\n}\n", "html": "
    \n \n \n \n \n \n
    \n \n

    Notifications (30)

    \n \n \n \n \n
    \n
    \n A dismissible warning message strip. \n
    \n
      \n \n \n \n \n Today\n \n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n \n More\n \n
      \n\n \n \n \n Yesterday\n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n
      \n
    \n
    \n
    \n
    \n
    \n" }, + { + "name": "notification-component-as-content-example", + "description": "Notification Component As Content", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" + }, { "name": "notification-options-example", "description": "Notification Options", @@ -41833,17 +41863,17 @@ "sourceFile": "libs/core/notification/notification-link/notification-link.component.ts", "source": "typedoc", "examples": [ - { - "name": "notification-component-as-content-example", - "description": "Notification Component As Content", - "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" - }, { "name": "notification-group-example", "description": "Notification Group", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { NgTemplateOutlet } from '@angular/common';\nimport { TitleComponent } from '@fundamental-ngx/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { MessageStripModule } from '@fundamental-ngx/core/message-strip';\nimport { NotificationModule } from '@fundamental-ngx/core/notification';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ToolbarModule } from '@fundamental-ngx/core/toolbar';\nimport { FDP_ICON_TAB_BAR } from '@fundamental-ngx/platform/icon-tab-bar';\n\nexport type Notification = {\n avatar: string;\n title: string;\n unread: boolean;\n paragraph: string;\n footerContent1: string;\n footerContent2: string;\n actionButton: string;\n};\n\n@Component({\n selector: 'fd-notification-group-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './notification-group-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n NotificationModule,\n FDP_ICON_TAB_BAR,\n NgTemplateOutlet,\n AvatarComponent,\n MessageStripModule,\n ToolbarModule,\n ObjectStatusComponent,\n IconComponent,\n TitleComponent\n ]\n})\nexport class NotificationGroupExampleComponent {\n expandedByDate = true;\n expandedByType1 = true;\n expandedByType2 = false;\n expandedByPriority = true;\n\n notifications: Notification[] = [\n {\n avatar: 'batch-payments',\n title: 'Your leave request has been accepted',\n unread: false,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'customer',\n title: 'Your leave request has been accepted',\n unread: true,\n paragraph:\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Analytics Cloud',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n }\n ];\n\n notificationsWarning: Notification[] = [\n {\n avatar: 'work-history',\n title: 'Approve order #1234',\n unread: true,\n paragraph: 'Adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '7 minutes ago',\n actionButton: 'Accept'\n },\n {\n avatar: 'sap-box',\n title: 'Approve order #5678',\n unread: true,\n paragraph: 'Consectetur adipiscing elit tempor incididunt ut labore et dolore magna aliqua.',\n footerContent1: 'SAP Ariba',\n footerContent2: '2 days ago',\n actionButton: 'Accept'\n }\n ];\n}\n", "html": "
    \n \n \n \n \n \n
    \n \n

    Notifications (30)

    \n \n \n \n \n
    \n
    \n A dismissible warning message strip. \n
    \n
      \n \n \n \n \n Today\n \n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n \n More\n \n
      \n\n \n \n \n Yesterday\n \n \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n \n \n \n \n \n \n

      \n Notification Title (unread) lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n

      \n
      \n

      \n Description of notification topic lorem ipsum dolor sit amet, consectetur\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna\n aliqua.\n

      \n \n Product Name\n \n Feature Name\n \n 11:11 AM\n \n \n
      \n \n \n \n
      \n
      \n
      \n
      \n
    \n
    \n
    \n
    \n
    \n" }, + { + "name": "notification-component-as-content-example", + "description": "Notification Component As Content", + "typescript": "import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, signal } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { NotificationService } from '@fundamental-ngx/core/notification';\nimport { NotificationExampleContentComponent } from './notification-content.component';\n\n@Component({\n selector: 'fd-notification-component-as-content-example',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n \n {{ closeReason }}\n `,\n imports: [ButtonComponent],\n providers: [NotificationService]\n})\nexport class NotificationComponentAsContentExampleComponent {\n public closeReason: string;\n\n // Manual control signals for Show More/Show Less\n protected readonly isExpanded = signal(false);\n protected readonly isTruncated = signal(false);\n protected readonly showTrigger = computed(() => this.isTruncated() || this.isExpanded());\n\n constructor(\n private notificationService: NotificationService,\n private _cdr: ChangeDetectorRef\n ) {}\n\n open(): void {\n this.isExpanded.set(false);\n this.isTruncated.set(false);\n\n const notificationService = this.notificationService.open(NotificationExampleContentComponent, {\n data: {\n title: 'This is a very long notification title that will be truncated after two lines to keep the notification compact and readable in the list view',\n paragraph:\n 'This is a very long notification paragraph with multiple sentences. It contains important information that the user should read. The text will be truncated after two lines by default, but the user can click \"Show More\" to expand and read the full content.',\n firstFooterContent: 'SAP Analytics Cloud',\n secondFooterContent: 'Just Now',\n showTrigger: this.showTrigger,\n isExpanded: this.isExpanded\n },\n width: '500px'\n });\n\n // Check for truncation after notification renders\n setTimeout(() => this.checkTruncation(), 100);\n\n notificationService.afterClosed.subscribe(\n (result) => {\n this.closeReason = 'Notification closed with result: ' + result;\n this._cdr.detectChanges();\n },\n (error) => {\n this.closeReason = 'Notification dismissed with result: ' + error;\n this._cdr.detectChanges();\n }\n );\n }\n\n private checkTruncation(): void {\n // Query for the elements using unique identifiers\n const titleEl = document.querySelector('.fd-notification__title') as HTMLElement;\n const paragraphEl = document.querySelector('.fd-notification__paragraph') as HTMLElement;\n\n if (titleEl || paragraphEl) {\n const titleTruncated = titleEl ? titleEl.scrollHeight > titleEl.clientHeight : false;\n const paragraphTruncated = paragraphEl ? paragraphEl.scrollHeight > paragraphEl.clientHeight : false;\n\n this.isTruncated.set(titleTruncated || paragraphTruncated);\n }\n }\n}\n" + }, { "name": "notification-options-example", "description": "Notification Options", @@ -42514,6 +42544,18 @@ "description": "ARIA label for the popover body", "required": false }, + { + "name": "bodyAriaLabelledBy", + "type": "null | string", + "description": "ID of the element that labels the popover body. Alternative to\n[bodyAriaLabel] when the label already exists in the DOM (e.g. the\ntrigger's text). Sets aria-labelledby on the popover body.", + "required": false + }, + { + "name": "bodyRole", + "type": "null | PopoverBodyRole | unknown", + "description": "ARIA role for the popover body. Default: 'dialog' (back-compat).\n\nWhen 'dialog', WCAG requires an accessible name — provide one via\n[bodyAriaLabel] or [bodyAriaLabelledBy]. Without a name, axe-core\nraises aria-dialog-name violations.\n\nSet to null when the popover is a non-modal disclosure widget and\nthe trigger's aria-haspopup already carries the relationship (no role\nattribute is rendered). Other valid values: 'region', 'menu', 'listbox',\n'tooltip', 'alertdialog' — match the role to the popover's actual semantics.\nAny valid ARIA role is accepted; the type provides autocomplete for common cases.", + "required": false + }, { "name": "cdkPositions", "type": "null | ConnectedPosition[]", @@ -42776,18 +42818,18 @@ "typescript": "import { Component, ViewEncapsulation } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverBodyDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-closing-example',\n templateUrl: './popover-closing-example.component.html',\n styleUrls: ['./popover-closing-example.component.scss'],\n encapsulation: ViewEncapsulation.None,\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n ButtonComponent,\n PopoverBodyHeaderDirective,\n PopoverBodyDirective,\n AvatarComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective\n ]\n})\nexport class PopoverClosingExampleComponent {}\n", "html": "
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n \n \n \n \n \n \n
    \n

    This popover stays open during router navigation.

    \n
    \n
    \n
    \n
    \n" }, - { - "name": "popover-complex-example", - "description": "Popover Complex", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-popover-complex-example',\n templateUrl: './popover-complex-example.component.html',\n styleUrls: ['./popover-complex-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonComponent,\n PopoverBodyComponent,\n TitleComponent,\n AvatarComponent,\n PopoverBodyHeaderDirective,\n ContentDensityDirective,\n PopoverBodyFooterDirective\n ]\n})\nexport class PopoverComplexExampleComponent {}\n", - "html": "
    \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n
    \n SubHeader\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n" - }, { "name": "popover-container-example", "description": "Popover Container", "typescript": "import { Component } from '@angular/core';\nimport { FocusableItemDirective } from '@fundamental-ngx/cdk';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-container-example',\n templateUrl: './popover-container-example.component.html',\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, FocusableItemDirective]\n})\nexport class PopoverContainerExampleComponent {}\n", "html": "

    appendTo

    \n

    Position the popover relative to a different element (the dashed box below).

    \n
    \n \n \n \n \n \n
    This popover is positioned relative to the container below
    \n
    \n
    \n
    \n\n
    Container (appendTo target)
    \n\n

    \n\n

    placementContainer

    \n

    \n Appends the overlay DOM element inside a container instead of body. Useful for z-index stacking contexts (e.g.,\n inside modals/dialogs). The popover still appears at the trigger, but its DOM is inside the container.\n

    \n
    \n \n \n \n \n \n
    Overlay DOM is inside the blue container
    \n
    \n
    \n (Inspect DOM to see overlay inside this container)\n
    \n" }, + { + "name": "popover-complex-example", + "description": "Popover Complex", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-popover-complex-example',\n templateUrl: './popover-complex-example.component.html',\n styleUrls: ['./popover-complex-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonComponent,\n PopoverBodyComponent,\n TitleComponent,\n AvatarComponent,\n PopoverBodyHeaderDirective,\n ContentDensityDirective,\n PopoverBodyFooterDirective\n ]\n})\nexport class PopoverComplexExampleComponent {}\n", + "html": "
    \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n
    \n SubHeader\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, { "name": "popover-dialog-example", "description": "Popover Dialog", @@ -42811,12 +42853,6 @@ "typescript": "import { Component, signal } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverComponent,\n PopoverContainerDirective,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-dynamic-container-height-example',\n templateUrl: './popover-dynamic-container-height-example.component.html',\n styles: [\n `\n .fd-docs-flex-display-helper {\n display: flex;\n align-items: center;\n justify-content: space-around;\n flex-flow: row wrap;\n width: 100%;\n }\n `\n ],\n imports: [\n PopoverContainerDirective,\n ButtonComponent,\n PopoverComponent,\n PopoverControlComponent,\n AvatarComponent,\n PopoverBodyComponent\n ]\n})\nexport class PopoverDynamicContainerHeightExampleComponent {\n showOverflowContainer = signal(false);\n\n private _overflowContainerTimeout: ReturnType | null = null;\n\n resetOverflowContainer(): void {\n if (this._overflowContainerTimeout) {\n clearTimeout(this._overflowContainerTimeout);\n }\n this.showOverflowContainer.set(false);\n this._overflowContainerTimeout = setTimeout(() => {\n this.showOverflowContainer.set(true);\n }, 2000);\n }\n}\n", "html": "
    \n @if (showOverflowContainer()) {\n
    \n }\n \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" }, - { - "name": "popover-focus-example", - "description": "Popover Focus", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-focus-example',\n templateUrl: './popover-focus-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n PopoverBodyHeaderDirective,\n BarModule,\n AvatarComponent,\n PopoverBodyFooterDirective,\n ContentDensityDirective\n ]\n})\nexport class PopoverFocusExampleComponent {}\n", - "html": "

    Focus Trapped & Auto Capture (default behavior)

    \n\n \n \n \n \n
    \n
    \n
    \n \n Header\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n

    \n\n

    Focus NOT Auto Captured

    \n\n \n \n \n \n
    \n

    Focus is not automatically moved to this popover when opened.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Restore Focus On Close (default: true)

    \n\n \n \n \n \n
    \n

    When closed, focus returns to the trigger button.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Do NOT Restore Focus On Close

    \n\n \n \n \n \n
    \n

    When closed, focus does NOT return to the trigger.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Prevent Space Key Scroll (default: true)

    \n

    \n By default, pressing Space on the trigger prevents page scrolling. Set\n [preventSpaceKeyScroll]=\"false\" to allow normal scroll behavior.\n

    \n\n \n \n \n \n
    \n

    When this popover's trigger is focused, pressing Space allows page scroll.

    \n
    \n
    \n
    \n" - }, { "name": "popover-inside-popover-example", "description": "Popover Inside Popover", @@ -42828,6 +42864,12 @@ "description": "Popover Lazy Init Of Body", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyDirective,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { PopoverLazyLoadedBodyComponent } from './popover-lazy-loaded-body.component';\n\n@Component({\n selector: 'fd-popover-lazy-init-of-body-example',\n template: `\n \n \n \n \n \n

    Header

    \n \n
    Footer
    \n
    \n
    \n `,\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyDirective,\n PopoverBodyHeaderDirective,\n PopoverBodyFooterDirective,\n ButtonComponent,\n PopoverLazyLoadedBodyComponent\n ]\n})\nexport class PopoverLazyInitOfBodyExampleComponent {}\n" }, + { + "name": "popover-focus-example", + "description": "Popover Focus", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-focus-example',\n templateUrl: './popover-focus-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n PopoverBodyHeaderDirective,\n BarModule,\n AvatarComponent,\n PopoverBodyFooterDirective,\n ContentDensityDirective\n ]\n})\nexport class PopoverFocusExampleComponent {}\n", + "html": "

    Focus Trapped & Auto Capture (default behavior)

    \n\n \n \n \n \n
    \n
    \n
    \n \n Header\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n

    \n\n

    Focus NOT Auto Captured

    \n\n \n \n \n \n
    \n

    Focus is not automatically moved to this popover when opened.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Restore Focus On Close (default: true)

    \n\n \n \n \n \n
    \n

    When closed, focus returns to the trigger button.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Do NOT Restore Focus On Close

    \n\n \n \n \n \n
    \n

    When closed, focus does NOT return to the trigger.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Prevent Space Key Scroll (default: true)

    \n

    \n By default, pressing Space on the trigger prevents page scrolling. Set\n [preventSpaceKeyScroll]=\"false\" to allow normal scroll behavior.\n

    \n\n \n \n \n \n
    \n

    When this popover's trigger is focused, pressing Space allows page scroll.

    \n
    \n
    \n
    \n" + }, { "name": "popover-mobile-example", "description": "Popover Mobile", @@ -42840,30 +42882,30 @@ "typescript": "import { ConnectionPositionPair } from '@angular/cdk/overlay';\nimport { Component, signal, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport { XPositions, YPositions } from '@fundamental-ngx/core/shared';\n\n@Component({\n selector: 'fd-popover-cdk-placement-example',\n templateUrl: './popover-cdk-placement-example.component.html',\n imports: [\n FormLabelComponent,\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent\n ]\n})\nexport class PopoverCdkPlacementExampleComponent {\n readonly popover = viewChild(PopoverComponent);\n\n readonly yPositions: YPositions[] = ['bottom', 'center', 'top'];\n readonly xPositions: XPositions[] = ['start', 'center', 'end'];\n\n originX = signal('center');\n originY = signal('center');\n overlayX = signal('center');\n overlayY = signal('center');\n\n cdkPosition = signal(this._buildCdkPositionObject());\n\n refresh(): void {\n this.cdkPosition.set(this._buildCdkPositionObject());\n this.popover()?.applyNewPosition(this.cdkPosition());\n }\n\n private _buildCdkPositionObject(): ConnectionPositionPair[] {\n return [\n {\n originX: this.originX(),\n originY: this.originY(),\n overlayX: this.overlayX(),\n overlayY: this.overlayY()\n }\n ];\n }\n}\n", "html": "
    \n \n \n @for (option of xPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of yPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of xPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of yPositions; track option) {\n \n }\n \n
    \n

    \n\n \n \n \n \n \n \n \n \n\n" }, - { - "name": "popover-placement-example", - "description": "Popover Placement", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-placement-example',\n templateUrl: './popover-placement-example.component.html',\n styleUrls: ['popover-placement-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, AvatarComponent]\n})\nexport class PopoverPlacementExampleComponent {}\n", - "html": "
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" - }, { "name": "popover-programmatic-open-example", "description": "Popover Programmatic Open", "typescript": "import { JsonPipe } from '@angular/common';\nimport { Component, signal } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverComponent,\n PopoverConfig,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-programmatic-open-example',\n templateUrl: './popover-programmatic-open-example.component.html',\n styleUrls: ['popover-programmatic-open-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n AvatarComponent,\n PopoverBodyComponent,\n ButtonComponent,\n JsonPipe\n ]\n})\nexport class PopoverProgrammaticOpenExampleComponent {\n /** Signal-based open state for two-way binding */\n isOpen = signal(false);\n\n /** Disabled state for the popover */\n isDisabled = signal(false);\n\n /** Config object example - can be used instead of individual inputs */\n popoverConfig: PopoverConfig = {\n placement: 'bottom-start',\n noArrow: false,\n closeOnEscapeKey: true,\n focusTrapped: true\n };\n\n /** Track open/close events */\n eventLog = signal([]);\n\n /** Called before popover opens */\n onBeforeOpen(): void {\n this.addToLog('beforeOpen event fired');\n }\n\n /** Called when open state changes */\n onOpenChange(isOpen: boolean): void {\n this.addToLog(`isOpenChange: ${isOpen}`);\n }\n\n /** Toggle disabled state */\n toggleDisabled(): void {\n this.isDisabled.update((v) => !v);\n this.addToLog(`Popover ${this.isDisabled() ? 'disabled' : 'enabled'}`);\n }\n\n /** Clear event log */\n clearLog(): void {\n this.eventLog.set([]);\n }\n\n private addToLog(message: string): void {\n this.eventLog.update((log) => [...log, `${new Date().toLocaleTimeString()}: ${message}`]);\n }\n}\n", "html": "\n

    Signal-based Programmatic Control

    \n
    \n \n \n \n \n \n \n \n \n \n \n \n
    \n\n\n

    Using Config Object

    \n\n \n \n \n \n
    \n

    This popover uses the [config] input:

    \n
    {{ popoverConfig | json }}
    \n
    \n
    \n
    \n\n\n

    Event Log

    \n
    \n @if (eventLog().length === 0) {\n

    No events yet. Open the popover to see events.

    \n } @else {\n
      \n @for (event of eventLog(); track event) {\n
    • {{ event }}
    • \n }\n
    \n \n }\n
    \n" }, + { + "name": "popover-non-dialog-example", + "description": "Popover Non Dialog", + "typescript": "import { Component } from '@angular/core';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-non-dialog-example',\n templateUrl: './popover-non-dialog-example.component.html',\n imports: [PopoverModule]\n})\nexport class PopoverNonDialogExampleComponent {}\n", + "html": "

    \n Use [bodyRole]=\"region\" (or null) when the popover is a non-modal disclosure rather than a\n dialog. Match the role to the popover's actual ARIA semantics.\n

    \n\n\n \n \n \n \n
    \n

    Quick Filters

    \n \n \n
    \n
    \n
    \n" + }, + { + "name": "popover-placement-example", + "description": "Popover Placement", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-placement-example',\n templateUrl: './popover-placement-example.component.html',\n styleUrls: ['popover-placement-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, AvatarComponent]\n})\nexport class PopoverPlacementExampleComponent {}\n", + "html": "
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" + }, { "name": "popover-resizable-example", "description": "Popover Resizable", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-resizable-example',\n templateUrl: './popover-resizable-example.component.html',\n styleUrls: ['popover-resizable-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent]\n})\nexport class PopoverResizableExampleComponent {}\n", "html": "
    \n \n \n \n \n\n \n
    \n

    Resizable content area

    \n

    \n Drag the resize handle to make room for longer content, tables, previews, or forms while keeping the\n popover within its configured limits.\n

    \n \n
    \n
    \n
    \n
    \n" }, - { - "name": "popover-scroll-example", - "description": "Popover Scroll", - "typescript": "import { Overlay, ScrollStrategy } from '@angular/cdk/overlay';\nimport { Component, inject } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-scroll-example',\n templateUrl: './popover-scroll-example.component.html',\n styleUrls: ['./popover-scroll-example.component.scss'],\n imports: [\n FormLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class PopoverScrollExampleComponent {\n /** Do nothing on scroll. */\n noopScrollStrategy: ScrollStrategy;\n\n /**\n * Close the overlay as soon as the user scrolls.\n * @param config Configuration to be used inside the scroll strategy.\n */\n closeScrollStrategy: ScrollStrategy;\n\n /** Block scrolling. */\n blockScrollStrategy: ScrollStrategy;\n\n /** Whether to close the overlay once the user has scrolled away completely. */\n autoClose = false;\n\n /** Time in milliseconds to throttle the scroll events. Use to increase performance. */\n scrollThrottle = 0;\n\n /**\n * Update the overlay's position on scroll.\n * @param config Configuration to be used inside the scroll strategy.\n * Allows debouncing the reposition calls.\n */\n repositionScrollStrategy: ScrollStrategy;\n\n private readonly _overlay = inject(Overlay);\n\n constructor() {\n this.noopScrollStrategy = this._overlay.scrollStrategies.noop();\n this.closeScrollStrategy = this._overlay.scrollStrategies.close();\n this.blockScrollStrategy = this._overlay.scrollStrategies.block();\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n\n refreshRepositionScrollStrategy(): void {\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n}\n", - "html": "\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n Close the overlay once the user has scrolled away completely?\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n" - }, { "name": "popover-example", "description": "Popover", @@ -42875,6 +42917,12 @@ "description": "Popover Trigger", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverComponent, PopoverTriggerDirective } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-trigger-example',\n templateUrl: './popover-trigger-example.component.html',\n imports: [ButtonComponent, PopoverTriggerDirective, PopoverComponent]\n})\nexport class PopoverTriggerExampleComponent {}\n", "html": "\n\n\n
    This popover is connected to trigger element
    \n
    \n" + }, + { + "name": "popover-scroll-example", + "description": "Popover Scroll", + "typescript": "import { Overlay, ScrollStrategy } from '@angular/cdk/overlay';\nimport { Component, inject } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-scroll-example',\n templateUrl: './popover-scroll-example.component.html',\n styleUrls: ['./popover-scroll-example.component.scss'],\n imports: [\n FormLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class PopoverScrollExampleComponent {\n /** Do nothing on scroll. */\n noopScrollStrategy: ScrollStrategy;\n\n /**\n * Close the overlay as soon as the user scrolls.\n * @param config Configuration to be used inside the scroll strategy.\n */\n closeScrollStrategy: ScrollStrategy;\n\n /** Block scrolling. */\n blockScrollStrategy: ScrollStrategy;\n\n /** Whether to close the overlay once the user has scrolled away completely. */\n autoClose = false;\n\n /** Time in milliseconds to throttle the scroll events. Use to increase performance. */\n scrollThrottle = 0;\n\n /**\n * Update the overlay's position on scroll.\n * @param config Configuration to be used inside the scroll strategy.\n * Allows debouncing the reposition calls.\n */\n repositionScrollStrategy: ScrollStrategy;\n\n private readonly _overlay = inject(Overlay);\n\n constructor() {\n this.noopScrollStrategy = this._overlay.scrollStrategies.noop();\n this.closeScrollStrategy = this._overlay.scrollStrategies.close();\n this.blockScrollStrategy = this._overlay.scrollStrategies.block();\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n\n refreshRepositionScrollStrategy(): void {\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n}\n", + "html": "\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n Close the overlay once the user has scrolled away completely?\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n" } ] }, @@ -42943,18 +42991,18 @@ "typescript": "import { Component, ViewEncapsulation } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverBodyDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-closing-example',\n templateUrl: './popover-closing-example.component.html',\n styleUrls: ['./popover-closing-example.component.scss'],\n encapsulation: ViewEncapsulation.None,\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n ButtonComponent,\n PopoverBodyHeaderDirective,\n PopoverBodyDirective,\n AvatarComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective\n ]\n})\nexport class PopoverClosingExampleComponent {}\n", "html": "
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n \n \n \n \n \n \n
    \n

    This popover stays open during router navigation.

    \n
    \n
    \n
    \n
    \n" }, - { - "name": "popover-complex-example", - "description": "Popover Complex", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-popover-complex-example',\n templateUrl: './popover-complex-example.component.html',\n styleUrls: ['./popover-complex-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonComponent,\n PopoverBodyComponent,\n TitleComponent,\n AvatarComponent,\n PopoverBodyHeaderDirective,\n ContentDensityDirective,\n PopoverBodyFooterDirective\n ]\n})\nexport class PopoverComplexExampleComponent {}\n", - "html": "
    \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n
    \n SubHeader\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n" - }, { "name": "popover-container-example", "description": "Popover Container", "typescript": "import { Component } from '@angular/core';\nimport { FocusableItemDirective } from '@fundamental-ngx/cdk';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-container-example',\n templateUrl: './popover-container-example.component.html',\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, FocusableItemDirective]\n})\nexport class PopoverContainerExampleComponent {}\n", "html": "

    appendTo

    \n

    Position the popover relative to a different element (the dashed box below).

    \n
    \n \n \n \n \n \n
    This popover is positioned relative to the container below
    \n
    \n
    \n
    \n\n
    Container (appendTo target)
    \n\n

    \n\n

    placementContainer

    \n

    \n Appends the overlay DOM element inside a container instead of body. Useful for z-index stacking contexts (e.g.,\n inside modals/dialogs). The popover still appears at the trigger, but its DOM is inside the container.\n

    \n
    \n \n \n \n \n \n
    Overlay DOM is inside the blue container
    \n
    \n
    \n (Inspect DOM to see overlay inside this container)\n
    \n" }, + { + "name": "popover-complex-example", + "description": "Popover Complex", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-popover-complex-example',\n templateUrl: './popover-complex-example.component.html',\n styleUrls: ['./popover-complex-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonComponent,\n PopoverBodyComponent,\n TitleComponent,\n AvatarComponent,\n PopoverBodyHeaderDirective,\n ContentDensityDirective,\n PopoverBodyFooterDirective\n ]\n})\nexport class PopoverComplexExampleComponent {}\n", + "html": "
    \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n
    \n SubHeader\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, { "name": "popover-dialog-example", "description": "Popover Dialog", @@ -42978,12 +43026,6 @@ "typescript": "import { Component, signal } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverComponent,\n PopoverContainerDirective,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-dynamic-container-height-example',\n templateUrl: './popover-dynamic-container-height-example.component.html',\n styles: [\n `\n .fd-docs-flex-display-helper {\n display: flex;\n align-items: center;\n justify-content: space-around;\n flex-flow: row wrap;\n width: 100%;\n }\n `\n ],\n imports: [\n PopoverContainerDirective,\n ButtonComponent,\n PopoverComponent,\n PopoverControlComponent,\n AvatarComponent,\n PopoverBodyComponent\n ]\n})\nexport class PopoverDynamicContainerHeightExampleComponent {\n showOverflowContainer = signal(false);\n\n private _overflowContainerTimeout: ReturnType | null = null;\n\n resetOverflowContainer(): void {\n if (this._overflowContainerTimeout) {\n clearTimeout(this._overflowContainerTimeout);\n }\n this.showOverflowContainer.set(false);\n this._overflowContainerTimeout = setTimeout(() => {\n this.showOverflowContainer.set(true);\n }, 2000);\n }\n}\n", "html": "
    \n @if (showOverflowContainer()) {\n
    \n }\n \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" }, - { - "name": "popover-focus-example", - "description": "Popover Focus", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-focus-example',\n templateUrl: './popover-focus-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n PopoverBodyHeaderDirective,\n BarModule,\n AvatarComponent,\n PopoverBodyFooterDirective,\n ContentDensityDirective\n ]\n})\nexport class PopoverFocusExampleComponent {}\n", - "html": "

    Focus Trapped & Auto Capture (default behavior)

    \n\n \n \n \n \n
    \n
    \n
    \n \n Header\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n

    \n\n

    Focus NOT Auto Captured

    \n\n \n \n \n \n
    \n

    Focus is not automatically moved to this popover when opened.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Restore Focus On Close (default: true)

    \n\n \n \n \n \n
    \n

    When closed, focus returns to the trigger button.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Do NOT Restore Focus On Close

    \n\n \n \n \n \n
    \n

    When closed, focus does NOT return to the trigger.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Prevent Space Key Scroll (default: true)

    \n

    \n By default, pressing Space on the trigger prevents page scrolling. Set\n [preventSpaceKeyScroll]=\"false\" to allow normal scroll behavior.\n

    \n\n \n \n \n \n
    \n

    When this popover's trigger is focused, pressing Space allows page scroll.

    \n
    \n
    \n
    \n" - }, { "name": "popover-inside-popover-example", "description": "Popover Inside Popover", @@ -42995,6 +43037,12 @@ "description": "Popover Lazy Init Of Body", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyDirective,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { PopoverLazyLoadedBodyComponent } from './popover-lazy-loaded-body.component';\n\n@Component({\n selector: 'fd-popover-lazy-init-of-body-example',\n template: `\n \n \n \n \n \n

    Header

    \n \n
    Footer
    \n
    \n
    \n `,\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyDirective,\n PopoverBodyHeaderDirective,\n PopoverBodyFooterDirective,\n ButtonComponent,\n PopoverLazyLoadedBodyComponent\n ]\n})\nexport class PopoverLazyInitOfBodyExampleComponent {}\n" }, + { + "name": "popover-focus-example", + "description": "Popover Focus", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-focus-example',\n templateUrl: './popover-focus-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n PopoverBodyHeaderDirective,\n BarModule,\n AvatarComponent,\n PopoverBodyFooterDirective,\n ContentDensityDirective\n ]\n})\nexport class PopoverFocusExampleComponent {}\n", + "html": "

    Focus Trapped & Auto Capture (default behavior)

    \n\n \n \n \n \n
    \n
    \n
    \n \n Header\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n

    \n\n

    Focus NOT Auto Captured

    \n\n \n \n \n \n
    \n

    Focus is not automatically moved to this popover when opened.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Restore Focus On Close (default: true)

    \n\n \n \n \n \n
    \n

    When closed, focus returns to the trigger button.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Do NOT Restore Focus On Close

    \n\n \n \n \n \n
    \n

    When closed, focus does NOT return to the trigger.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Prevent Space Key Scroll (default: true)

    \n

    \n By default, pressing Space on the trigger prevents page scrolling. Set\n [preventSpaceKeyScroll]=\"false\" to allow normal scroll behavior.\n

    \n\n \n \n \n \n
    \n

    When this popover's trigger is focused, pressing Space allows page scroll.

    \n
    \n
    \n
    \n" + }, { "name": "popover-mobile-example", "description": "Popover Mobile", @@ -43007,30 +43055,30 @@ "typescript": "import { ConnectionPositionPair } from '@angular/cdk/overlay';\nimport { Component, signal, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport { XPositions, YPositions } from '@fundamental-ngx/core/shared';\n\n@Component({\n selector: 'fd-popover-cdk-placement-example',\n templateUrl: './popover-cdk-placement-example.component.html',\n imports: [\n FormLabelComponent,\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent\n ]\n})\nexport class PopoverCdkPlacementExampleComponent {\n readonly popover = viewChild(PopoverComponent);\n\n readonly yPositions: YPositions[] = ['bottom', 'center', 'top'];\n readonly xPositions: XPositions[] = ['start', 'center', 'end'];\n\n originX = signal('center');\n originY = signal('center');\n overlayX = signal('center');\n overlayY = signal('center');\n\n cdkPosition = signal(this._buildCdkPositionObject());\n\n refresh(): void {\n this.cdkPosition.set(this._buildCdkPositionObject());\n this.popover()?.applyNewPosition(this.cdkPosition());\n }\n\n private _buildCdkPositionObject(): ConnectionPositionPair[] {\n return [\n {\n originX: this.originX(),\n originY: this.originY(),\n overlayX: this.overlayX(),\n overlayY: this.overlayY()\n }\n ];\n }\n}\n", "html": "
    \n \n \n @for (option of xPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of yPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of xPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of yPositions; track option) {\n \n }\n \n
    \n

    \n\n \n \n \n \n \n \n \n \n\n" }, - { - "name": "popover-placement-example", - "description": "Popover Placement", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-placement-example',\n templateUrl: './popover-placement-example.component.html',\n styleUrls: ['popover-placement-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, AvatarComponent]\n})\nexport class PopoverPlacementExampleComponent {}\n", - "html": "
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" - }, { "name": "popover-programmatic-open-example", "description": "Popover Programmatic Open", "typescript": "import { JsonPipe } from '@angular/common';\nimport { Component, signal } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverComponent,\n PopoverConfig,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-programmatic-open-example',\n templateUrl: './popover-programmatic-open-example.component.html',\n styleUrls: ['popover-programmatic-open-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n AvatarComponent,\n PopoverBodyComponent,\n ButtonComponent,\n JsonPipe\n ]\n})\nexport class PopoverProgrammaticOpenExampleComponent {\n /** Signal-based open state for two-way binding */\n isOpen = signal(false);\n\n /** Disabled state for the popover */\n isDisabled = signal(false);\n\n /** Config object example - can be used instead of individual inputs */\n popoverConfig: PopoverConfig = {\n placement: 'bottom-start',\n noArrow: false,\n closeOnEscapeKey: true,\n focusTrapped: true\n };\n\n /** Track open/close events */\n eventLog = signal([]);\n\n /** Called before popover opens */\n onBeforeOpen(): void {\n this.addToLog('beforeOpen event fired');\n }\n\n /** Called when open state changes */\n onOpenChange(isOpen: boolean): void {\n this.addToLog(`isOpenChange: ${isOpen}`);\n }\n\n /** Toggle disabled state */\n toggleDisabled(): void {\n this.isDisabled.update((v) => !v);\n this.addToLog(`Popover ${this.isDisabled() ? 'disabled' : 'enabled'}`);\n }\n\n /** Clear event log */\n clearLog(): void {\n this.eventLog.set([]);\n }\n\n private addToLog(message: string): void {\n this.eventLog.update((log) => [...log, `${new Date().toLocaleTimeString()}: ${message}`]);\n }\n}\n", "html": "\n

    Signal-based Programmatic Control

    \n
    \n \n \n \n \n \n \n \n \n \n \n \n
    \n\n\n

    Using Config Object

    \n\n \n \n \n \n
    \n

    This popover uses the [config] input:

    \n
    {{ popoverConfig | json }}
    \n
    \n
    \n
    \n\n\n

    Event Log

    \n
    \n @if (eventLog().length === 0) {\n

    No events yet. Open the popover to see events.

    \n } @else {\n
      \n @for (event of eventLog(); track event) {\n
    • {{ event }}
    • \n }\n
    \n \n }\n
    \n" }, + { + "name": "popover-non-dialog-example", + "description": "Popover Non Dialog", + "typescript": "import { Component } from '@angular/core';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-non-dialog-example',\n templateUrl: './popover-non-dialog-example.component.html',\n imports: [PopoverModule]\n})\nexport class PopoverNonDialogExampleComponent {}\n", + "html": "

    \n Use [bodyRole]=\"region\" (or null) when the popover is a non-modal disclosure rather than a\n dialog. Match the role to the popover's actual ARIA semantics.\n

    \n\n\n \n \n \n \n
    \n

    Quick Filters

    \n \n \n
    \n
    \n
    \n" + }, + { + "name": "popover-placement-example", + "description": "Popover Placement", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-placement-example',\n templateUrl: './popover-placement-example.component.html',\n styleUrls: ['popover-placement-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, AvatarComponent]\n})\nexport class PopoverPlacementExampleComponent {}\n", + "html": "
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" + }, { "name": "popover-resizable-example", "description": "Popover Resizable", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-resizable-example',\n templateUrl: './popover-resizable-example.component.html',\n styleUrls: ['popover-resizable-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent]\n})\nexport class PopoverResizableExampleComponent {}\n", "html": "
    \n \n \n \n \n\n \n
    \n

    Resizable content area

    \n

    \n Drag the resize handle to make room for longer content, tables, previews, or forms while keeping the\n popover within its configured limits.\n

    \n \n
    \n
    \n
    \n
    \n" }, - { - "name": "popover-scroll-example", - "description": "Popover Scroll", - "typescript": "import { Overlay, ScrollStrategy } from '@angular/cdk/overlay';\nimport { Component, inject } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-scroll-example',\n templateUrl: './popover-scroll-example.component.html',\n styleUrls: ['./popover-scroll-example.component.scss'],\n imports: [\n FormLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class PopoverScrollExampleComponent {\n /** Do nothing on scroll. */\n noopScrollStrategy: ScrollStrategy;\n\n /**\n * Close the overlay as soon as the user scrolls.\n * @param config Configuration to be used inside the scroll strategy.\n */\n closeScrollStrategy: ScrollStrategy;\n\n /** Block scrolling. */\n blockScrollStrategy: ScrollStrategy;\n\n /** Whether to close the overlay once the user has scrolled away completely. */\n autoClose = false;\n\n /** Time in milliseconds to throttle the scroll events. Use to increase performance. */\n scrollThrottle = 0;\n\n /**\n * Update the overlay's position on scroll.\n * @param config Configuration to be used inside the scroll strategy.\n * Allows debouncing the reposition calls.\n */\n repositionScrollStrategy: ScrollStrategy;\n\n private readonly _overlay = inject(Overlay);\n\n constructor() {\n this.noopScrollStrategy = this._overlay.scrollStrategies.noop();\n this.closeScrollStrategy = this._overlay.scrollStrategies.close();\n this.blockScrollStrategy = this._overlay.scrollStrategies.block();\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n\n refreshRepositionScrollStrategy(): void {\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n}\n", - "html": "\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n Close the overlay once the user has scrolled away completely?\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n" - }, { "name": "popover-example", "description": "Popover", @@ -43042,6 +43090,12 @@ "description": "Popover Trigger", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverComponent, PopoverTriggerDirective } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-trigger-example',\n templateUrl: './popover-trigger-example.component.html',\n imports: [ButtonComponent, PopoverTriggerDirective, PopoverComponent]\n})\nexport class PopoverTriggerExampleComponent {}\n", "html": "\n\n\n
    This popover is connected to trigger element
    \n
    \n" + }, + { + "name": "popover-scroll-example", + "description": "Popover Scroll", + "typescript": "import { Overlay, ScrollStrategy } from '@angular/cdk/overlay';\nimport { Component, inject } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-scroll-example',\n templateUrl: './popover-scroll-example.component.html',\n styleUrls: ['./popover-scroll-example.component.scss'],\n imports: [\n FormLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class PopoverScrollExampleComponent {\n /** Do nothing on scroll. */\n noopScrollStrategy: ScrollStrategy;\n\n /**\n * Close the overlay as soon as the user scrolls.\n * @param config Configuration to be used inside the scroll strategy.\n */\n closeScrollStrategy: ScrollStrategy;\n\n /** Block scrolling. */\n blockScrollStrategy: ScrollStrategy;\n\n /** Whether to close the overlay once the user has scrolled away completely. */\n autoClose = false;\n\n /** Time in milliseconds to throttle the scroll events. Use to increase performance. */\n scrollThrottle = 0;\n\n /**\n * Update the overlay's position on scroll.\n * @param config Configuration to be used inside the scroll strategy.\n * Allows debouncing the reposition calls.\n */\n repositionScrollStrategy: ScrollStrategy;\n\n private readonly _overlay = inject(Overlay);\n\n constructor() {\n this.noopScrollStrategy = this._overlay.scrollStrategies.noop();\n this.closeScrollStrategy = this._overlay.scrollStrategies.close();\n this.blockScrollStrategy = this._overlay.scrollStrategies.block();\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n\n refreshRepositionScrollStrategy(): void {\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n}\n", + "html": "\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n Close the overlay once the user has scrolled away completely?\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n" } ] }, @@ -43065,18 +43119,18 @@ "typescript": "import { Component, ViewEncapsulation } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverBodyDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-closing-example',\n templateUrl: './popover-closing-example.component.html',\n styleUrls: ['./popover-closing-example.component.scss'],\n encapsulation: ViewEncapsulation.None,\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n ButtonComponent,\n PopoverBodyHeaderDirective,\n PopoverBodyDirective,\n AvatarComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective\n ]\n})\nexport class PopoverClosingExampleComponent {}\n", "html": "
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n \n \n \n \n \n \n
    \n

    This popover stays open during router navigation.

    \n
    \n
    \n
    \n
    \n" }, - { - "name": "popover-complex-example", - "description": "Popover Complex", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-popover-complex-example',\n templateUrl: './popover-complex-example.component.html',\n styleUrls: ['./popover-complex-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonComponent,\n PopoverBodyComponent,\n TitleComponent,\n AvatarComponent,\n PopoverBodyHeaderDirective,\n ContentDensityDirective,\n PopoverBodyFooterDirective\n ]\n})\nexport class PopoverComplexExampleComponent {}\n", - "html": "
    \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n
    \n SubHeader\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n" - }, { "name": "popover-container-example", "description": "Popover Container", "typescript": "import { Component } from '@angular/core';\nimport { FocusableItemDirective } from '@fundamental-ngx/cdk';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-container-example',\n templateUrl: './popover-container-example.component.html',\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, FocusableItemDirective]\n})\nexport class PopoverContainerExampleComponent {}\n", "html": "

    appendTo

    \n

    Position the popover relative to a different element (the dashed box below).

    \n
    \n \n \n \n \n \n
    This popover is positioned relative to the container below
    \n
    \n
    \n
    \n\n
    Container (appendTo target)
    \n\n

    \n\n

    placementContainer

    \n

    \n Appends the overlay DOM element inside a container instead of body. Useful for z-index stacking contexts (e.g.,\n inside modals/dialogs). The popover still appears at the trigger, but its DOM is inside the container.\n

    \n
    \n \n \n \n \n \n
    Overlay DOM is inside the blue container
    \n
    \n
    \n (Inspect DOM to see overlay inside this container)\n
    \n" }, + { + "name": "popover-complex-example", + "description": "Popover Complex", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-popover-complex-example',\n templateUrl: './popover-complex-example.component.html',\n styleUrls: ['./popover-complex-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonComponent,\n PopoverBodyComponent,\n TitleComponent,\n AvatarComponent,\n PopoverBodyHeaderDirective,\n ContentDensityDirective,\n PopoverBodyFooterDirective\n ]\n})\nexport class PopoverComplexExampleComponent {}\n", + "html": "
    \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n
    \n SubHeader\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, { "name": "popover-dialog-example", "description": "Popover Dialog", @@ -43100,12 +43154,6 @@ "typescript": "import { Component, signal } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverComponent,\n PopoverContainerDirective,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-dynamic-container-height-example',\n templateUrl: './popover-dynamic-container-height-example.component.html',\n styles: [\n `\n .fd-docs-flex-display-helper {\n display: flex;\n align-items: center;\n justify-content: space-around;\n flex-flow: row wrap;\n width: 100%;\n }\n `\n ],\n imports: [\n PopoverContainerDirective,\n ButtonComponent,\n PopoverComponent,\n PopoverControlComponent,\n AvatarComponent,\n PopoverBodyComponent\n ]\n})\nexport class PopoverDynamicContainerHeightExampleComponent {\n showOverflowContainer = signal(false);\n\n private _overflowContainerTimeout: ReturnType | null = null;\n\n resetOverflowContainer(): void {\n if (this._overflowContainerTimeout) {\n clearTimeout(this._overflowContainerTimeout);\n }\n this.showOverflowContainer.set(false);\n this._overflowContainerTimeout = setTimeout(() => {\n this.showOverflowContainer.set(true);\n }, 2000);\n }\n}\n", "html": "
    \n @if (showOverflowContainer()) {\n
    \n }\n \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" }, - { - "name": "popover-focus-example", - "description": "Popover Focus", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-focus-example',\n templateUrl: './popover-focus-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n PopoverBodyHeaderDirective,\n BarModule,\n AvatarComponent,\n PopoverBodyFooterDirective,\n ContentDensityDirective\n ]\n})\nexport class PopoverFocusExampleComponent {}\n", - "html": "

    Focus Trapped & Auto Capture (default behavior)

    \n\n \n \n \n \n
    \n
    \n
    \n \n Header\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n

    \n\n

    Focus NOT Auto Captured

    \n\n \n \n \n \n
    \n

    Focus is not automatically moved to this popover when opened.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Restore Focus On Close (default: true)

    \n\n \n \n \n \n
    \n

    When closed, focus returns to the trigger button.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Do NOT Restore Focus On Close

    \n\n \n \n \n \n
    \n

    When closed, focus does NOT return to the trigger.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Prevent Space Key Scroll (default: true)

    \n

    \n By default, pressing Space on the trigger prevents page scrolling. Set\n [preventSpaceKeyScroll]=\"false\" to allow normal scroll behavior.\n

    \n\n \n \n \n \n
    \n

    When this popover's trigger is focused, pressing Space allows page scroll.

    \n
    \n
    \n
    \n" - }, { "name": "popover-inside-popover-example", "description": "Popover Inside Popover", @@ -43117,6 +43165,12 @@ "description": "Popover Lazy Init Of Body", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyDirective,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { PopoverLazyLoadedBodyComponent } from './popover-lazy-loaded-body.component';\n\n@Component({\n selector: 'fd-popover-lazy-init-of-body-example',\n template: `\n \n \n \n \n \n

    Header

    \n \n
    Footer
    \n
    \n
    \n `,\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyDirective,\n PopoverBodyHeaderDirective,\n PopoverBodyFooterDirective,\n ButtonComponent,\n PopoverLazyLoadedBodyComponent\n ]\n})\nexport class PopoverLazyInitOfBodyExampleComponent {}\n" }, + { + "name": "popover-focus-example", + "description": "Popover Focus", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-focus-example',\n templateUrl: './popover-focus-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n PopoverBodyHeaderDirective,\n BarModule,\n AvatarComponent,\n PopoverBodyFooterDirective,\n ContentDensityDirective\n ]\n})\nexport class PopoverFocusExampleComponent {}\n", + "html": "

    Focus Trapped & Auto Capture (default behavior)

    \n\n \n \n \n \n
    \n
    \n
    \n \n Header\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n

    \n\n

    Focus NOT Auto Captured

    \n\n \n \n \n \n
    \n

    Focus is not automatically moved to this popover when opened.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Restore Focus On Close (default: true)

    \n\n \n \n \n \n
    \n

    When closed, focus returns to the trigger button.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Do NOT Restore Focus On Close

    \n\n \n \n \n \n
    \n

    When closed, focus does NOT return to the trigger.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Prevent Space Key Scroll (default: true)

    \n

    \n By default, pressing Space on the trigger prevents page scrolling. Set\n [preventSpaceKeyScroll]=\"false\" to allow normal scroll behavior.\n

    \n\n \n \n \n \n
    \n

    When this popover's trigger is focused, pressing Space allows page scroll.

    \n
    \n
    \n
    \n" + }, { "name": "popover-mobile-example", "description": "Popover Mobile", @@ -43129,30 +43183,30 @@ "typescript": "import { ConnectionPositionPair } from '@angular/cdk/overlay';\nimport { Component, signal, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport { XPositions, YPositions } from '@fundamental-ngx/core/shared';\n\n@Component({\n selector: 'fd-popover-cdk-placement-example',\n templateUrl: './popover-cdk-placement-example.component.html',\n imports: [\n FormLabelComponent,\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent\n ]\n})\nexport class PopoverCdkPlacementExampleComponent {\n readonly popover = viewChild(PopoverComponent);\n\n readonly yPositions: YPositions[] = ['bottom', 'center', 'top'];\n readonly xPositions: XPositions[] = ['start', 'center', 'end'];\n\n originX = signal('center');\n originY = signal('center');\n overlayX = signal('center');\n overlayY = signal('center');\n\n cdkPosition = signal(this._buildCdkPositionObject());\n\n refresh(): void {\n this.cdkPosition.set(this._buildCdkPositionObject());\n this.popover()?.applyNewPosition(this.cdkPosition());\n }\n\n private _buildCdkPositionObject(): ConnectionPositionPair[] {\n return [\n {\n originX: this.originX(),\n originY: this.originY(),\n overlayX: this.overlayX(),\n overlayY: this.overlayY()\n }\n ];\n }\n}\n", "html": "
    \n \n \n @for (option of xPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of yPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of xPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of yPositions; track option) {\n \n }\n \n
    \n

    \n\n \n \n \n \n \n \n \n \n\n" }, - { - "name": "popover-placement-example", - "description": "Popover Placement", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-placement-example',\n templateUrl: './popover-placement-example.component.html',\n styleUrls: ['popover-placement-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, AvatarComponent]\n})\nexport class PopoverPlacementExampleComponent {}\n", - "html": "
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" - }, { "name": "popover-programmatic-open-example", "description": "Popover Programmatic Open", "typescript": "import { JsonPipe } from '@angular/common';\nimport { Component, signal } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverComponent,\n PopoverConfig,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-programmatic-open-example',\n templateUrl: './popover-programmatic-open-example.component.html',\n styleUrls: ['popover-programmatic-open-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n AvatarComponent,\n PopoverBodyComponent,\n ButtonComponent,\n JsonPipe\n ]\n})\nexport class PopoverProgrammaticOpenExampleComponent {\n /** Signal-based open state for two-way binding */\n isOpen = signal(false);\n\n /** Disabled state for the popover */\n isDisabled = signal(false);\n\n /** Config object example - can be used instead of individual inputs */\n popoverConfig: PopoverConfig = {\n placement: 'bottom-start',\n noArrow: false,\n closeOnEscapeKey: true,\n focusTrapped: true\n };\n\n /** Track open/close events */\n eventLog = signal([]);\n\n /** Called before popover opens */\n onBeforeOpen(): void {\n this.addToLog('beforeOpen event fired');\n }\n\n /** Called when open state changes */\n onOpenChange(isOpen: boolean): void {\n this.addToLog(`isOpenChange: ${isOpen}`);\n }\n\n /** Toggle disabled state */\n toggleDisabled(): void {\n this.isDisabled.update((v) => !v);\n this.addToLog(`Popover ${this.isDisabled() ? 'disabled' : 'enabled'}`);\n }\n\n /** Clear event log */\n clearLog(): void {\n this.eventLog.set([]);\n }\n\n private addToLog(message: string): void {\n this.eventLog.update((log) => [...log, `${new Date().toLocaleTimeString()}: ${message}`]);\n }\n}\n", "html": "\n

    Signal-based Programmatic Control

    \n
    \n \n \n \n \n \n \n \n \n \n \n \n
    \n\n\n

    Using Config Object

    \n\n \n \n \n \n
    \n

    This popover uses the [config] input:

    \n
    {{ popoverConfig | json }}
    \n
    \n
    \n
    \n\n\n

    Event Log

    \n
    \n @if (eventLog().length === 0) {\n

    No events yet. Open the popover to see events.

    \n } @else {\n
      \n @for (event of eventLog(); track event) {\n
    • {{ event }}
    • \n }\n
    \n \n }\n
    \n" }, + { + "name": "popover-non-dialog-example", + "description": "Popover Non Dialog", + "typescript": "import { Component } from '@angular/core';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-non-dialog-example',\n templateUrl: './popover-non-dialog-example.component.html',\n imports: [PopoverModule]\n})\nexport class PopoverNonDialogExampleComponent {}\n", + "html": "

    \n Use [bodyRole]=\"region\" (or null) when the popover is a non-modal disclosure rather than a\n dialog. Match the role to the popover's actual ARIA semantics.\n

    \n\n\n \n \n \n \n
    \n

    Quick Filters

    \n \n \n
    \n
    \n
    \n" + }, + { + "name": "popover-placement-example", + "description": "Popover Placement", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-placement-example',\n templateUrl: './popover-placement-example.component.html',\n styleUrls: ['popover-placement-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, AvatarComponent]\n})\nexport class PopoverPlacementExampleComponent {}\n", + "html": "
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" + }, { "name": "popover-resizable-example", "description": "Popover Resizable", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-resizable-example',\n templateUrl: './popover-resizable-example.component.html',\n styleUrls: ['popover-resizable-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent]\n})\nexport class PopoverResizableExampleComponent {}\n", "html": "
    \n \n \n \n \n\n \n
    \n

    Resizable content area

    \n

    \n Drag the resize handle to make room for longer content, tables, previews, or forms while keeping the\n popover within its configured limits.\n

    \n \n
    \n
    \n
    \n
    \n" }, - { - "name": "popover-scroll-example", - "description": "Popover Scroll", - "typescript": "import { Overlay, ScrollStrategy } from '@angular/cdk/overlay';\nimport { Component, inject } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-scroll-example',\n templateUrl: './popover-scroll-example.component.html',\n styleUrls: ['./popover-scroll-example.component.scss'],\n imports: [\n FormLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class PopoverScrollExampleComponent {\n /** Do nothing on scroll. */\n noopScrollStrategy: ScrollStrategy;\n\n /**\n * Close the overlay as soon as the user scrolls.\n * @param config Configuration to be used inside the scroll strategy.\n */\n closeScrollStrategy: ScrollStrategy;\n\n /** Block scrolling. */\n blockScrollStrategy: ScrollStrategy;\n\n /** Whether to close the overlay once the user has scrolled away completely. */\n autoClose = false;\n\n /** Time in milliseconds to throttle the scroll events. Use to increase performance. */\n scrollThrottle = 0;\n\n /**\n * Update the overlay's position on scroll.\n * @param config Configuration to be used inside the scroll strategy.\n * Allows debouncing the reposition calls.\n */\n repositionScrollStrategy: ScrollStrategy;\n\n private readonly _overlay = inject(Overlay);\n\n constructor() {\n this.noopScrollStrategy = this._overlay.scrollStrategies.noop();\n this.closeScrollStrategy = this._overlay.scrollStrategies.close();\n this.blockScrollStrategy = this._overlay.scrollStrategies.block();\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n\n refreshRepositionScrollStrategy(): void {\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n}\n", - "html": "\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n Close the overlay once the user has scrolled away completely?\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n" - }, { "name": "popover-example", "description": "Popover", @@ -43164,6 +43218,12 @@ "description": "Popover Trigger", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverComponent, PopoverTriggerDirective } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-trigger-example',\n templateUrl: './popover-trigger-example.component.html',\n imports: [ButtonComponent, PopoverTriggerDirective, PopoverComponent]\n})\nexport class PopoverTriggerExampleComponent {}\n", "html": "\n\n\n
    This popover is connected to trigger element
    \n
    \n" + }, + { + "name": "popover-scroll-example", + "description": "Popover Scroll", + "typescript": "import { Overlay, ScrollStrategy } from '@angular/cdk/overlay';\nimport { Component, inject } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-scroll-example',\n templateUrl: './popover-scroll-example.component.html',\n styleUrls: ['./popover-scroll-example.component.scss'],\n imports: [\n FormLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class PopoverScrollExampleComponent {\n /** Do nothing on scroll. */\n noopScrollStrategy: ScrollStrategy;\n\n /**\n * Close the overlay as soon as the user scrolls.\n * @param config Configuration to be used inside the scroll strategy.\n */\n closeScrollStrategy: ScrollStrategy;\n\n /** Block scrolling. */\n blockScrollStrategy: ScrollStrategy;\n\n /** Whether to close the overlay once the user has scrolled away completely. */\n autoClose = false;\n\n /** Time in milliseconds to throttle the scroll events. Use to increase performance. */\n scrollThrottle = 0;\n\n /**\n * Update the overlay's position on scroll.\n * @param config Configuration to be used inside the scroll strategy.\n * Allows debouncing the reposition calls.\n */\n repositionScrollStrategy: ScrollStrategy;\n\n private readonly _overlay = inject(Overlay);\n\n constructor() {\n this.noopScrollStrategy = this._overlay.scrollStrategies.noop();\n this.closeScrollStrategy = this._overlay.scrollStrategies.close();\n this.blockScrollStrategy = this._overlay.scrollStrategies.block();\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n\n refreshRepositionScrollStrategy(): void {\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n}\n", + "html": "\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n Close the overlay once the user has scrolled away completely?\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n" } ] }, @@ -43213,18 +43273,18 @@ "typescript": "import { Component, ViewEncapsulation } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverBodyDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-closing-example',\n templateUrl: './popover-closing-example.component.html',\n styleUrls: ['./popover-closing-example.component.scss'],\n encapsulation: ViewEncapsulation.None,\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n ButtonComponent,\n PopoverBodyHeaderDirective,\n PopoverBodyDirective,\n AvatarComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective\n ]\n})\nexport class PopoverClosingExampleComponent {}\n", "html": "
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n \n \n \n \n \n
    \n
    \n
    \n \n
    Header
    \n
    \n
    \n
    \n \n
    \n \n \n \n \n \n \n
    \n

    This popover stays open during router navigation.

    \n
    \n
    \n
    \n
    \n" }, - { - "name": "popover-complex-example", - "description": "Popover Complex", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-popover-complex-example',\n templateUrl: './popover-complex-example.component.html',\n styleUrls: ['./popover-complex-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonComponent,\n PopoverBodyComponent,\n TitleComponent,\n AvatarComponent,\n PopoverBodyHeaderDirective,\n ContentDensityDirective,\n PopoverBodyFooterDirective\n ]\n})\nexport class PopoverComplexExampleComponent {}\n", - "html": "
    \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n
    \n SubHeader\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n" - }, { "name": "popover-container-example", "description": "Popover Container", "typescript": "import { Component } from '@angular/core';\nimport { FocusableItemDirective } from '@fundamental-ngx/cdk';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-container-example',\n templateUrl: './popover-container-example.component.html',\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, FocusableItemDirective]\n})\nexport class PopoverContainerExampleComponent {}\n", "html": "

    appendTo

    \n

    Position the popover relative to a different element (the dashed box below).

    \n
    \n \n \n \n \n \n
    This popover is positioned relative to the container below
    \n
    \n
    \n
    \n\n
    Container (appendTo target)
    \n\n

    \n\n

    placementContainer

    \n

    \n Appends the overlay DOM element inside a container instead of body. Useful for z-index stacking contexts (e.g.,\n inside modals/dialogs). The popover still appears at the trigger, but its DOM is inside the container.\n

    \n
    \n \n \n \n \n \n
    Overlay DOM is inside the blue container
    \n
    \n
    \n (Inspect DOM to see overlay inside this container)\n
    \n" }, + { + "name": "popover-complex-example", + "description": "Popover Complex", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport {\n BarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonBarComponent\n} from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { TitleComponent } from '@fundamental-ngx/core/title';\n\n@Component({\n selector: 'fd-popover-complex-example',\n templateUrl: './popover-complex-example.component.html',\n styleUrls: ['./popover-complex-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n BarComponent,\n ButtonBarComponent,\n BarElementDirective,\n BarLeftDirective,\n BarMiddleDirective,\n BarRightDirective,\n ButtonComponent,\n PopoverBodyComponent,\n TitleComponent,\n AvatarComponent,\n PopoverBodyHeaderDirective,\n ContentDensityDirective,\n PopoverBodyFooterDirective\n ]\n})\nexport class PopoverComplexExampleComponent {}\n", + "html": "
    \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n \n \n \n \n \n
    \n
    \n
    \n
    Header
    \n
    \n
    \n
    \n
    \n SubHeader\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, { "name": "popover-dialog-example", "description": "Popover Dialog", @@ -43248,12 +43308,6 @@ "typescript": "import { Component, signal } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverComponent,\n PopoverContainerDirective,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-dynamic-container-height-example',\n templateUrl: './popover-dynamic-container-height-example.component.html',\n styles: [\n `\n .fd-docs-flex-display-helper {\n display: flex;\n align-items: center;\n justify-content: space-around;\n flex-flow: row wrap;\n width: 100%;\n }\n `\n ],\n imports: [\n PopoverContainerDirective,\n ButtonComponent,\n PopoverComponent,\n PopoverControlComponent,\n AvatarComponent,\n PopoverBodyComponent\n ]\n})\nexport class PopoverDynamicContainerHeightExampleComponent {\n showOverflowContainer = signal(false);\n\n private _overflowContainerTimeout: ReturnType | null = null;\n\n resetOverflowContainer(): void {\n if (this._overflowContainerTimeout) {\n clearTimeout(this._overflowContainerTimeout);\n }\n this.showOverflowContainer.set(false);\n this._overflowContainerTimeout = setTimeout(() => {\n this.showOverflowContainer.set(true);\n }, 2000);\n }\n}\n", "html": "
    \n @if (showOverflowContainer()) {\n
    \n }\n \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" }, - { - "name": "popover-focus-example", - "description": "Popover Focus", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-focus-example',\n templateUrl: './popover-focus-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n PopoverBodyHeaderDirective,\n BarModule,\n AvatarComponent,\n PopoverBodyFooterDirective,\n ContentDensityDirective\n ]\n})\nexport class PopoverFocusExampleComponent {}\n", - "html": "

    Focus Trapped & Auto Capture (default behavior)

    \n\n \n \n \n \n
    \n
    \n
    \n \n Header\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n

    \n\n

    Focus NOT Auto Captured

    \n\n \n \n \n \n
    \n

    Focus is not automatically moved to this popover when opened.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Restore Focus On Close (default: true)

    \n\n \n \n \n \n
    \n

    When closed, focus returns to the trigger button.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Do NOT Restore Focus On Close

    \n\n \n \n \n \n
    \n

    When closed, focus does NOT return to the trigger.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Prevent Space Key Scroll (default: true)

    \n

    \n By default, pressing Space on the trigger prevents page scrolling. Set\n [preventSpaceKeyScroll]=\"false\" to allow normal scroll behavior.\n

    \n\n \n \n \n \n
    \n

    When this popover's trigger is focused, pressing Space allows page scroll.

    \n
    \n
    \n
    \n" - }, { "name": "popover-inside-popover-example", "description": "Popover Inside Popover", @@ -43265,6 +43319,12 @@ "description": "Popover Lazy Init Of Body", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyDirective,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\nimport { PopoverLazyLoadedBodyComponent } from './popover-lazy-loaded-body.component';\n\n@Component({\n selector: 'fd-popover-lazy-init-of-body-example',\n template: `\n \n \n \n \n \n

    Header

    \n \n
    Footer
    \n
    \n
    \n `,\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyDirective,\n PopoverBodyHeaderDirective,\n PopoverBodyFooterDirective,\n ButtonComponent,\n PopoverLazyLoadedBodyComponent\n ]\n})\nexport class PopoverLazyInitOfBodyExampleComponent {}\n" }, + { + "name": "popover-focus-example", + "description": "Popover Focus", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n PopoverBodyComponent,\n PopoverBodyFooterDirective,\n PopoverBodyHeaderDirective,\n PopoverComponent,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-focus-example',\n templateUrl: './popover-focus-example.component.html',\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n PopoverBodyHeaderDirective,\n BarModule,\n AvatarComponent,\n PopoverBodyFooterDirective,\n ContentDensityDirective\n ]\n})\nexport class PopoverFocusExampleComponent {}\n", + "html": "

    Focus Trapped & Auto Capture (default behavior)

    \n\n \n \n \n \n
    \n
    \n
    \n \n Header\n
    \n
    \n
    \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n\n

    \n\n

    Focus NOT Auto Captured

    \n\n \n \n \n \n
    \n

    Focus is not automatically moved to this popover when opened.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Restore Focus On Close (default: true)

    \n\n \n \n \n \n
    \n

    When closed, focus returns to the trigger button.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Do NOT Restore Focus On Close

    \n\n \n \n \n \n
    \n

    When closed, focus does NOT return to the trigger.

    \n \n
    \n
    \n
    \n\n

    \n\n

    Prevent Space Key Scroll (default: true)

    \n

    \n By default, pressing Space on the trigger prevents page scrolling. Set\n [preventSpaceKeyScroll]=\"false\" to allow normal scroll behavior.\n

    \n\n \n \n \n \n
    \n

    When this popover's trigger is focused, pressing Space allows page scroll.

    \n
    \n
    \n
    \n" + }, { "name": "popover-mobile-example", "description": "Popover Mobile", @@ -43277,30 +43337,30 @@ "typescript": "import { ConnectionPositionPair } from '@angular/cdk/overlay';\nimport { Component, signal, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport { XPositions, YPositions } from '@fundamental-ngx/core/shared';\n\n@Component({\n selector: 'fd-popover-cdk-placement-example',\n templateUrl: './popover-cdk-placement-example.component.html',\n imports: [\n FormLabelComponent,\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent\n ]\n})\nexport class PopoverCdkPlacementExampleComponent {\n readonly popover = viewChild(PopoverComponent);\n\n readonly yPositions: YPositions[] = ['bottom', 'center', 'top'];\n readonly xPositions: XPositions[] = ['start', 'center', 'end'];\n\n originX = signal('center');\n originY = signal('center');\n overlayX = signal('center');\n overlayY = signal('center');\n\n cdkPosition = signal(this._buildCdkPositionObject());\n\n refresh(): void {\n this.cdkPosition.set(this._buildCdkPositionObject());\n this.popover()?.applyNewPosition(this.cdkPosition());\n }\n\n private _buildCdkPositionObject(): ConnectionPositionPair[] {\n return [\n {\n originX: this.originX(),\n originY: this.originY(),\n overlayX: this.overlayX(),\n overlayY: this.overlayY()\n }\n ];\n }\n}\n", "html": "
    \n \n \n @for (option of xPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of yPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of xPositions; track option) {\n \n }\n \n
    \n \n \n @for (option of yPositions; track option) {\n \n }\n \n
    \n

    \n\n \n \n \n \n \n \n \n \n\n" }, - { - "name": "popover-placement-example", - "description": "Popover Placement", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-placement-example',\n templateUrl: './popover-placement-example.component.html',\n styleUrls: ['popover-placement-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, AvatarComponent]\n})\nexport class PopoverPlacementExampleComponent {}\n", - "html": "
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" - }, { "name": "popover-programmatic-open-example", "description": "Popover Programmatic Open", "typescript": "import { JsonPipe } from '@angular/common';\nimport { Component, signal } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n PopoverBodyComponent,\n PopoverComponent,\n PopoverConfig,\n PopoverControlComponent\n} from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-programmatic-open-example',\n templateUrl: './popover-programmatic-open-example.component.html',\n styleUrls: ['popover-programmatic-open-example.component.scss'],\n imports: [\n PopoverComponent,\n PopoverControlComponent,\n AvatarComponent,\n PopoverBodyComponent,\n ButtonComponent,\n JsonPipe\n ]\n})\nexport class PopoverProgrammaticOpenExampleComponent {\n /** Signal-based open state for two-way binding */\n isOpen = signal(false);\n\n /** Disabled state for the popover */\n isDisabled = signal(false);\n\n /** Config object example - can be used instead of individual inputs */\n popoverConfig: PopoverConfig = {\n placement: 'bottom-start',\n noArrow: false,\n closeOnEscapeKey: true,\n focusTrapped: true\n };\n\n /** Track open/close events */\n eventLog = signal([]);\n\n /** Called before popover opens */\n onBeforeOpen(): void {\n this.addToLog('beforeOpen event fired');\n }\n\n /** Called when open state changes */\n onOpenChange(isOpen: boolean): void {\n this.addToLog(`isOpenChange: ${isOpen}`);\n }\n\n /** Toggle disabled state */\n toggleDisabled(): void {\n this.isDisabled.update((v) => !v);\n this.addToLog(`Popover ${this.isDisabled() ? 'disabled' : 'enabled'}`);\n }\n\n /** Clear event log */\n clearLog(): void {\n this.eventLog.set([]);\n }\n\n private addToLog(message: string): void {\n this.eventLog.update((log) => [...log, `${new Date().toLocaleTimeString()}: ${message}`]);\n }\n}\n", "html": "\n

    Signal-based Programmatic Control

    \n
    \n \n \n \n \n \n \n \n \n \n \n \n
    \n\n\n

    Using Config Object

    \n\n \n \n \n \n
    \n

    This popover uses the [config] input:

    \n
    {{ popoverConfig | json }}
    \n
    \n
    \n
    \n\n\n

    Event Log

    \n
    \n @if (eventLog().length === 0) {\n

    No events yet. Open the popover to see events.

    \n } @else {\n
      \n @for (event of eventLog(); track event) {\n
    • {{ event }}
    • \n }\n
    \n \n }\n
    \n" }, + { + "name": "popover-non-dialog-example", + "description": "Popover Non Dialog", + "typescript": "import { Component } from '@angular/core';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-non-dialog-example',\n templateUrl: './popover-non-dialog-example.component.html',\n imports: [PopoverModule]\n})\nexport class PopoverNonDialogExampleComponent {}\n", + "html": "

    \n Use [bodyRole]=\"region\" (or null) when the popover is a non-modal disclosure rather than a\n dialog. Match the role to the popover's actual ARIA semantics.\n

    \n\n\n \n \n \n \n
    \n

    Quick Filters

    \n \n \n
    \n
    \n
    \n" + }, + { + "name": "popover-placement-example", + "description": "Popover Placement", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-placement-example',\n templateUrl: './popover-placement-example.component.html',\n styleUrls: ['popover-placement-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent, AvatarComponent]\n})\nexport class PopoverPlacementExampleComponent {}\n", + "html": "
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n \n \n \n \n \n \n \n \n
    \n
    \n" + }, { "name": "popover-resizable-example", "description": "Popover Resizable", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-resizable-example',\n templateUrl: './popover-resizable-example.component.html',\n styleUrls: ['popover-resizable-example.component.scss'],\n imports: [PopoverComponent, PopoverControlComponent, ButtonComponent, PopoverBodyComponent]\n})\nexport class PopoverResizableExampleComponent {}\n", "html": "
    \n \n \n \n \n\n \n
    \n

    Resizable content area

    \n

    \n Drag the resize handle to make room for longer content, tables, previews, or forms while keeping the\n popover within its configured limits.\n

    \n \n
    \n
    \n
    \n
    \n" }, - { - "name": "popover-scroll-example", - "description": "Popover Scroll", - "typescript": "import { Overlay, ScrollStrategy } from '@angular/cdk/overlay';\nimport { Component, inject } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-scroll-example',\n templateUrl: './popover-scroll-example.component.html',\n styleUrls: ['./popover-scroll-example.component.scss'],\n imports: [\n FormLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class PopoverScrollExampleComponent {\n /** Do nothing on scroll. */\n noopScrollStrategy: ScrollStrategy;\n\n /**\n * Close the overlay as soon as the user scrolls.\n * @param config Configuration to be used inside the scroll strategy.\n */\n closeScrollStrategy: ScrollStrategy;\n\n /** Block scrolling. */\n blockScrollStrategy: ScrollStrategy;\n\n /** Whether to close the overlay once the user has scrolled away completely. */\n autoClose = false;\n\n /** Time in milliseconds to throttle the scroll events. Use to increase performance. */\n scrollThrottle = 0;\n\n /**\n * Update the overlay's position on scroll.\n * @param config Configuration to be used inside the scroll strategy.\n * Allows debouncing the reposition calls.\n */\n repositionScrollStrategy: ScrollStrategy;\n\n private readonly _overlay = inject(Overlay);\n\n constructor() {\n this.noopScrollStrategy = this._overlay.scrollStrategies.noop();\n this.closeScrollStrategy = this._overlay.scrollStrategies.close();\n this.blockScrollStrategy = this._overlay.scrollStrategies.block();\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n\n refreshRepositionScrollStrategy(): void {\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n}\n", - "html": "\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n Close the overlay once the user has scrolled away completely?\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n" - }, { "name": "popover-example", "description": "Popover", @@ -43312,6 +43372,12 @@ "description": "Popover Trigger", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { PopoverComponent, PopoverTriggerDirective } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-trigger-example',\n templateUrl: './popover-trigger-example.component.html',\n imports: [ButtonComponent, PopoverTriggerDirective, PopoverComponent]\n})\nexport class PopoverTriggerExampleComponent {}\n", "html": "\n\n\n
    This popover is connected to trigger element
    \n
    \n" + }, + { + "name": "popover-scroll-example", + "description": "Popover Scroll", + "typescript": "import { Overlay, ScrollStrategy } from '@angular/cdk/overlay';\nimport { Component, inject } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\n\n@Component({\n selector: 'fd-popover-scroll-example',\n templateUrl: './popover-scroll-example.component.html',\n styleUrls: ['./popover-scroll-example.component.scss'],\n imports: [\n FormLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n ButtonComponent,\n PopoverBodyComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class PopoverScrollExampleComponent {\n /** Do nothing on scroll. */\n noopScrollStrategy: ScrollStrategy;\n\n /**\n * Close the overlay as soon as the user scrolls.\n * @param config Configuration to be used inside the scroll strategy.\n */\n closeScrollStrategy: ScrollStrategy;\n\n /** Block scrolling. */\n blockScrollStrategy: ScrollStrategy;\n\n /** Whether to close the overlay once the user has scrolled away completely. */\n autoClose = false;\n\n /** Time in milliseconds to throttle the scroll events. Use to increase performance. */\n scrollThrottle = 0;\n\n /**\n * Update the overlay's position on scroll.\n * @param config Configuration to be used inside the scroll strategy.\n * Allows debouncing the reposition calls.\n */\n repositionScrollStrategy: ScrollStrategy;\n\n private readonly _overlay = inject(Overlay);\n\n constructor() {\n this.noopScrollStrategy = this._overlay.scrollStrategies.noop();\n this.closeScrollStrategy = this._overlay.scrollStrategies.close();\n this.blockScrollStrategy = this._overlay.scrollStrategies.block();\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n\n refreshRepositionScrollStrategy(): void {\n this.repositionScrollStrategy = this._overlay.scrollStrategies.reposition({\n autoClose: this.autoClose,\n scrollThrottle: this.scrollThrottle\n });\n }\n}\n", + "html": "\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n\n


    \n\n\n\n Close the overlay once the user has scrolled away completely?\n\n\n \n \n
    Start scrolling to see behaviour
    \n
    \n
    \n" } ] }, @@ -44967,18 +45033,18 @@ "sourceFile": "libs/core/select/select.component.ts", "source": "typedoc", "examples": [ - { - "name": "select-adding-example", - "description": "Select Adding", - "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { SelectModule } from '@fundamental-ngx/core/select';\n\n@Component({\n selector: 'fd-select-adding-example',\n templateUrl: './select-adding-example.component.html',\n styleUrls: ['./select-adding-example.component.scss'],\n imports: [ButtonComponent, SelectModule]\n})\nexport class SelectAddingExampleComponent {\n options: string[] = ['Apple', 'Pineapple', 'Tomato', 'Strawberry'];\n\n selectedValue: string;\n\n addedOptions = 1;\n\n addOption(): void {\n this.options.push(`New option ${this.addedOptions++}`);\n }\n\n removeOption(): void {\n if (this.options.length > 1) {\n this.options.pop();\n }\n }\n}\n", - "html": "
    \n \n \n
    \n\n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n
    \nSelected value: {{ selectedValue }}\n" - }, { "name": "select-custom-comparator-example", "description": "Select Custom Comparator", "typescript": "import { Component } from '@angular/core';\nimport { SelectModule } from '@fundamental-ngx/core/select';\n\ntype CarType = { id: string; name: string };\n\n@Component({\n selector: 'fd-select-custom-comparator-example',\n templateUrl: './select-custom-comparator-example.component.html',\n imports: [SelectModule]\n})\n// eslint-disable-next-line @angular-eslint/component-class-suffix\nexport class SelectCustomComparatorExample {\n carTypes: CarType[] = [\n { id: '1', name: 'Hatchback' },\n { id: '2', name: 'Sedan' },\n { id: '3', name: 'Coupe' }\n ];\n selectedCarType: CarType = { id: '1', name: 'Hatchback' };\n\n get optionMatchedByValue(): string {\n const matchingIndex = this.carTypes.findIndex((carType) => this.comparator(carType, this.selectedCarType));\n if (matchingIndex < 0) {\n return 'No available option that matches the selected option by value';\n }\n return JSON.stringify(this.carTypes[matchingIndex], undefined, 2);\n }\n\n get optionMatchedByReference(): string {\n const matchingIndex = this.carTypes.findIndex((carType) => carType === this.selectedCarType);\n if (matchingIndex < 0) {\n return 'No available option that matches the selected option by reference';\n }\n return JSON.stringify(this.carTypes[matchingIndex], undefined, 2);\n }\n\n comparator: (obj1: CarType, obj2: CarType) => boolean = (obj1: CarType, obj2: CarType) =>\n obj1 && obj2 && obj1.id === obj2.id;\n\n setCarTypeByCopy(newValue: CarType): void {\n this.selectedCarType = { ...newValue };\n }\n}\n", "html": "

    Custom comparator

    \n\n @for (carType of carTypes; track carType) {\n {{ carType.name }}\n }\n\n

    Options matching selected option by value: \"{{ optionMatchedByValue }}\".

    \n

    Options matching selected option by reference: \"{{ optionMatchedByReference }}\".

    \n" }, + { + "name": "select-adding-example", + "description": "Select Adding", + "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { SelectModule } from '@fundamental-ngx/core/select';\n\n@Component({\n selector: 'fd-select-adding-example',\n templateUrl: './select-adding-example.component.html',\n styleUrls: ['./select-adding-example.component.scss'],\n imports: [ButtonComponent, SelectModule]\n})\nexport class SelectAddingExampleComponent {\n options: string[] = ['Apple', 'Pineapple', 'Tomato', 'Strawberry'];\n\n selectedValue: string;\n\n addedOptions = 1;\n\n addOption(): void {\n this.options.push(`New option ${this.addedOptions++}`);\n }\n\n removeOption(): void {\n if (this.options.length > 1) {\n this.options.pop();\n }\n }\n}\n", + "html": "
    \n \n \n
    \n\n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n
    \nSelected value: {{ selectedValue }}\n" + }, { "name": "select-max-height-example", "description": "Select Max Height", @@ -44991,6 +45057,12 @@ "typescript": "import { Component } from '@angular/core';\nimport { MobileModeConfig } from '@fundamental-ngx/core/mobile-mode';\nimport { SelectModule } from '@fundamental-ngx/core/select';\n\n@Component({\n selector: 'fd-select-mobile-example',\n templateUrl: './select-mobile-example.component.html',\n imports: [SelectModule]\n})\nexport class SelectMobileExampleComponent {\n options: string[] = ['Apple', 'Pineapple', 'Tomato', 'Strawberry'];\n mobileConfig: MobileModeConfig = { hasCloseButton: true, title: 'Select your favourite fruit' };\n selectedValue: string;\n}\n", "html": "\n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n\nSelected value: {{ selectedValue }}\n" }, + { + "name": "select-semantic-state-example", + "description": "Select Semantic State", + "typescript": "import { Component } from '@angular/core';\nimport { FormInputMessageGroupComponent, FormItemComponent, FormMessageComponent } from '@fundamental-ngx/core/form';\nimport { SelectModule } from '@fundamental-ngx/core/select';\n\n@Component({\n selector: 'fd-select-semantic-state-example',\n templateUrl: './select-semantic-state-example.component.html',\n imports: [FormItemComponent, SelectModule, FormMessageComponent, FormInputMessageGroupComponent]\n})\nexport class SelectSemanticStateExampleComponent {\n options: string[] = ['Apple', 'Pineapple', 'Tomato', 'Strawberry'];\n selectedValue1: string;\n selectedValue2: string;\n selectedValue3: string;\n selectedValue4: string;\n}\n", + "html": "

    Success state (with visible long text)

    \n
    \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n \n Success message\n
    \n

    Warning state

    \n
    \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n
    \n Warning message\n
    \n

    Error state

    \n
    \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n
    \n Error message\n
    \n

    Information state

    \n
    \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n \n Information message\n
    \n\n

    Form message with event triggers:

    \n
    \n \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n \n \n Success message\n
    \n
    \n" + }, { "name": "select-mode-example", "description": "Select Mode", @@ -45002,12 +45074,6 @@ "description": "Select Programmatic", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { SelectModule } from '@fundamental-ngx/core/select';\n\n@Component({\n selector: 'fd-select-programmatic-example',\n templateUrl: './select-programmatic-example.component.html',\n styleUrls: ['./select-programmatic-example.component.scss'],\n imports: [ButtonComponent, SelectModule]\n})\nexport class SelectProgrammaticExampleComponent {\n options: string[] = ['Apple', 'Pineapple', 'Tomato', 'Strawberry'];\n selectedPosition = 0;\n\n selectedValue: string = this.options[0];\n newValue = this.options[0];\n\n changeValue(): void {\n this.selectedValue = this.getNewValue();\n }\n\n getPosition(selectedValue: string): number {\n return this.options.findIndex((item) => selectedValue === item);\n }\n\n getNewValue(): string {\n this.selectedPosition = this.getPosition(this.selectedValue);\n\n if (this.selectedPosition < this.options.length - 1) {\n this.selectedPosition++;\n } else {\n this.selectedPosition = 0;\n }\n\n this.newValue = this.options[this.selectedPosition];\n return this.selectedValue === this.newValue ? this.getNewValue() : this.newValue;\n }\n}\n", "html": "
    \n \n \n \n
    \n\n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n
    \nSelected value: {{ selectedValue }}\n" - }, - { - "name": "select-semantic-state-example", - "description": "Select Semantic State", - "typescript": "import { Component } from '@angular/core';\nimport { FormInputMessageGroupComponent, FormItemComponent, FormMessageComponent } from '@fundamental-ngx/core/form';\nimport { SelectModule } from '@fundamental-ngx/core/select';\n\n@Component({\n selector: 'fd-select-semantic-state-example',\n templateUrl: './select-semantic-state-example.component.html',\n imports: [FormItemComponent, SelectModule, FormMessageComponent, FormInputMessageGroupComponent]\n})\nexport class SelectSemanticStateExampleComponent {\n options: string[] = ['Apple', 'Pineapple', 'Tomato', 'Strawberry'];\n selectedValue1: string;\n selectedValue2: string;\n selectedValue3: string;\n selectedValue4: string;\n}\n", - "html": "

    Success state (with visible long text)

    \n
    \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n \n Success message\n
    \n

    Warning state

    \n
    \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n
    \n Warning message\n
    \n

    Error state

    \n
    \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n
    \n Error message\n
    \n

    Information state

    \n
    \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n \n Information message\n
    \n\n

    Form message with event triggers:

    \n
    \n \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n \n \n Success message\n
    \n
    \n" } ] }, @@ -45025,18 +45091,18 @@ "sourceFile": "libs/core/select/select-mobile/select-mobile.component.ts", "source": "typedoc", "examples": [ - { - "name": "select-adding-example", - "description": "Select Adding", - "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { SelectModule } from '@fundamental-ngx/core/select';\n\n@Component({\n selector: 'fd-select-adding-example',\n templateUrl: './select-adding-example.component.html',\n styleUrls: ['./select-adding-example.component.scss'],\n imports: [ButtonComponent, SelectModule]\n})\nexport class SelectAddingExampleComponent {\n options: string[] = ['Apple', 'Pineapple', 'Tomato', 'Strawberry'];\n\n selectedValue: string;\n\n addedOptions = 1;\n\n addOption(): void {\n this.options.push(`New option ${this.addedOptions++}`);\n }\n\n removeOption(): void {\n if (this.options.length > 1) {\n this.options.pop();\n }\n }\n}\n", - "html": "
    \n \n \n
    \n\n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n
    \nSelected value: {{ selectedValue }}\n" - }, { "name": "select-custom-comparator-example", "description": "Select Custom Comparator", "typescript": "import { Component } from '@angular/core';\nimport { SelectModule } from '@fundamental-ngx/core/select';\n\ntype CarType = { id: string; name: string };\n\n@Component({\n selector: 'fd-select-custom-comparator-example',\n templateUrl: './select-custom-comparator-example.component.html',\n imports: [SelectModule]\n})\n// eslint-disable-next-line @angular-eslint/component-class-suffix\nexport class SelectCustomComparatorExample {\n carTypes: CarType[] = [\n { id: '1', name: 'Hatchback' },\n { id: '2', name: 'Sedan' },\n { id: '3', name: 'Coupe' }\n ];\n selectedCarType: CarType = { id: '1', name: 'Hatchback' };\n\n get optionMatchedByValue(): string {\n const matchingIndex = this.carTypes.findIndex((carType) => this.comparator(carType, this.selectedCarType));\n if (matchingIndex < 0) {\n return 'No available option that matches the selected option by value';\n }\n return JSON.stringify(this.carTypes[matchingIndex], undefined, 2);\n }\n\n get optionMatchedByReference(): string {\n const matchingIndex = this.carTypes.findIndex((carType) => carType === this.selectedCarType);\n if (matchingIndex < 0) {\n return 'No available option that matches the selected option by reference';\n }\n return JSON.stringify(this.carTypes[matchingIndex], undefined, 2);\n }\n\n comparator: (obj1: CarType, obj2: CarType) => boolean = (obj1: CarType, obj2: CarType) =>\n obj1 && obj2 && obj1.id === obj2.id;\n\n setCarTypeByCopy(newValue: CarType): void {\n this.selectedCarType = { ...newValue };\n }\n}\n", "html": "

    Custom comparator

    \n\n @for (carType of carTypes; track carType) {\n {{ carType.name }}\n }\n\n

    Options matching selected option by value: \"{{ optionMatchedByValue }}\".

    \n

    Options matching selected option by reference: \"{{ optionMatchedByReference }}\".

    \n" }, + { + "name": "select-adding-example", + "description": "Select Adding", + "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { SelectModule } from '@fundamental-ngx/core/select';\n\n@Component({\n selector: 'fd-select-adding-example',\n templateUrl: './select-adding-example.component.html',\n styleUrls: ['./select-adding-example.component.scss'],\n imports: [ButtonComponent, SelectModule]\n})\nexport class SelectAddingExampleComponent {\n options: string[] = ['Apple', 'Pineapple', 'Tomato', 'Strawberry'];\n\n selectedValue: string;\n\n addedOptions = 1;\n\n addOption(): void {\n this.options.push(`New option ${this.addedOptions++}`);\n }\n\n removeOption(): void {\n if (this.options.length > 1) {\n this.options.pop();\n }\n }\n}\n", + "html": "
    \n \n \n
    \n\n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n
    \nSelected value: {{ selectedValue }}\n" + }, { "name": "select-max-height-example", "description": "Select Max Height", @@ -45049,6 +45115,12 @@ "typescript": "import { Component } from '@angular/core';\nimport { MobileModeConfig } from '@fundamental-ngx/core/mobile-mode';\nimport { SelectModule } from '@fundamental-ngx/core/select';\n\n@Component({\n selector: 'fd-select-mobile-example',\n templateUrl: './select-mobile-example.component.html',\n imports: [SelectModule]\n})\nexport class SelectMobileExampleComponent {\n options: string[] = ['Apple', 'Pineapple', 'Tomato', 'Strawberry'];\n mobileConfig: MobileModeConfig = { hasCloseButton: true, title: 'Select your favourite fruit' };\n selectedValue: string;\n}\n", "html": "\n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n\nSelected value: {{ selectedValue }}\n" }, + { + "name": "select-semantic-state-example", + "description": "Select Semantic State", + "typescript": "import { Component } from '@angular/core';\nimport { FormInputMessageGroupComponent, FormItemComponent, FormMessageComponent } from '@fundamental-ngx/core/form';\nimport { SelectModule } from '@fundamental-ngx/core/select';\n\n@Component({\n selector: 'fd-select-semantic-state-example',\n templateUrl: './select-semantic-state-example.component.html',\n imports: [FormItemComponent, SelectModule, FormMessageComponent, FormInputMessageGroupComponent]\n})\nexport class SelectSemanticStateExampleComponent {\n options: string[] = ['Apple', 'Pineapple', 'Tomato', 'Strawberry'];\n selectedValue1: string;\n selectedValue2: string;\n selectedValue3: string;\n selectedValue4: string;\n}\n", + "html": "

    Success state (with visible long text)

    \n
    \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n \n Success message\n
    \n

    Warning state

    \n
    \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n
    \n Warning message\n
    \n

    Error state

    \n
    \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n
    \n Error message\n
    \n

    Information state

    \n
    \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n \n Information message\n
    \n\n

    Form message with event triggers:

    \n
    \n \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n \n \n Success message\n
    \n
    \n" + }, { "name": "select-mode-example", "description": "Select Mode", @@ -45060,12 +45132,6 @@ "description": "Select Programmatic", "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { SelectModule } from '@fundamental-ngx/core/select';\n\n@Component({\n selector: 'fd-select-programmatic-example',\n templateUrl: './select-programmatic-example.component.html',\n styleUrls: ['./select-programmatic-example.component.scss'],\n imports: [ButtonComponent, SelectModule]\n})\nexport class SelectProgrammaticExampleComponent {\n options: string[] = ['Apple', 'Pineapple', 'Tomato', 'Strawberry'];\n selectedPosition = 0;\n\n selectedValue: string = this.options[0];\n newValue = this.options[0];\n\n changeValue(): void {\n this.selectedValue = this.getNewValue();\n }\n\n getPosition(selectedValue: string): number {\n return this.options.findIndex((item) => selectedValue === item);\n }\n\n getNewValue(): string {\n this.selectedPosition = this.getPosition(this.selectedValue);\n\n if (this.selectedPosition < this.options.length - 1) {\n this.selectedPosition++;\n } else {\n this.selectedPosition = 0;\n }\n\n this.newValue = this.options[this.selectedPosition];\n return this.selectedValue === this.newValue ? this.getNewValue() : this.newValue;\n }\n}\n", "html": "
    \n \n \n \n
    \n\n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n
    \nSelected value: {{ selectedValue }}\n" - }, - { - "name": "select-semantic-state-example", - "description": "Select Semantic State", - "typescript": "import { Component } from '@angular/core';\nimport { FormInputMessageGroupComponent, FormItemComponent, FormMessageComponent } from '@fundamental-ngx/core/form';\nimport { SelectModule } from '@fundamental-ngx/core/select';\n\n@Component({\n selector: 'fd-select-semantic-state-example',\n templateUrl: './select-semantic-state-example.component.html',\n imports: [FormItemComponent, SelectModule, FormMessageComponent, FormInputMessageGroupComponent]\n})\nexport class SelectSemanticStateExampleComponent {\n options: string[] = ['Apple', 'Pineapple', 'Tomato', 'Strawberry'];\n selectedValue1: string;\n selectedValue2: string;\n selectedValue3: string;\n selectedValue4: string;\n}\n", - "html": "

    Success state (with visible long text)

    \n
    \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n \n Success message\n
    \n

    Warning state

    \n
    \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n
    \n Warning message\n
    \n

    Error state

    \n
    \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n
    \n Error message\n
    \n

    Information state

    \n
    \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n \n Information message\n
    \n\n

    Form message with event triggers:

    \n
    \n \n \n @for (option of options; track option) {\n
  • {{ option }}
  • \n }\n \n \n Success message\n
    \n
    \n" } ] }, @@ -45193,18 +45259,18 @@ "typescript": "import { Component, inject, OnInit, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { IllustratedMessageModule, SvgConfig } from '@fundamental-ngx/core/illustrated-message';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { SegmentedButtonComponent } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\nimport { DataProvider, SearchFieldDataSource } from '@fundamental-ngx/platform/shared';\nimport { Observable, of } from 'rxjs';\n\n@Component({\n selector: 'fd-shellbar-complex-search-results-example',\n templateUrl: './shellbar-complex-search-results-example.component.html',\n imports: [\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarModule,\n BarRightDirective,\n MessageToastModule,\n SearchFieldComponent,\n ShellbarActionComponent,\n FormsModule,\n SegmentedButtonComponent,\n CheckboxComponent,\n IllustratedMessageModule\n ]\n})\nexport class ShellbarComplexSearchResultsExampleComponent implements OnInit {\n shellSearchField = viewChild('shellSearchField');\n\n dataSource: SearchFieldDataSource;\n\n expanded = true;\n\n exampleType: 'default' | 'advancedFilter' | 'mobile' = 'default';\n\n emptyResultsType: 'illustratedMessage' | 'customSuggestions' = 'illustratedMessage';\n\n emptyDefaultSuggestions: SuggestionItem[] = [\n {\n value: 'Peach',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Pear',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Plum',\n data: {\n type: 'fruit'\n }\n }\n ];\n\n categories: ValueLabelItem[] = [\n {\n value: 'fruit',\n label: 'Fruits'\n },\n {\n value: 'vegetable',\n label: 'Vegetables'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n label: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n label: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n smallConfig: SvgConfig = {\n small: { url: 'assets/images/sapIllus-Ice-Cream-Demo-Small.svg', id: 'sapIllus-Ice-Cream-Demo-Small' }\n };\n\n showCategories = true;\n\n suggestionsLoading = false;\n\n private _messageToastService = inject(MessageToastService);\n\n ngOnInit(): void {\n this.dataSource = new SearchFieldDataSource(new ShellSearchFieldDataProvider());\n SUGGESTIONS[0].children?.forEach((child) => {\n this.emptyDefaultSuggestions.push(child);\n });\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n showAllSearchResultsClicked(): void {\n this.suggestionsLoading = true;\n setTimeout(() => {\n this.suggestionsLoading = false;\n this.shellSearchField()?.resetCategory();\n this.shellSearchField()?.clearTextInput();\n }, 500);\n }\n\n submit(event: SearchInput): void {\n alert('Search submitted. See developer console for event');\n console.log(event);\n }\n}\n\nexport class ShellSearchFieldDataProvider extends DataProvider {\n constructor() {\n super();\n }\n\n fetch(params: Map): Observable {\n const data = SUGGESTIONS;\n const name = params.get('keyword');\n const category = params.get('category');\n if ((!name || name.trim() === '') && !category) {\n return of(data);\n } else {\n const filteredData = data.filter((suggestion) => {\n let foundMatchingChild = false;\n if (suggestion.children) {\n for (let i = 0; i < suggestion.children.length && !foundMatchingChild; i++) {\n foundMatchingChild = this._checkForMatches(suggestion.children[i], name, category);\n }\n } else {\n foundMatchingChild = this._checkForMatches(suggestion, name, category);\n }\n return foundMatchingChild;\n });\n return of(filteredData);\n }\n }\n\n private _checkForMatches(item: any, name: string | undefined, category: string | undefined): boolean {\n let foundMatchingItem = false;\n if (name && category) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1 && item.data?.type === category) {\n foundMatchingItem = true;\n }\n } else if (name) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1) {\n foundMatchingItem = true;\n }\n } else if (category) {\n if (item.data?.type === category) {\n foundMatchingItem = true;\n }\n }\n return foundMatchingItem;\n }\n}\n\nconst SUGGESTIONS: SuggestionItem[] = [\n {\n value: 'Fruits',\n isGroupHeader: true,\n children: [\n {\n value: 'Apple',\n data: {\n type: 'fruit',\n listIconGlyph: 'globe'\n }\n },\n {\n value: 'Banana',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Blueberry',\n data: {\n type: 'fruit',\n prefix: 'Prefix text:',\n actionButtons: [\n {\n actionButtonGlyph: 'refresh',\n actionButtonCallback: () => {\n alert('Blueberry refresh button clicked');\n },\n actionButtonId: 'refresh-button-1',\n actionButtonLabel: 'Refresh Item'\n },\n {\n actionButtonGlyph: 'settings',\n actionButtonCallback: () => {\n alert('Blueberry settings button clicked');\n },\n actionButtonLabel: 'Settings'\n }\n ],\n showDeleteButton: true,\n deleteCallback: () => {\n alert('Blueberry delete button clicked');\n }\n }\n },\n {\n value: 'Cherry',\n data: {\n type: 'fruit'\n }\n }\n ],\n searchInScopeText: 'Search in [Fruits]',\n searchInScopeCounter: 1234,\n searchInScopeCallback: () => {\n alert('Search in scope callback clicked');\n }\n },\n {\n value: 'Vegetables',\n isGroupHeader: true,\n children: [\n {\n value: 'Broccoli',\n data: {\n type: 'vegetable',\n subline: 'Flower vegetable',\n avatarLabel: 'John Doe'\n }\n },\n {\n value: 'Carrot',\n data: {\n type: 'vegetable',\n subline: 'Root vegetable',\n listIconGlyph: 'cart'\n }\n },\n {\n value: 'Corn',\n data: {\n type: 'vegetable'\n }\n },\n {\n value: 'Radish',\n data: {\n type: 'vegetable'\n }\n }\n ],\n showMoreText: 'Show More',\n showMoreCounter: 1234,\n showMoreCallback: () => {\n alert('Show more callback clicked');\n }\n }\n];\n", "html": "Shell search field example type:\n
    \n\n \n \n \n\n
    \nEmpty search results example type:\n
    \n\n \n \n\n
    \n\n\n
    \n \n \n \n \n \n Product Identifier\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n
    \n\n\n
    \n \n
    \n
    \n\n\n @if (emptyResultsType === 'illustratedMessage') {\n
    \n
    \n

    No Results

    \n

    Start by proiding your search criteria.

    \n
    \n
    \n }\n
    \n" }, + { + "name": "shellbar-responsive-example", + "description": "Shellbar Responsive", + "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", + "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, { "name": "shellbar-branding-context-area-example", "description": "Shellbar Branding Context Area", "typescript": "import { Component, ElementRef, signal, ViewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ClickedDirective } from '@fundamental-ngx/cdk';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport {\n ShellbarComponent,\n ShellbarMenuItem,\n ShellbarModule,\n ShellbarUser,\n ShellbarUserMenu\n} from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\n@Component({\n selector: 'fd-shellbar-branding-context-area-example',\n templateUrl: './shellbar-branding-context-area-example.component.html',\n imports: [\n ShellbarModule,\n MenuModule,\n AvatarComponent,\n ClickedDirective,\n ButtonComponent,\n FormsModule,\n ProductSwitchModule,\n SearchFieldComponent,\n ObjectStatusComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n PopoverModule,\n ListModule,\n PanelModule,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarBrandingContextAreaExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n @ViewChild(ShellbarComponent, { read: ElementRef })\n shellbar: ElementRef;\n\n expanded = true;\n\n isOpen = false;\n\n searchTerm = '';\n\n inputText = '';\n\n showButtonWithPriority3 = true;\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n productMenuItems: ShellbarMenuItem[] = [\n {\n name: 'Application A',\n callback: () => {\n alert('Application A Clicked');\n }\n },\n {\n name: 'Application B',\n callback: () => {\n alert('Application B Clicked');\n }\n },\n {\n name: 'Application C',\n callback: () => {\n alert('Application C Clicked');\n }\n },\n {\n name: 'Application D',\n callback: () => {\n alert('Application D Clicked');\n }\n }\n ];\n\n accountToggledState = signal(true);\n filterToggledState = signal(false);\n cartToggledState = signal(false);\n\n actions = [\n {\n glyph: 'account',\n callback: () => this.actionAccountCallback(),\n label: 'Account',\n ariaLabel: 'Account Action',\n title: 'Account',\n type: 'transparent' as ButtonType,\n toggled: this.accountToggledState\n },\n {\n glyph: 'filter',\n callback: () => this.actionFilterCallback(),\n label: 'Filter',\n ariaLabel: 'Filter Action',\n title: 'Filter',\n type: 'attention' as ButtonType,\n toggled: this.filterToggledState\n },\n {\n glyph: 'cart',\n callback: () => this.actionCartCallback(),\n label: 'Cart',\n ariaLabel: 'Cart Action',\n type: 'positive' as ButtonType,\n title: 'Cart',\n toggled: this.cartToggledState\n },\n {\n glyph: 'bell',\n callback: (event: MouseEvent) => this.actionNotificationCallback(event),\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home'),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n user: ShellbarUser = {\n fullName: 'William Willson',\n colorAccent: 6\n };\n\n userMenu: ShellbarUserMenu[] = [\n { text: 'Settings', callback: this.settingsCallback },\n { text: 'Sign Out', callback: this.signOutCallback }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n brandingClicked($event: Event): void {\n console.log($event);\n alert('Branding clicked');\n }\n\n settingsCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Settings Clicked');\n }\n\n signOutCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionAccountCallback(): void {\n this.accountToggledState.set(!this.accountToggledState());\n }\n\n actionFilterCallback(): void {\n this.filterToggledState.set(!this.filterToggledState());\n }\n\n actionCartCallback(): void {\n this.cartToggledState.set(!this.cartToggledState());\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n assistiveToolsCallback(): void {\n alert('Assistive Tools Clicked');\n }\n\n navClicked(event): void {\n console.log(event);\n alert('Navigation Button Clicked');\n }\n\n backClicked(event): void {\n console.log(event);\n alert('Back Button Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n toggleButton3(): void {\n this.showButtonWithPriority3 = !this.showButtonWithPriority3;\n }\n\n itemVisibilityChanged(event: any): void {\n console.log(event);\n }\n}\n", "html": "\n \n \n \n \n Product Identifier\n \n\n \n \n \n \n \n \n @if (showButtonWithPriority3) {\n \n }\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n\n\n
    \n\n\n" }, - { - "name": "shellbar-context-area-overflow-example", - "description": "Shellbar Context Area Overflow", - "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", - "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" - }, { "name": "shellbar-growing-group-example", "description": "Shellbar Growing Group", @@ -45212,10 +45278,10 @@ "html": "

    This example shows Shellbar groups taking only space needed for the content inside.

    \n\n \n \n \n \n Product Identifier\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n" }, { - "name": "shellbar-responsive-example", - "description": "Shellbar Responsive", - "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", - "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + "name": "shellbar-context-area-overflow-example", + "description": "Shellbar Context Area Overflow", + "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", + "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" } ] }, @@ -45312,18 +45378,18 @@ "typescript": "import { Component, inject, OnInit, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { IllustratedMessageModule, SvgConfig } from '@fundamental-ngx/core/illustrated-message';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { SegmentedButtonComponent } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\nimport { DataProvider, SearchFieldDataSource } from '@fundamental-ngx/platform/shared';\nimport { Observable, of } from 'rxjs';\n\n@Component({\n selector: 'fd-shellbar-complex-search-results-example',\n templateUrl: './shellbar-complex-search-results-example.component.html',\n imports: [\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarModule,\n BarRightDirective,\n MessageToastModule,\n SearchFieldComponent,\n ShellbarActionComponent,\n FormsModule,\n SegmentedButtonComponent,\n CheckboxComponent,\n IllustratedMessageModule\n ]\n})\nexport class ShellbarComplexSearchResultsExampleComponent implements OnInit {\n shellSearchField = viewChild('shellSearchField');\n\n dataSource: SearchFieldDataSource;\n\n expanded = true;\n\n exampleType: 'default' | 'advancedFilter' | 'mobile' = 'default';\n\n emptyResultsType: 'illustratedMessage' | 'customSuggestions' = 'illustratedMessage';\n\n emptyDefaultSuggestions: SuggestionItem[] = [\n {\n value: 'Peach',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Pear',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Plum',\n data: {\n type: 'fruit'\n }\n }\n ];\n\n categories: ValueLabelItem[] = [\n {\n value: 'fruit',\n label: 'Fruits'\n },\n {\n value: 'vegetable',\n label: 'Vegetables'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n label: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n label: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n smallConfig: SvgConfig = {\n small: { url: 'assets/images/sapIllus-Ice-Cream-Demo-Small.svg', id: 'sapIllus-Ice-Cream-Demo-Small' }\n };\n\n showCategories = true;\n\n suggestionsLoading = false;\n\n private _messageToastService = inject(MessageToastService);\n\n ngOnInit(): void {\n this.dataSource = new SearchFieldDataSource(new ShellSearchFieldDataProvider());\n SUGGESTIONS[0].children?.forEach((child) => {\n this.emptyDefaultSuggestions.push(child);\n });\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n showAllSearchResultsClicked(): void {\n this.suggestionsLoading = true;\n setTimeout(() => {\n this.suggestionsLoading = false;\n this.shellSearchField()?.resetCategory();\n this.shellSearchField()?.clearTextInput();\n }, 500);\n }\n\n submit(event: SearchInput): void {\n alert('Search submitted. See developer console for event');\n console.log(event);\n }\n}\n\nexport class ShellSearchFieldDataProvider extends DataProvider {\n constructor() {\n super();\n }\n\n fetch(params: Map): Observable {\n const data = SUGGESTIONS;\n const name = params.get('keyword');\n const category = params.get('category');\n if ((!name || name.trim() === '') && !category) {\n return of(data);\n } else {\n const filteredData = data.filter((suggestion) => {\n let foundMatchingChild = false;\n if (suggestion.children) {\n for (let i = 0; i < suggestion.children.length && !foundMatchingChild; i++) {\n foundMatchingChild = this._checkForMatches(suggestion.children[i], name, category);\n }\n } else {\n foundMatchingChild = this._checkForMatches(suggestion, name, category);\n }\n return foundMatchingChild;\n });\n return of(filteredData);\n }\n }\n\n private _checkForMatches(item: any, name: string | undefined, category: string | undefined): boolean {\n let foundMatchingItem = false;\n if (name && category) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1 && item.data?.type === category) {\n foundMatchingItem = true;\n }\n } else if (name) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1) {\n foundMatchingItem = true;\n }\n } else if (category) {\n if (item.data?.type === category) {\n foundMatchingItem = true;\n }\n }\n return foundMatchingItem;\n }\n}\n\nconst SUGGESTIONS: SuggestionItem[] = [\n {\n value: 'Fruits',\n isGroupHeader: true,\n children: [\n {\n value: 'Apple',\n data: {\n type: 'fruit',\n listIconGlyph: 'globe'\n }\n },\n {\n value: 'Banana',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Blueberry',\n data: {\n type: 'fruit',\n prefix: 'Prefix text:',\n actionButtons: [\n {\n actionButtonGlyph: 'refresh',\n actionButtonCallback: () => {\n alert('Blueberry refresh button clicked');\n },\n actionButtonId: 'refresh-button-1',\n actionButtonLabel: 'Refresh Item'\n },\n {\n actionButtonGlyph: 'settings',\n actionButtonCallback: () => {\n alert('Blueberry settings button clicked');\n },\n actionButtonLabel: 'Settings'\n }\n ],\n showDeleteButton: true,\n deleteCallback: () => {\n alert('Blueberry delete button clicked');\n }\n }\n },\n {\n value: 'Cherry',\n data: {\n type: 'fruit'\n }\n }\n ],\n searchInScopeText: 'Search in [Fruits]',\n searchInScopeCounter: 1234,\n searchInScopeCallback: () => {\n alert('Search in scope callback clicked');\n }\n },\n {\n value: 'Vegetables',\n isGroupHeader: true,\n children: [\n {\n value: 'Broccoli',\n data: {\n type: 'vegetable',\n subline: 'Flower vegetable',\n avatarLabel: 'John Doe'\n }\n },\n {\n value: 'Carrot',\n data: {\n type: 'vegetable',\n subline: 'Root vegetable',\n listIconGlyph: 'cart'\n }\n },\n {\n value: 'Corn',\n data: {\n type: 'vegetable'\n }\n },\n {\n value: 'Radish',\n data: {\n type: 'vegetable'\n }\n }\n ],\n showMoreText: 'Show More',\n showMoreCounter: 1234,\n showMoreCallback: () => {\n alert('Show more callback clicked');\n }\n }\n];\n", "html": "Shell search field example type:\n
    \n\n \n \n \n\n
    \nEmpty search results example type:\n
    \n\n \n \n\n
    \n\n\n
    \n \n \n \n \n \n Product Identifier\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n
    \n\n\n
    \n \n
    \n
    \n\n\n @if (emptyResultsType === 'illustratedMessage') {\n
    \n
    \n

    No Results

    \n

    Start by proiding your search criteria.

    \n
    \n
    \n }\n
    \n" }, + { + "name": "shellbar-responsive-example", + "description": "Shellbar Responsive", + "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", + "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, { "name": "shellbar-branding-context-area-example", "description": "Shellbar Branding Context Area", "typescript": "import { Component, ElementRef, signal, ViewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ClickedDirective } from '@fundamental-ngx/cdk';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport {\n ShellbarComponent,\n ShellbarMenuItem,\n ShellbarModule,\n ShellbarUser,\n ShellbarUserMenu\n} from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\n@Component({\n selector: 'fd-shellbar-branding-context-area-example',\n templateUrl: './shellbar-branding-context-area-example.component.html',\n imports: [\n ShellbarModule,\n MenuModule,\n AvatarComponent,\n ClickedDirective,\n ButtonComponent,\n FormsModule,\n ProductSwitchModule,\n SearchFieldComponent,\n ObjectStatusComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n PopoverModule,\n ListModule,\n PanelModule,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarBrandingContextAreaExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n @ViewChild(ShellbarComponent, { read: ElementRef })\n shellbar: ElementRef;\n\n expanded = true;\n\n isOpen = false;\n\n searchTerm = '';\n\n inputText = '';\n\n showButtonWithPriority3 = true;\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n productMenuItems: ShellbarMenuItem[] = [\n {\n name: 'Application A',\n callback: () => {\n alert('Application A Clicked');\n }\n },\n {\n name: 'Application B',\n callback: () => {\n alert('Application B Clicked');\n }\n },\n {\n name: 'Application C',\n callback: () => {\n alert('Application C Clicked');\n }\n },\n {\n name: 'Application D',\n callback: () => {\n alert('Application D Clicked');\n }\n }\n ];\n\n accountToggledState = signal(true);\n filterToggledState = signal(false);\n cartToggledState = signal(false);\n\n actions = [\n {\n glyph: 'account',\n callback: () => this.actionAccountCallback(),\n label: 'Account',\n ariaLabel: 'Account Action',\n title: 'Account',\n type: 'transparent' as ButtonType,\n toggled: this.accountToggledState\n },\n {\n glyph: 'filter',\n callback: () => this.actionFilterCallback(),\n label: 'Filter',\n ariaLabel: 'Filter Action',\n title: 'Filter',\n type: 'attention' as ButtonType,\n toggled: this.filterToggledState\n },\n {\n glyph: 'cart',\n callback: () => this.actionCartCallback(),\n label: 'Cart',\n ariaLabel: 'Cart Action',\n type: 'positive' as ButtonType,\n title: 'Cart',\n toggled: this.cartToggledState\n },\n {\n glyph: 'bell',\n callback: (event: MouseEvent) => this.actionNotificationCallback(event),\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home'),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n user: ShellbarUser = {\n fullName: 'William Willson',\n colorAccent: 6\n };\n\n userMenu: ShellbarUserMenu[] = [\n { text: 'Settings', callback: this.settingsCallback },\n { text: 'Sign Out', callback: this.signOutCallback }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n brandingClicked($event: Event): void {\n console.log($event);\n alert('Branding clicked');\n }\n\n settingsCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Settings Clicked');\n }\n\n signOutCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionAccountCallback(): void {\n this.accountToggledState.set(!this.accountToggledState());\n }\n\n actionFilterCallback(): void {\n this.filterToggledState.set(!this.filterToggledState());\n }\n\n actionCartCallback(): void {\n this.cartToggledState.set(!this.cartToggledState());\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n assistiveToolsCallback(): void {\n alert('Assistive Tools Clicked');\n }\n\n navClicked(event): void {\n console.log(event);\n alert('Navigation Button Clicked');\n }\n\n backClicked(event): void {\n console.log(event);\n alert('Back Button Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n toggleButton3(): void {\n this.showButtonWithPriority3 = !this.showButtonWithPriority3;\n }\n\n itemVisibilityChanged(event: any): void {\n console.log(event);\n }\n}\n", "html": "\n \n \n \n \n Product Identifier\n \n\n \n \n \n \n \n \n @if (showButtonWithPriority3) {\n \n }\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n\n\n
    \n\n\n" }, - { - "name": "shellbar-context-area-overflow-example", - "description": "Shellbar Context Area Overflow", - "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", - "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" - }, { "name": "shellbar-growing-group-example", "description": "Shellbar Growing Group", @@ -45331,10 +45397,10 @@ "html": "

    This example shows Shellbar groups taking only space needed for the content inside.

    \n\n \n \n \n \n Product Identifier\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n" }, { - "name": "shellbar-responsive-example", - "description": "Shellbar Responsive", - "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", - "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + "name": "shellbar-context-area-overflow-example", + "description": "Shellbar Context Area Overflow", + "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", + "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" } ] }, @@ -45410,18 +45476,18 @@ "typescript": "import { Component, inject, OnInit, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { IllustratedMessageModule, SvgConfig } from '@fundamental-ngx/core/illustrated-message';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { SegmentedButtonComponent } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\nimport { DataProvider, SearchFieldDataSource } from '@fundamental-ngx/platform/shared';\nimport { Observable, of } from 'rxjs';\n\n@Component({\n selector: 'fd-shellbar-complex-search-results-example',\n templateUrl: './shellbar-complex-search-results-example.component.html',\n imports: [\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarModule,\n BarRightDirective,\n MessageToastModule,\n SearchFieldComponent,\n ShellbarActionComponent,\n FormsModule,\n SegmentedButtonComponent,\n CheckboxComponent,\n IllustratedMessageModule\n ]\n})\nexport class ShellbarComplexSearchResultsExampleComponent implements OnInit {\n shellSearchField = viewChild('shellSearchField');\n\n dataSource: SearchFieldDataSource;\n\n expanded = true;\n\n exampleType: 'default' | 'advancedFilter' | 'mobile' = 'default';\n\n emptyResultsType: 'illustratedMessage' | 'customSuggestions' = 'illustratedMessage';\n\n emptyDefaultSuggestions: SuggestionItem[] = [\n {\n value: 'Peach',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Pear',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Plum',\n data: {\n type: 'fruit'\n }\n }\n ];\n\n categories: ValueLabelItem[] = [\n {\n value: 'fruit',\n label: 'Fruits'\n },\n {\n value: 'vegetable',\n label: 'Vegetables'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n label: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n label: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n smallConfig: SvgConfig = {\n small: { url: 'assets/images/sapIllus-Ice-Cream-Demo-Small.svg', id: 'sapIllus-Ice-Cream-Demo-Small' }\n };\n\n showCategories = true;\n\n suggestionsLoading = false;\n\n private _messageToastService = inject(MessageToastService);\n\n ngOnInit(): void {\n this.dataSource = new SearchFieldDataSource(new ShellSearchFieldDataProvider());\n SUGGESTIONS[0].children?.forEach((child) => {\n this.emptyDefaultSuggestions.push(child);\n });\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n showAllSearchResultsClicked(): void {\n this.suggestionsLoading = true;\n setTimeout(() => {\n this.suggestionsLoading = false;\n this.shellSearchField()?.resetCategory();\n this.shellSearchField()?.clearTextInput();\n }, 500);\n }\n\n submit(event: SearchInput): void {\n alert('Search submitted. See developer console for event');\n console.log(event);\n }\n}\n\nexport class ShellSearchFieldDataProvider extends DataProvider {\n constructor() {\n super();\n }\n\n fetch(params: Map): Observable {\n const data = SUGGESTIONS;\n const name = params.get('keyword');\n const category = params.get('category');\n if ((!name || name.trim() === '') && !category) {\n return of(data);\n } else {\n const filteredData = data.filter((suggestion) => {\n let foundMatchingChild = false;\n if (suggestion.children) {\n for (let i = 0; i < suggestion.children.length && !foundMatchingChild; i++) {\n foundMatchingChild = this._checkForMatches(suggestion.children[i], name, category);\n }\n } else {\n foundMatchingChild = this._checkForMatches(suggestion, name, category);\n }\n return foundMatchingChild;\n });\n return of(filteredData);\n }\n }\n\n private _checkForMatches(item: any, name: string | undefined, category: string | undefined): boolean {\n let foundMatchingItem = false;\n if (name && category) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1 && item.data?.type === category) {\n foundMatchingItem = true;\n }\n } else if (name) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1) {\n foundMatchingItem = true;\n }\n } else if (category) {\n if (item.data?.type === category) {\n foundMatchingItem = true;\n }\n }\n return foundMatchingItem;\n }\n}\n\nconst SUGGESTIONS: SuggestionItem[] = [\n {\n value: 'Fruits',\n isGroupHeader: true,\n children: [\n {\n value: 'Apple',\n data: {\n type: 'fruit',\n listIconGlyph: 'globe'\n }\n },\n {\n value: 'Banana',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Blueberry',\n data: {\n type: 'fruit',\n prefix: 'Prefix text:',\n actionButtons: [\n {\n actionButtonGlyph: 'refresh',\n actionButtonCallback: () => {\n alert('Blueberry refresh button clicked');\n },\n actionButtonId: 'refresh-button-1',\n actionButtonLabel: 'Refresh Item'\n },\n {\n actionButtonGlyph: 'settings',\n actionButtonCallback: () => {\n alert('Blueberry settings button clicked');\n },\n actionButtonLabel: 'Settings'\n }\n ],\n showDeleteButton: true,\n deleteCallback: () => {\n alert('Blueberry delete button clicked');\n }\n }\n },\n {\n value: 'Cherry',\n data: {\n type: 'fruit'\n }\n }\n ],\n searchInScopeText: 'Search in [Fruits]',\n searchInScopeCounter: 1234,\n searchInScopeCallback: () => {\n alert('Search in scope callback clicked');\n }\n },\n {\n value: 'Vegetables',\n isGroupHeader: true,\n children: [\n {\n value: 'Broccoli',\n data: {\n type: 'vegetable',\n subline: 'Flower vegetable',\n avatarLabel: 'John Doe'\n }\n },\n {\n value: 'Carrot',\n data: {\n type: 'vegetable',\n subline: 'Root vegetable',\n listIconGlyph: 'cart'\n }\n },\n {\n value: 'Corn',\n data: {\n type: 'vegetable'\n }\n },\n {\n value: 'Radish',\n data: {\n type: 'vegetable'\n }\n }\n ],\n showMoreText: 'Show More',\n showMoreCounter: 1234,\n showMoreCallback: () => {\n alert('Show more callback clicked');\n }\n }\n];\n", "html": "Shell search field example type:\n
    \n\n \n \n \n\n
    \nEmpty search results example type:\n
    \n\n \n \n\n
    \n\n\n
    \n \n \n \n \n \n Product Identifier\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n
    \n\n\n
    \n \n
    \n
    \n\n\n @if (emptyResultsType === 'illustratedMessage') {\n
    \n
    \n

    No Results

    \n

    Start by proiding your search criteria.

    \n
    \n
    \n }\n
    \n" }, + { + "name": "shellbar-responsive-example", + "description": "Shellbar Responsive", + "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", + "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, { "name": "shellbar-branding-context-area-example", "description": "Shellbar Branding Context Area", "typescript": "import { Component, ElementRef, signal, ViewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ClickedDirective } from '@fundamental-ngx/cdk';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport {\n ShellbarComponent,\n ShellbarMenuItem,\n ShellbarModule,\n ShellbarUser,\n ShellbarUserMenu\n} from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\n@Component({\n selector: 'fd-shellbar-branding-context-area-example',\n templateUrl: './shellbar-branding-context-area-example.component.html',\n imports: [\n ShellbarModule,\n MenuModule,\n AvatarComponent,\n ClickedDirective,\n ButtonComponent,\n FormsModule,\n ProductSwitchModule,\n SearchFieldComponent,\n ObjectStatusComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n PopoverModule,\n ListModule,\n PanelModule,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarBrandingContextAreaExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n @ViewChild(ShellbarComponent, { read: ElementRef })\n shellbar: ElementRef;\n\n expanded = true;\n\n isOpen = false;\n\n searchTerm = '';\n\n inputText = '';\n\n showButtonWithPriority3 = true;\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n productMenuItems: ShellbarMenuItem[] = [\n {\n name: 'Application A',\n callback: () => {\n alert('Application A Clicked');\n }\n },\n {\n name: 'Application B',\n callback: () => {\n alert('Application B Clicked');\n }\n },\n {\n name: 'Application C',\n callback: () => {\n alert('Application C Clicked');\n }\n },\n {\n name: 'Application D',\n callback: () => {\n alert('Application D Clicked');\n }\n }\n ];\n\n accountToggledState = signal(true);\n filterToggledState = signal(false);\n cartToggledState = signal(false);\n\n actions = [\n {\n glyph: 'account',\n callback: () => this.actionAccountCallback(),\n label: 'Account',\n ariaLabel: 'Account Action',\n title: 'Account',\n type: 'transparent' as ButtonType,\n toggled: this.accountToggledState\n },\n {\n glyph: 'filter',\n callback: () => this.actionFilterCallback(),\n label: 'Filter',\n ariaLabel: 'Filter Action',\n title: 'Filter',\n type: 'attention' as ButtonType,\n toggled: this.filterToggledState\n },\n {\n glyph: 'cart',\n callback: () => this.actionCartCallback(),\n label: 'Cart',\n ariaLabel: 'Cart Action',\n type: 'positive' as ButtonType,\n title: 'Cart',\n toggled: this.cartToggledState\n },\n {\n glyph: 'bell',\n callback: (event: MouseEvent) => this.actionNotificationCallback(event),\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home'),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n user: ShellbarUser = {\n fullName: 'William Willson',\n colorAccent: 6\n };\n\n userMenu: ShellbarUserMenu[] = [\n { text: 'Settings', callback: this.settingsCallback },\n { text: 'Sign Out', callback: this.signOutCallback }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n brandingClicked($event: Event): void {\n console.log($event);\n alert('Branding clicked');\n }\n\n settingsCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Settings Clicked');\n }\n\n signOutCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionAccountCallback(): void {\n this.accountToggledState.set(!this.accountToggledState());\n }\n\n actionFilterCallback(): void {\n this.filterToggledState.set(!this.filterToggledState());\n }\n\n actionCartCallback(): void {\n this.cartToggledState.set(!this.cartToggledState());\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n assistiveToolsCallback(): void {\n alert('Assistive Tools Clicked');\n }\n\n navClicked(event): void {\n console.log(event);\n alert('Navigation Button Clicked');\n }\n\n backClicked(event): void {\n console.log(event);\n alert('Back Button Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n toggleButton3(): void {\n this.showButtonWithPriority3 = !this.showButtonWithPriority3;\n }\n\n itemVisibilityChanged(event: any): void {\n console.log(event);\n }\n}\n", "html": "\n \n \n \n \n Product Identifier\n \n\n \n \n \n \n \n \n @if (showButtonWithPriority3) {\n \n }\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n\n\n
    \n\n\n" }, - { - "name": "shellbar-context-area-overflow-example", - "description": "Shellbar Context Area Overflow", - "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", - "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" - }, { "name": "shellbar-growing-group-example", "description": "Shellbar Growing Group", @@ -45429,10 +45495,10 @@ "html": "

    This example shows Shellbar groups taking only space needed for the content inside.

    \n\n \n \n \n \n Product Identifier\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n" }, { - "name": "shellbar-responsive-example", - "description": "Shellbar Responsive", - "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", - "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + "name": "shellbar-context-area-overflow-example", + "description": "Shellbar Context Area Overflow", + "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", + "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" } ] }, @@ -45488,18 +45554,18 @@ "typescript": "import { Component, inject, OnInit, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { IllustratedMessageModule, SvgConfig } from '@fundamental-ngx/core/illustrated-message';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { SegmentedButtonComponent } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\nimport { DataProvider, SearchFieldDataSource } from '@fundamental-ngx/platform/shared';\nimport { Observable, of } from 'rxjs';\n\n@Component({\n selector: 'fd-shellbar-complex-search-results-example',\n templateUrl: './shellbar-complex-search-results-example.component.html',\n imports: [\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarModule,\n BarRightDirective,\n MessageToastModule,\n SearchFieldComponent,\n ShellbarActionComponent,\n FormsModule,\n SegmentedButtonComponent,\n CheckboxComponent,\n IllustratedMessageModule\n ]\n})\nexport class ShellbarComplexSearchResultsExampleComponent implements OnInit {\n shellSearchField = viewChild('shellSearchField');\n\n dataSource: SearchFieldDataSource;\n\n expanded = true;\n\n exampleType: 'default' | 'advancedFilter' | 'mobile' = 'default';\n\n emptyResultsType: 'illustratedMessage' | 'customSuggestions' = 'illustratedMessage';\n\n emptyDefaultSuggestions: SuggestionItem[] = [\n {\n value: 'Peach',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Pear',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Plum',\n data: {\n type: 'fruit'\n }\n }\n ];\n\n categories: ValueLabelItem[] = [\n {\n value: 'fruit',\n label: 'Fruits'\n },\n {\n value: 'vegetable',\n label: 'Vegetables'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n label: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n label: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n smallConfig: SvgConfig = {\n small: { url: 'assets/images/sapIllus-Ice-Cream-Demo-Small.svg', id: 'sapIllus-Ice-Cream-Demo-Small' }\n };\n\n showCategories = true;\n\n suggestionsLoading = false;\n\n private _messageToastService = inject(MessageToastService);\n\n ngOnInit(): void {\n this.dataSource = new SearchFieldDataSource(new ShellSearchFieldDataProvider());\n SUGGESTIONS[0].children?.forEach((child) => {\n this.emptyDefaultSuggestions.push(child);\n });\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n showAllSearchResultsClicked(): void {\n this.suggestionsLoading = true;\n setTimeout(() => {\n this.suggestionsLoading = false;\n this.shellSearchField()?.resetCategory();\n this.shellSearchField()?.clearTextInput();\n }, 500);\n }\n\n submit(event: SearchInput): void {\n alert('Search submitted. See developer console for event');\n console.log(event);\n }\n}\n\nexport class ShellSearchFieldDataProvider extends DataProvider {\n constructor() {\n super();\n }\n\n fetch(params: Map): Observable {\n const data = SUGGESTIONS;\n const name = params.get('keyword');\n const category = params.get('category');\n if ((!name || name.trim() === '') && !category) {\n return of(data);\n } else {\n const filteredData = data.filter((suggestion) => {\n let foundMatchingChild = false;\n if (suggestion.children) {\n for (let i = 0; i < suggestion.children.length && !foundMatchingChild; i++) {\n foundMatchingChild = this._checkForMatches(suggestion.children[i], name, category);\n }\n } else {\n foundMatchingChild = this._checkForMatches(suggestion, name, category);\n }\n return foundMatchingChild;\n });\n return of(filteredData);\n }\n }\n\n private _checkForMatches(item: any, name: string | undefined, category: string | undefined): boolean {\n let foundMatchingItem = false;\n if (name && category) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1 && item.data?.type === category) {\n foundMatchingItem = true;\n }\n } else if (name) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1) {\n foundMatchingItem = true;\n }\n } else if (category) {\n if (item.data?.type === category) {\n foundMatchingItem = true;\n }\n }\n return foundMatchingItem;\n }\n}\n\nconst SUGGESTIONS: SuggestionItem[] = [\n {\n value: 'Fruits',\n isGroupHeader: true,\n children: [\n {\n value: 'Apple',\n data: {\n type: 'fruit',\n listIconGlyph: 'globe'\n }\n },\n {\n value: 'Banana',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Blueberry',\n data: {\n type: 'fruit',\n prefix: 'Prefix text:',\n actionButtons: [\n {\n actionButtonGlyph: 'refresh',\n actionButtonCallback: () => {\n alert('Blueberry refresh button clicked');\n },\n actionButtonId: 'refresh-button-1',\n actionButtonLabel: 'Refresh Item'\n },\n {\n actionButtonGlyph: 'settings',\n actionButtonCallback: () => {\n alert('Blueberry settings button clicked');\n },\n actionButtonLabel: 'Settings'\n }\n ],\n showDeleteButton: true,\n deleteCallback: () => {\n alert('Blueberry delete button clicked');\n }\n }\n },\n {\n value: 'Cherry',\n data: {\n type: 'fruit'\n }\n }\n ],\n searchInScopeText: 'Search in [Fruits]',\n searchInScopeCounter: 1234,\n searchInScopeCallback: () => {\n alert('Search in scope callback clicked');\n }\n },\n {\n value: 'Vegetables',\n isGroupHeader: true,\n children: [\n {\n value: 'Broccoli',\n data: {\n type: 'vegetable',\n subline: 'Flower vegetable',\n avatarLabel: 'John Doe'\n }\n },\n {\n value: 'Carrot',\n data: {\n type: 'vegetable',\n subline: 'Root vegetable',\n listIconGlyph: 'cart'\n }\n },\n {\n value: 'Corn',\n data: {\n type: 'vegetable'\n }\n },\n {\n value: 'Radish',\n data: {\n type: 'vegetable'\n }\n }\n ],\n showMoreText: 'Show More',\n showMoreCounter: 1234,\n showMoreCallback: () => {\n alert('Show more callback clicked');\n }\n }\n];\n", "html": "Shell search field example type:\n
    \n\n \n \n \n\n
    \nEmpty search results example type:\n
    \n\n \n \n\n
    \n\n\n
    \n \n \n \n \n \n Product Identifier\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n
    \n\n\n
    \n \n
    \n
    \n\n\n @if (emptyResultsType === 'illustratedMessage') {\n
    \n
    \n

    No Results

    \n

    Start by proiding your search criteria.

    \n
    \n
    \n }\n
    \n" }, + { + "name": "shellbar-responsive-example", + "description": "Shellbar Responsive", + "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", + "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, { "name": "shellbar-branding-context-area-example", "description": "Shellbar Branding Context Area", "typescript": "import { Component, ElementRef, signal, ViewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ClickedDirective } from '@fundamental-ngx/cdk';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport {\n ShellbarComponent,\n ShellbarMenuItem,\n ShellbarModule,\n ShellbarUser,\n ShellbarUserMenu\n} from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\n@Component({\n selector: 'fd-shellbar-branding-context-area-example',\n templateUrl: './shellbar-branding-context-area-example.component.html',\n imports: [\n ShellbarModule,\n MenuModule,\n AvatarComponent,\n ClickedDirective,\n ButtonComponent,\n FormsModule,\n ProductSwitchModule,\n SearchFieldComponent,\n ObjectStatusComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n PopoverModule,\n ListModule,\n PanelModule,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarBrandingContextAreaExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n @ViewChild(ShellbarComponent, { read: ElementRef })\n shellbar: ElementRef;\n\n expanded = true;\n\n isOpen = false;\n\n searchTerm = '';\n\n inputText = '';\n\n showButtonWithPriority3 = true;\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n productMenuItems: ShellbarMenuItem[] = [\n {\n name: 'Application A',\n callback: () => {\n alert('Application A Clicked');\n }\n },\n {\n name: 'Application B',\n callback: () => {\n alert('Application B Clicked');\n }\n },\n {\n name: 'Application C',\n callback: () => {\n alert('Application C Clicked');\n }\n },\n {\n name: 'Application D',\n callback: () => {\n alert('Application D Clicked');\n }\n }\n ];\n\n accountToggledState = signal(true);\n filterToggledState = signal(false);\n cartToggledState = signal(false);\n\n actions = [\n {\n glyph: 'account',\n callback: () => this.actionAccountCallback(),\n label: 'Account',\n ariaLabel: 'Account Action',\n title: 'Account',\n type: 'transparent' as ButtonType,\n toggled: this.accountToggledState\n },\n {\n glyph: 'filter',\n callback: () => this.actionFilterCallback(),\n label: 'Filter',\n ariaLabel: 'Filter Action',\n title: 'Filter',\n type: 'attention' as ButtonType,\n toggled: this.filterToggledState\n },\n {\n glyph: 'cart',\n callback: () => this.actionCartCallback(),\n label: 'Cart',\n ariaLabel: 'Cart Action',\n type: 'positive' as ButtonType,\n title: 'Cart',\n toggled: this.cartToggledState\n },\n {\n glyph: 'bell',\n callback: (event: MouseEvent) => this.actionNotificationCallback(event),\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home'),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n user: ShellbarUser = {\n fullName: 'William Willson',\n colorAccent: 6\n };\n\n userMenu: ShellbarUserMenu[] = [\n { text: 'Settings', callback: this.settingsCallback },\n { text: 'Sign Out', callback: this.signOutCallback }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n brandingClicked($event: Event): void {\n console.log($event);\n alert('Branding clicked');\n }\n\n settingsCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Settings Clicked');\n }\n\n signOutCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionAccountCallback(): void {\n this.accountToggledState.set(!this.accountToggledState());\n }\n\n actionFilterCallback(): void {\n this.filterToggledState.set(!this.filterToggledState());\n }\n\n actionCartCallback(): void {\n this.cartToggledState.set(!this.cartToggledState());\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n assistiveToolsCallback(): void {\n alert('Assistive Tools Clicked');\n }\n\n navClicked(event): void {\n console.log(event);\n alert('Navigation Button Clicked');\n }\n\n backClicked(event): void {\n console.log(event);\n alert('Back Button Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n toggleButton3(): void {\n this.showButtonWithPriority3 = !this.showButtonWithPriority3;\n }\n\n itemVisibilityChanged(event: any): void {\n console.log(event);\n }\n}\n", "html": "\n \n \n \n \n Product Identifier\n \n\n \n \n \n \n \n \n @if (showButtonWithPriority3) {\n \n }\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n\n\n
    \n\n\n" }, - { - "name": "shellbar-context-area-overflow-example", - "description": "Shellbar Context Area Overflow", - "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", - "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" - }, { "name": "shellbar-growing-group-example", "description": "Shellbar Growing Group", @@ -45507,10 +45573,10 @@ "html": "

    This example shows Shellbar groups taking only space needed for the content inside.

    \n\n \n \n \n \n Product Identifier\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n" }, { - "name": "shellbar-responsive-example", - "description": "Shellbar Responsive", - "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", - "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + "name": "shellbar-context-area-overflow-example", + "description": "Shellbar Context Area Overflow", + "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", + "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" } ] }, @@ -45554,18 +45620,18 @@ "typescript": "import { Component, inject, OnInit, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { IllustratedMessageModule, SvgConfig } from '@fundamental-ngx/core/illustrated-message';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { SegmentedButtonComponent } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\nimport { DataProvider, SearchFieldDataSource } from '@fundamental-ngx/platform/shared';\nimport { Observable, of } from 'rxjs';\n\n@Component({\n selector: 'fd-shellbar-complex-search-results-example',\n templateUrl: './shellbar-complex-search-results-example.component.html',\n imports: [\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarModule,\n BarRightDirective,\n MessageToastModule,\n SearchFieldComponent,\n ShellbarActionComponent,\n FormsModule,\n SegmentedButtonComponent,\n CheckboxComponent,\n IllustratedMessageModule\n ]\n})\nexport class ShellbarComplexSearchResultsExampleComponent implements OnInit {\n shellSearchField = viewChild('shellSearchField');\n\n dataSource: SearchFieldDataSource;\n\n expanded = true;\n\n exampleType: 'default' | 'advancedFilter' | 'mobile' = 'default';\n\n emptyResultsType: 'illustratedMessage' | 'customSuggestions' = 'illustratedMessage';\n\n emptyDefaultSuggestions: SuggestionItem[] = [\n {\n value: 'Peach',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Pear',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Plum',\n data: {\n type: 'fruit'\n }\n }\n ];\n\n categories: ValueLabelItem[] = [\n {\n value: 'fruit',\n label: 'Fruits'\n },\n {\n value: 'vegetable',\n label: 'Vegetables'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n label: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n label: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n smallConfig: SvgConfig = {\n small: { url: 'assets/images/sapIllus-Ice-Cream-Demo-Small.svg', id: 'sapIllus-Ice-Cream-Demo-Small' }\n };\n\n showCategories = true;\n\n suggestionsLoading = false;\n\n private _messageToastService = inject(MessageToastService);\n\n ngOnInit(): void {\n this.dataSource = new SearchFieldDataSource(new ShellSearchFieldDataProvider());\n SUGGESTIONS[0].children?.forEach((child) => {\n this.emptyDefaultSuggestions.push(child);\n });\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n showAllSearchResultsClicked(): void {\n this.suggestionsLoading = true;\n setTimeout(() => {\n this.suggestionsLoading = false;\n this.shellSearchField()?.resetCategory();\n this.shellSearchField()?.clearTextInput();\n }, 500);\n }\n\n submit(event: SearchInput): void {\n alert('Search submitted. See developer console for event');\n console.log(event);\n }\n}\n\nexport class ShellSearchFieldDataProvider extends DataProvider {\n constructor() {\n super();\n }\n\n fetch(params: Map): Observable {\n const data = SUGGESTIONS;\n const name = params.get('keyword');\n const category = params.get('category');\n if ((!name || name.trim() === '') && !category) {\n return of(data);\n } else {\n const filteredData = data.filter((suggestion) => {\n let foundMatchingChild = false;\n if (suggestion.children) {\n for (let i = 0; i < suggestion.children.length && !foundMatchingChild; i++) {\n foundMatchingChild = this._checkForMatches(suggestion.children[i], name, category);\n }\n } else {\n foundMatchingChild = this._checkForMatches(suggestion, name, category);\n }\n return foundMatchingChild;\n });\n return of(filteredData);\n }\n }\n\n private _checkForMatches(item: any, name: string | undefined, category: string | undefined): boolean {\n let foundMatchingItem = false;\n if (name && category) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1 && item.data?.type === category) {\n foundMatchingItem = true;\n }\n } else if (name) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1) {\n foundMatchingItem = true;\n }\n } else if (category) {\n if (item.data?.type === category) {\n foundMatchingItem = true;\n }\n }\n return foundMatchingItem;\n }\n}\n\nconst SUGGESTIONS: SuggestionItem[] = [\n {\n value: 'Fruits',\n isGroupHeader: true,\n children: [\n {\n value: 'Apple',\n data: {\n type: 'fruit',\n listIconGlyph: 'globe'\n }\n },\n {\n value: 'Banana',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Blueberry',\n data: {\n type: 'fruit',\n prefix: 'Prefix text:',\n actionButtons: [\n {\n actionButtonGlyph: 'refresh',\n actionButtonCallback: () => {\n alert('Blueberry refresh button clicked');\n },\n actionButtonId: 'refresh-button-1',\n actionButtonLabel: 'Refresh Item'\n },\n {\n actionButtonGlyph: 'settings',\n actionButtonCallback: () => {\n alert('Blueberry settings button clicked');\n },\n actionButtonLabel: 'Settings'\n }\n ],\n showDeleteButton: true,\n deleteCallback: () => {\n alert('Blueberry delete button clicked');\n }\n }\n },\n {\n value: 'Cherry',\n data: {\n type: 'fruit'\n }\n }\n ],\n searchInScopeText: 'Search in [Fruits]',\n searchInScopeCounter: 1234,\n searchInScopeCallback: () => {\n alert('Search in scope callback clicked');\n }\n },\n {\n value: 'Vegetables',\n isGroupHeader: true,\n children: [\n {\n value: 'Broccoli',\n data: {\n type: 'vegetable',\n subline: 'Flower vegetable',\n avatarLabel: 'John Doe'\n }\n },\n {\n value: 'Carrot',\n data: {\n type: 'vegetable',\n subline: 'Root vegetable',\n listIconGlyph: 'cart'\n }\n },\n {\n value: 'Corn',\n data: {\n type: 'vegetable'\n }\n },\n {\n value: 'Radish',\n data: {\n type: 'vegetable'\n }\n }\n ],\n showMoreText: 'Show More',\n showMoreCounter: 1234,\n showMoreCallback: () => {\n alert('Show more callback clicked');\n }\n }\n];\n", "html": "Shell search field example type:\n
    \n\n \n \n \n\n
    \nEmpty search results example type:\n
    \n\n \n \n\n
    \n\n\n
    \n \n \n \n \n \n Product Identifier\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n
    \n\n\n
    \n \n
    \n
    \n\n\n @if (emptyResultsType === 'illustratedMessage') {\n
    \n
    \n

    No Results

    \n

    Start by proiding your search criteria.

    \n
    \n
    \n }\n
    \n" }, + { + "name": "shellbar-responsive-example", + "description": "Shellbar Responsive", + "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", + "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, { "name": "shellbar-branding-context-area-example", "description": "Shellbar Branding Context Area", "typescript": "import { Component, ElementRef, signal, ViewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ClickedDirective } from '@fundamental-ngx/cdk';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport {\n ShellbarComponent,\n ShellbarMenuItem,\n ShellbarModule,\n ShellbarUser,\n ShellbarUserMenu\n} from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\n@Component({\n selector: 'fd-shellbar-branding-context-area-example',\n templateUrl: './shellbar-branding-context-area-example.component.html',\n imports: [\n ShellbarModule,\n MenuModule,\n AvatarComponent,\n ClickedDirective,\n ButtonComponent,\n FormsModule,\n ProductSwitchModule,\n SearchFieldComponent,\n ObjectStatusComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n PopoverModule,\n ListModule,\n PanelModule,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarBrandingContextAreaExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n @ViewChild(ShellbarComponent, { read: ElementRef })\n shellbar: ElementRef;\n\n expanded = true;\n\n isOpen = false;\n\n searchTerm = '';\n\n inputText = '';\n\n showButtonWithPriority3 = true;\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n productMenuItems: ShellbarMenuItem[] = [\n {\n name: 'Application A',\n callback: () => {\n alert('Application A Clicked');\n }\n },\n {\n name: 'Application B',\n callback: () => {\n alert('Application B Clicked');\n }\n },\n {\n name: 'Application C',\n callback: () => {\n alert('Application C Clicked');\n }\n },\n {\n name: 'Application D',\n callback: () => {\n alert('Application D Clicked');\n }\n }\n ];\n\n accountToggledState = signal(true);\n filterToggledState = signal(false);\n cartToggledState = signal(false);\n\n actions = [\n {\n glyph: 'account',\n callback: () => this.actionAccountCallback(),\n label: 'Account',\n ariaLabel: 'Account Action',\n title: 'Account',\n type: 'transparent' as ButtonType,\n toggled: this.accountToggledState\n },\n {\n glyph: 'filter',\n callback: () => this.actionFilterCallback(),\n label: 'Filter',\n ariaLabel: 'Filter Action',\n title: 'Filter',\n type: 'attention' as ButtonType,\n toggled: this.filterToggledState\n },\n {\n glyph: 'cart',\n callback: () => this.actionCartCallback(),\n label: 'Cart',\n ariaLabel: 'Cart Action',\n type: 'positive' as ButtonType,\n title: 'Cart',\n toggled: this.cartToggledState\n },\n {\n glyph: 'bell',\n callback: (event: MouseEvent) => this.actionNotificationCallback(event),\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home'),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n user: ShellbarUser = {\n fullName: 'William Willson',\n colorAccent: 6\n };\n\n userMenu: ShellbarUserMenu[] = [\n { text: 'Settings', callback: this.settingsCallback },\n { text: 'Sign Out', callback: this.signOutCallback }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n brandingClicked($event: Event): void {\n console.log($event);\n alert('Branding clicked');\n }\n\n settingsCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Settings Clicked');\n }\n\n signOutCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionAccountCallback(): void {\n this.accountToggledState.set(!this.accountToggledState());\n }\n\n actionFilterCallback(): void {\n this.filterToggledState.set(!this.filterToggledState());\n }\n\n actionCartCallback(): void {\n this.cartToggledState.set(!this.cartToggledState());\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n assistiveToolsCallback(): void {\n alert('Assistive Tools Clicked');\n }\n\n navClicked(event): void {\n console.log(event);\n alert('Navigation Button Clicked');\n }\n\n backClicked(event): void {\n console.log(event);\n alert('Back Button Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n toggleButton3(): void {\n this.showButtonWithPriority3 = !this.showButtonWithPriority3;\n }\n\n itemVisibilityChanged(event: any): void {\n console.log(event);\n }\n}\n", "html": "\n \n \n \n \n Product Identifier\n \n\n \n \n \n \n \n \n @if (showButtonWithPriority3) {\n \n }\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n\n\n
    \n\n\n" }, - { - "name": "shellbar-context-area-overflow-example", - "description": "Shellbar Context Area Overflow", - "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", - "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" - }, { "name": "shellbar-growing-group-example", "description": "Shellbar Growing Group", @@ -45573,10 +45639,10 @@ "html": "

    This example shows Shellbar groups taking only space needed for the content inside.

    \n\n \n \n \n \n Product Identifier\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n" }, { - "name": "shellbar-responsive-example", - "description": "Shellbar Responsive", - "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", - "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + "name": "shellbar-context-area-overflow-example", + "description": "Shellbar Context Area Overflow", + "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", + "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" } ] }, @@ -45631,18 +45697,18 @@ "typescript": "import { Component, inject, OnInit, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { IllustratedMessageModule, SvgConfig } from '@fundamental-ngx/core/illustrated-message';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { SegmentedButtonComponent } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\nimport { DataProvider, SearchFieldDataSource } from '@fundamental-ngx/platform/shared';\nimport { Observable, of } from 'rxjs';\n\n@Component({\n selector: 'fd-shellbar-complex-search-results-example',\n templateUrl: './shellbar-complex-search-results-example.component.html',\n imports: [\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarModule,\n BarRightDirective,\n MessageToastModule,\n SearchFieldComponent,\n ShellbarActionComponent,\n FormsModule,\n SegmentedButtonComponent,\n CheckboxComponent,\n IllustratedMessageModule\n ]\n})\nexport class ShellbarComplexSearchResultsExampleComponent implements OnInit {\n shellSearchField = viewChild('shellSearchField');\n\n dataSource: SearchFieldDataSource;\n\n expanded = true;\n\n exampleType: 'default' | 'advancedFilter' | 'mobile' = 'default';\n\n emptyResultsType: 'illustratedMessage' | 'customSuggestions' = 'illustratedMessage';\n\n emptyDefaultSuggestions: SuggestionItem[] = [\n {\n value: 'Peach',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Pear',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Plum',\n data: {\n type: 'fruit'\n }\n }\n ];\n\n categories: ValueLabelItem[] = [\n {\n value: 'fruit',\n label: 'Fruits'\n },\n {\n value: 'vegetable',\n label: 'Vegetables'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n label: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n label: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n smallConfig: SvgConfig = {\n small: { url: 'assets/images/sapIllus-Ice-Cream-Demo-Small.svg', id: 'sapIllus-Ice-Cream-Demo-Small' }\n };\n\n showCategories = true;\n\n suggestionsLoading = false;\n\n private _messageToastService = inject(MessageToastService);\n\n ngOnInit(): void {\n this.dataSource = new SearchFieldDataSource(new ShellSearchFieldDataProvider());\n SUGGESTIONS[0].children?.forEach((child) => {\n this.emptyDefaultSuggestions.push(child);\n });\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n showAllSearchResultsClicked(): void {\n this.suggestionsLoading = true;\n setTimeout(() => {\n this.suggestionsLoading = false;\n this.shellSearchField()?.resetCategory();\n this.shellSearchField()?.clearTextInput();\n }, 500);\n }\n\n submit(event: SearchInput): void {\n alert('Search submitted. See developer console for event');\n console.log(event);\n }\n}\n\nexport class ShellSearchFieldDataProvider extends DataProvider {\n constructor() {\n super();\n }\n\n fetch(params: Map): Observable {\n const data = SUGGESTIONS;\n const name = params.get('keyword');\n const category = params.get('category');\n if ((!name || name.trim() === '') && !category) {\n return of(data);\n } else {\n const filteredData = data.filter((suggestion) => {\n let foundMatchingChild = false;\n if (suggestion.children) {\n for (let i = 0; i < suggestion.children.length && !foundMatchingChild; i++) {\n foundMatchingChild = this._checkForMatches(suggestion.children[i], name, category);\n }\n } else {\n foundMatchingChild = this._checkForMatches(suggestion, name, category);\n }\n return foundMatchingChild;\n });\n return of(filteredData);\n }\n }\n\n private _checkForMatches(item: any, name: string | undefined, category: string | undefined): boolean {\n let foundMatchingItem = false;\n if (name && category) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1 && item.data?.type === category) {\n foundMatchingItem = true;\n }\n } else if (name) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1) {\n foundMatchingItem = true;\n }\n } else if (category) {\n if (item.data?.type === category) {\n foundMatchingItem = true;\n }\n }\n return foundMatchingItem;\n }\n}\n\nconst SUGGESTIONS: SuggestionItem[] = [\n {\n value: 'Fruits',\n isGroupHeader: true,\n children: [\n {\n value: 'Apple',\n data: {\n type: 'fruit',\n listIconGlyph: 'globe'\n }\n },\n {\n value: 'Banana',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Blueberry',\n data: {\n type: 'fruit',\n prefix: 'Prefix text:',\n actionButtons: [\n {\n actionButtonGlyph: 'refresh',\n actionButtonCallback: () => {\n alert('Blueberry refresh button clicked');\n },\n actionButtonId: 'refresh-button-1',\n actionButtonLabel: 'Refresh Item'\n },\n {\n actionButtonGlyph: 'settings',\n actionButtonCallback: () => {\n alert('Blueberry settings button clicked');\n },\n actionButtonLabel: 'Settings'\n }\n ],\n showDeleteButton: true,\n deleteCallback: () => {\n alert('Blueberry delete button clicked');\n }\n }\n },\n {\n value: 'Cherry',\n data: {\n type: 'fruit'\n }\n }\n ],\n searchInScopeText: 'Search in [Fruits]',\n searchInScopeCounter: 1234,\n searchInScopeCallback: () => {\n alert('Search in scope callback clicked');\n }\n },\n {\n value: 'Vegetables',\n isGroupHeader: true,\n children: [\n {\n value: 'Broccoli',\n data: {\n type: 'vegetable',\n subline: 'Flower vegetable',\n avatarLabel: 'John Doe'\n }\n },\n {\n value: 'Carrot',\n data: {\n type: 'vegetable',\n subline: 'Root vegetable',\n listIconGlyph: 'cart'\n }\n },\n {\n value: 'Corn',\n data: {\n type: 'vegetable'\n }\n },\n {\n value: 'Radish',\n data: {\n type: 'vegetable'\n }\n }\n ],\n showMoreText: 'Show More',\n showMoreCounter: 1234,\n showMoreCallback: () => {\n alert('Show more callback clicked');\n }\n }\n];\n", "html": "Shell search field example type:\n
    \n\n \n \n \n\n
    \nEmpty search results example type:\n
    \n\n \n \n\n
    \n\n\n
    \n \n \n \n \n \n Product Identifier\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n
    \n\n\n
    \n \n
    \n
    \n\n\n @if (emptyResultsType === 'illustratedMessage') {\n
    \n
    \n

    No Results

    \n

    Start by proiding your search criteria.

    \n
    \n
    \n }\n
    \n" }, + { + "name": "shellbar-responsive-example", + "description": "Shellbar Responsive", + "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", + "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, { "name": "shellbar-branding-context-area-example", "description": "Shellbar Branding Context Area", "typescript": "import { Component, ElementRef, signal, ViewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ClickedDirective } from '@fundamental-ngx/cdk';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport {\n ShellbarComponent,\n ShellbarMenuItem,\n ShellbarModule,\n ShellbarUser,\n ShellbarUserMenu\n} from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\n@Component({\n selector: 'fd-shellbar-branding-context-area-example',\n templateUrl: './shellbar-branding-context-area-example.component.html',\n imports: [\n ShellbarModule,\n MenuModule,\n AvatarComponent,\n ClickedDirective,\n ButtonComponent,\n FormsModule,\n ProductSwitchModule,\n SearchFieldComponent,\n ObjectStatusComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n PopoverModule,\n ListModule,\n PanelModule,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarBrandingContextAreaExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n @ViewChild(ShellbarComponent, { read: ElementRef })\n shellbar: ElementRef;\n\n expanded = true;\n\n isOpen = false;\n\n searchTerm = '';\n\n inputText = '';\n\n showButtonWithPriority3 = true;\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n productMenuItems: ShellbarMenuItem[] = [\n {\n name: 'Application A',\n callback: () => {\n alert('Application A Clicked');\n }\n },\n {\n name: 'Application B',\n callback: () => {\n alert('Application B Clicked');\n }\n },\n {\n name: 'Application C',\n callback: () => {\n alert('Application C Clicked');\n }\n },\n {\n name: 'Application D',\n callback: () => {\n alert('Application D Clicked');\n }\n }\n ];\n\n accountToggledState = signal(true);\n filterToggledState = signal(false);\n cartToggledState = signal(false);\n\n actions = [\n {\n glyph: 'account',\n callback: () => this.actionAccountCallback(),\n label: 'Account',\n ariaLabel: 'Account Action',\n title: 'Account',\n type: 'transparent' as ButtonType,\n toggled: this.accountToggledState\n },\n {\n glyph: 'filter',\n callback: () => this.actionFilterCallback(),\n label: 'Filter',\n ariaLabel: 'Filter Action',\n title: 'Filter',\n type: 'attention' as ButtonType,\n toggled: this.filterToggledState\n },\n {\n glyph: 'cart',\n callback: () => this.actionCartCallback(),\n label: 'Cart',\n ariaLabel: 'Cart Action',\n type: 'positive' as ButtonType,\n title: 'Cart',\n toggled: this.cartToggledState\n },\n {\n glyph: 'bell',\n callback: (event: MouseEvent) => this.actionNotificationCallback(event),\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home'),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n user: ShellbarUser = {\n fullName: 'William Willson',\n colorAccent: 6\n };\n\n userMenu: ShellbarUserMenu[] = [\n { text: 'Settings', callback: this.settingsCallback },\n { text: 'Sign Out', callback: this.signOutCallback }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n brandingClicked($event: Event): void {\n console.log($event);\n alert('Branding clicked');\n }\n\n settingsCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Settings Clicked');\n }\n\n signOutCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionAccountCallback(): void {\n this.accountToggledState.set(!this.accountToggledState());\n }\n\n actionFilterCallback(): void {\n this.filterToggledState.set(!this.filterToggledState());\n }\n\n actionCartCallback(): void {\n this.cartToggledState.set(!this.cartToggledState());\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n assistiveToolsCallback(): void {\n alert('Assistive Tools Clicked');\n }\n\n navClicked(event): void {\n console.log(event);\n alert('Navigation Button Clicked');\n }\n\n backClicked(event): void {\n console.log(event);\n alert('Back Button Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n toggleButton3(): void {\n this.showButtonWithPriority3 = !this.showButtonWithPriority3;\n }\n\n itemVisibilityChanged(event: any): void {\n console.log(event);\n }\n}\n", "html": "\n \n \n \n \n Product Identifier\n \n\n \n \n \n \n \n \n @if (showButtonWithPriority3) {\n \n }\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n\n\n
    \n\n\n" }, - { - "name": "shellbar-context-area-overflow-example", - "description": "Shellbar Context Area Overflow", - "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", - "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" - }, { "name": "shellbar-growing-group-example", "description": "Shellbar Growing Group", @@ -45650,10 +45716,10 @@ "html": "

    This example shows Shellbar groups taking only space needed for the content inside.

    \n\n \n \n \n \n Product Identifier\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n" }, { - "name": "shellbar-responsive-example", - "description": "Shellbar Responsive", - "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", - "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + "name": "shellbar-context-area-overflow-example", + "description": "Shellbar Context Area Overflow", + "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", + "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" } ] }, @@ -45689,18 +45755,18 @@ "typescript": "import { Component, inject, OnInit, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { IllustratedMessageModule, SvgConfig } from '@fundamental-ngx/core/illustrated-message';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { SegmentedButtonComponent } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\nimport { DataProvider, SearchFieldDataSource } from '@fundamental-ngx/platform/shared';\nimport { Observable, of } from 'rxjs';\n\n@Component({\n selector: 'fd-shellbar-complex-search-results-example',\n templateUrl: './shellbar-complex-search-results-example.component.html',\n imports: [\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarModule,\n BarRightDirective,\n MessageToastModule,\n SearchFieldComponent,\n ShellbarActionComponent,\n FormsModule,\n SegmentedButtonComponent,\n CheckboxComponent,\n IllustratedMessageModule\n ]\n})\nexport class ShellbarComplexSearchResultsExampleComponent implements OnInit {\n shellSearchField = viewChild('shellSearchField');\n\n dataSource: SearchFieldDataSource;\n\n expanded = true;\n\n exampleType: 'default' | 'advancedFilter' | 'mobile' = 'default';\n\n emptyResultsType: 'illustratedMessage' | 'customSuggestions' = 'illustratedMessage';\n\n emptyDefaultSuggestions: SuggestionItem[] = [\n {\n value: 'Peach',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Pear',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Plum',\n data: {\n type: 'fruit'\n }\n }\n ];\n\n categories: ValueLabelItem[] = [\n {\n value: 'fruit',\n label: 'Fruits'\n },\n {\n value: 'vegetable',\n label: 'Vegetables'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n label: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n label: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n smallConfig: SvgConfig = {\n small: { url: 'assets/images/sapIllus-Ice-Cream-Demo-Small.svg', id: 'sapIllus-Ice-Cream-Demo-Small' }\n };\n\n showCategories = true;\n\n suggestionsLoading = false;\n\n private _messageToastService = inject(MessageToastService);\n\n ngOnInit(): void {\n this.dataSource = new SearchFieldDataSource(new ShellSearchFieldDataProvider());\n SUGGESTIONS[0].children?.forEach((child) => {\n this.emptyDefaultSuggestions.push(child);\n });\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n showAllSearchResultsClicked(): void {\n this.suggestionsLoading = true;\n setTimeout(() => {\n this.suggestionsLoading = false;\n this.shellSearchField()?.resetCategory();\n this.shellSearchField()?.clearTextInput();\n }, 500);\n }\n\n submit(event: SearchInput): void {\n alert('Search submitted. See developer console for event');\n console.log(event);\n }\n}\n\nexport class ShellSearchFieldDataProvider extends DataProvider {\n constructor() {\n super();\n }\n\n fetch(params: Map): Observable {\n const data = SUGGESTIONS;\n const name = params.get('keyword');\n const category = params.get('category');\n if ((!name || name.trim() === '') && !category) {\n return of(data);\n } else {\n const filteredData = data.filter((suggestion) => {\n let foundMatchingChild = false;\n if (suggestion.children) {\n for (let i = 0; i < suggestion.children.length && !foundMatchingChild; i++) {\n foundMatchingChild = this._checkForMatches(suggestion.children[i], name, category);\n }\n } else {\n foundMatchingChild = this._checkForMatches(suggestion, name, category);\n }\n return foundMatchingChild;\n });\n return of(filteredData);\n }\n }\n\n private _checkForMatches(item: any, name: string | undefined, category: string | undefined): boolean {\n let foundMatchingItem = false;\n if (name && category) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1 && item.data?.type === category) {\n foundMatchingItem = true;\n }\n } else if (name) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1) {\n foundMatchingItem = true;\n }\n } else if (category) {\n if (item.data?.type === category) {\n foundMatchingItem = true;\n }\n }\n return foundMatchingItem;\n }\n}\n\nconst SUGGESTIONS: SuggestionItem[] = [\n {\n value: 'Fruits',\n isGroupHeader: true,\n children: [\n {\n value: 'Apple',\n data: {\n type: 'fruit',\n listIconGlyph: 'globe'\n }\n },\n {\n value: 'Banana',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Blueberry',\n data: {\n type: 'fruit',\n prefix: 'Prefix text:',\n actionButtons: [\n {\n actionButtonGlyph: 'refresh',\n actionButtonCallback: () => {\n alert('Blueberry refresh button clicked');\n },\n actionButtonId: 'refresh-button-1',\n actionButtonLabel: 'Refresh Item'\n },\n {\n actionButtonGlyph: 'settings',\n actionButtonCallback: () => {\n alert('Blueberry settings button clicked');\n },\n actionButtonLabel: 'Settings'\n }\n ],\n showDeleteButton: true,\n deleteCallback: () => {\n alert('Blueberry delete button clicked');\n }\n }\n },\n {\n value: 'Cherry',\n data: {\n type: 'fruit'\n }\n }\n ],\n searchInScopeText: 'Search in [Fruits]',\n searchInScopeCounter: 1234,\n searchInScopeCallback: () => {\n alert('Search in scope callback clicked');\n }\n },\n {\n value: 'Vegetables',\n isGroupHeader: true,\n children: [\n {\n value: 'Broccoli',\n data: {\n type: 'vegetable',\n subline: 'Flower vegetable',\n avatarLabel: 'John Doe'\n }\n },\n {\n value: 'Carrot',\n data: {\n type: 'vegetable',\n subline: 'Root vegetable',\n listIconGlyph: 'cart'\n }\n },\n {\n value: 'Corn',\n data: {\n type: 'vegetable'\n }\n },\n {\n value: 'Radish',\n data: {\n type: 'vegetable'\n }\n }\n ],\n showMoreText: 'Show More',\n showMoreCounter: 1234,\n showMoreCallback: () => {\n alert('Show more callback clicked');\n }\n }\n];\n", "html": "Shell search field example type:\n
    \n\n \n \n \n\n
    \nEmpty search results example type:\n
    \n\n \n \n\n
    \n\n\n
    \n \n \n \n \n \n Product Identifier\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n
    \n\n\n
    \n \n
    \n
    \n\n\n @if (emptyResultsType === 'illustratedMessage') {\n
    \n
    \n

    No Results

    \n

    Start by proiding your search criteria.

    \n
    \n
    \n }\n
    \n" }, + { + "name": "shellbar-responsive-example", + "description": "Shellbar Responsive", + "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", + "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, { "name": "shellbar-branding-context-area-example", "description": "Shellbar Branding Context Area", "typescript": "import { Component, ElementRef, signal, ViewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ClickedDirective } from '@fundamental-ngx/cdk';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport {\n ShellbarComponent,\n ShellbarMenuItem,\n ShellbarModule,\n ShellbarUser,\n ShellbarUserMenu\n} from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\n@Component({\n selector: 'fd-shellbar-branding-context-area-example',\n templateUrl: './shellbar-branding-context-area-example.component.html',\n imports: [\n ShellbarModule,\n MenuModule,\n AvatarComponent,\n ClickedDirective,\n ButtonComponent,\n FormsModule,\n ProductSwitchModule,\n SearchFieldComponent,\n ObjectStatusComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n PopoverModule,\n ListModule,\n PanelModule,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarBrandingContextAreaExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n @ViewChild(ShellbarComponent, { read: ElementRef })\n shellbar: ElementRef;\n\n expanded = true;\n\n isOpen = false;\n\n searchTerm = '';\n\n inputText = '';\n\n showButtonWithPriority3 = true;\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n productMenuItems: ShellbarMenuItem[] = [\n {\n name: 'Application A',\n callback: () => {\n alert('Application A Clicked');\n }\n },\n {\n name: 'Application B',\n callback: () => {\n alert('Application B Clicked');\n }\n },\n {\n name: 'Application C',\n callback: () => {\n alert('Application C Clicked');\n }\n },\n {\n name: 'Application D',\n callback: () => {\n alert('Application D Clicked');\n }\n }\n ];\n\n accountToggledState = signal(true);\n filterToggledState = signal(false);\n cartToggledState = signal(false);\n\n actions = [\n {\n glyph: 'account',\n callback: () => this.actionAccountCallback(),\n label: 'Account',\n ariaLabel: 'Account Action',\n title: 'Account',\n type: 'transparent' as ButtonType,\n toggled: this.accountToggledState\n },\n {\n glyph: 'filter',\n callback: () => this.actionFilterCallback(),\n label: 'Filter',\n ariaLabel: 'Filter Action',\n title: 'Filter',\n type: 'attention' as ButtonType,\n toggled: this.filterToggledState\n },\n {\n glyph: 'cart',\n callback: () => this.actionCartCallback(),\n label: 'Cart',\n ariaLabel: 'Cart Action',\n type: 'positive' as ButtonType,\n title: 'Cart',\n toggled: this.cartToggledState\n },\n {\n glyph: 'bell',\n callback: (event: MouseEvent) => this.actionNotificationCallback(event),\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home'),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n user: ShellbarUser = {\n fullName: 'William Willson',\n colorAccent: 6\n };\n\n userMenu: ShellbarUserMenu[] = [\n { text: 'Settings', callback: this.settingsCallback },\n { text: 'Sign Out', callback: this.signOutCallback }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n brandingClicked($event: Event): void {\n console.log($event);\n alert('Branding clicked');\n }\n\n settingsCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Settings Clicked');\n }\n\n signOutCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionAccountCallback(): void {\n this.accountToggledState.set(!this.accountToggledState());\n }\n\n actionFilterCallback(): void {\n this.filterToggledState.set(!this.filterToggledState());\n }\n\n actionCartCallback(): void {\n this.cartToggledState.set(!this.cartToggledState());\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n assistiveToolsCallback(): void {\n alert('Assistive Tools Clicked');\n }\n\n navClicked(event): void {\n console.log(event);\n alert('Navigation Button Clicked');\n }\n\n backClicked(event): void {\n console.log(event);\n alert('Back Button Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n toggleButton3(): void {\n this.showButtonWithPriority3 = !this.showButtonWithPriority3;\n }\n\n itemVisibilityChanged(event: any): void {\n console.log(event);\n }\n}\n", "html": "\n \n \n \n \n Product Identifier\n \n\n \n \n \n \n \n \n @if (showButtonWithPriority3) {\n \n }\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n\n\n
    \n\n\n" }, - { - "name": "shellbar-context-area-overflow-example", - "description": "Shellbar Context Area Overflow", - "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", - "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" - }, { "name": "shellbar-growing-group-example", "description": "Shellbar Growing Group", @@ -45708,10 +45774,10 @@ "html": "

    This example shows Shellbar groups taking only space needed for the content inside.

    \n\n \n \n \n \n Product Identifier\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n" }, { - "name": "shellbar-responsive-example", - "description": "Shellbar Responsive", - "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", - "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + "name": "shellbar-context-area-overflow-example", + "description": "Shellbar Context Area Overflow", + "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", + "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" } ] }, @@ -45747,18 +45813,18 @@ "typescript": "import { Component, inject, OnInit, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { IllustratedMessageModule, SvgConfig } from '@fundamental-ngx/core/illustrated-message';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { SegmentedButtonComponent } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\nimport { DataProvider, SearchFieldDataSource } from '@fundamental-ngx/platform/shared';\nimport { Observable, of } from 'rxjs';\n\n@Component({\n selector: 'fd-shellbar-complex-search-results-example',\n templateUrl: './shellbar-complex-search-results-example.component.html',\n imports: [\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarModule,\n BarRightDirective,\n MessageToastModule,\n SearchFieldComponent,\n ShellbarActionComponent,\n FormsModule,\n SegmentedButtonComponent,\n CheckboxComponent,\n IllustratedMessageModule\n ]\n})\nexport class ShellbarComplexSearchResultsExampleComponent implements OnInit {\n shellSearchField = viewChild('shellSearchField');\n\n dataSource: SearchFieldDataSource;\n\n expanded = true;\n\n exampleType: 'default' | 'advancedFilter' | 'mobile' = 'default';\n\n emptyResultsType: 'illustratedMessage' | 'customSuggestions' = 'illustratedMessage';\n\n emptyDefaultSuggestions: SuggestionItem[] = [\n {\n value: 'Peach',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Pear',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Plum',\n data: {\n type: 'fruit'\n }\n }\n ];\n\n categories: ValueLabelItem[] = [\n {\n value: 'fruit',\n label: 'Fruits'\n },\n {\n value: 'vegetable',\n label: 'Vegetables'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n label: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n label: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n smallConfig: SvgConfig = {\n small: { url: 'assets/images/sapIllus-Ice-Cream-Demo-Small.svg', id: 'sapIllus-Ice-Cream-Demo-Small' }\n };\n\n showCategories = true;\n\n suggestionsLoading = false;\n\n private _messageToastService = inject(MessageToastService);\n\n ngOnInit(): void {\n this.dataSource = new SearchFieldDataSource(new ShellSearchFieldDataProvider());\n SUGGESTIONS[0].children?.forEach((child) => {\n this.emptyDefaultSuggestions.push(child);\n });\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n showAllSearchResultsClicked(): void {\n this.suggestionsLoading = true;\n setTimeout(() => {\n this.suggestionsLoading = false;\n this.shellSearchField()?.resetCategory();\n this.shellSearchField()?.clearTextInput();\n }, 500);\n }\n\n submit(event: SearchInput): void {\n alert('Search submitted. See developer console for event');\n console.log(event);\n }\n}\n\nexport class ShellSearchFieldDataProvider extends DataProvider {\n constructor() {\n super();\n }\n\n fetch(params: Map): Observable {\n const data = SUGGESTIONS;\n const name = params.get('keyword');\n const category = params.get('category');\n if ((!name || name.trim() === '') && !category) {\n return of(data);\n } else {\n const filteredData = data.filter((suggestion) => {\n let foundMatchingChild = false;\n if (suggestion.children) {\n for (let i = 0; i < suggestion.children.length && !foundMatchingChild; i++) {\n foundMatchingChild = this._checkForMatches(suggestion.children[i], name, category);\n }\n } else {\n foundMatchingChild = this._checkForMatches(suggestion, name, category);\n }\n return foundMatchingChild;\n });\n return of(filteredData);\n }\n }\n\n private _checkForMatches(item: any, name: string | undefined, category: string | undefined): boolean {\n let foundMatchingItem = false;\n if (name && category) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1 && item.data?.type === category) {\n foundMatchingItem = true;\n }\n } else if (name) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1) {\n foundMatchingItem = true;\n }\n } else if (category) {\n if (item.data?.type === category) {\n foundMatchingItem = true;\n }\n }\n return foundMatchingItem;\n }\n}\n\nconst SUGGESTIONS: SuggestionItem[] = [\n {\n value: 'Fruits',\n isGroupHeader: true,\n children: [\n {\n value: 'Apple',\n data: {\n type: 'fruit',\n listIconGlyph: 'globe'\n }\n },\n {\n value: 'Banana',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Blueberry',\n data: {\n type: 'fruit',\n prefix: 'Prefix text:',\n actionButtons: [\n {\n actionButtonGlyph: 'refresh',\n actionButtonCallback: () => {\n alert('Blueberry refresh button clicked');\n },\n actionButtonId: 'refresh-button-1',\n actionButtonLabel: 'Refresh Item'\n },\n {\n actionButtonGlyph: 'settings',\n actionButtonCallback: () => {\n alert('Blueberry settings button clicked');\n },\n actionButtonLabel: 'Settings'\n }\n ],\n showDeleteButton: true,\n deleteCallback: () => {\n alert('Blueberry delete button clicked');\n }\n }\n },\n {\n value: 'Cherry',\n data: {\n type: 'fruit'\n }\n }\n ],\n searchInScopeText: 'Search in [Fruits]',\n searchInScopeCounter: 1234,\n searchInScopeCallback: () => {\n alert('Search in scope callback clicked');\n }\n },\n {\n value: 'Vegetables',\n isGroupHeader: true,\n children: [\n {\n value: 'Broccoli',\n data: {\n type: 'vegetable',\n subline: 'Flower vegetable',\n avatarLabel: 'John Doe'\n }\n },\n {\n value: 'Carrot',\n data: {\n type: 'vegetable',\n subline: 'Root vegetable',\n listIconGlyph: 'cart'\n }\n },\n {\n value: 'Corn',\n data: {\n type: 'vegetable'\n }\n },\n {\n value: 'Radish',\n data: {\n type: 'vegetable'\n }\n }\n ],\n showMoreText: 'Show More',\n showMoreCounter: 1234,\n showMoreCallback: () => {\n alert('Show more callback clicked');\n }\n }\n];\n", "html": "Shell search field example type:\n
    \n\n \n \n \n\n
    \nEmpty search results example type:\n
    \n\n \n \n\n
    \n\n\n
    \n \n \n \n \n \n Product Identifier\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n
    \n\n\n
    \n \n
    \n
    \n\n\n @if (emptyResultsType === 'illustratedMessage') {\n
    \n
    \n

    No Results

    \n

    Start by proiding your search criteria.

    \n
    \n
    \n }\n
    \n" }, + { + "name": "shellbar-responsive-example", + "description": "Shellbar Responsive", + "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", + "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, { "name": "shellbar-branding-context-area-example", "description": "Shellbar Branding Context Area", "typescript": "import { Component, ElementRef, signal, ViewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ClickedDirective } from '@fundamental-ngx/cdk';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport {\n ShellbarComponent,\n ShellbarMenuItem,\n ShellbarModule,\n ShellbarUser,\n ShellbarUserMenu\n} from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\n@Component({\n selector: 'fd-shellbar-branding-context-area-example',\n templateUrl: './shellbar-branding-context-area-example.component.html',\n imports: [\n ShellbarModule,\n MenuModule,\n AvatarComponent,\n ClickedDirective,\n ButtonComponent,\n FormsModule,\n ProductSwitchModule,\n SearchFieldComponent,\n ObjectStatusComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n PopoverModule,\n ListModule,\n PanelModule,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarBrandingContextAreaExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n @ViewChild(ShellbarComponent, { read: ElementRef })\n shellbar: ElementRef;\n\n expanded = true;\n\n isOpen = false;\n\n searchTerm = '';\n\n inputText = '';\n\n showButtonWithPriority3 = true;\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n productMenuItems: ShellbarMenuItem[] = [\n {\n name: 'Application A',\n callback: () => {\n alert('Application A Clicked');\n }\n },\n {\n name: 'Application B',\n callback: () => {\n alert('Application B Clicked');\n }\n },\n {\n name: 'Application C',\n callback: () => {\n alert('Application C Clicked');\n }\n },\n {\n name: 'Application D',\n callback: () => {\n alert('Application D Clicked');\n }\n }\n ];\n\n accountToggledState = signal(true);\n filterToggledState = signal(false);\n cartToggledState = signal(false);\n\n actions = [\n {\n glyph: 'account',\n callback: () => this.actionAccountCallback(),\n label: 'Account',\n ariaLabel: 'Account Action',\n title: 'Account',\n type: 'transparent' as ButtonType,\n toggled: this.accountToggledState\n },\n {\n glyph: 'filter',\n callback: () => this.actionFilterCallback(),\n label: 'Filter',\n ariaLabel: 'Filter Action',\n title: 'Filter',\n type: 'attention' as ButtonType,\n toggled: this.filterToggledState\n },\n {\n glyph: 'cart',\n callback: () => this.actionCartCallback(),\n label: 'Cart',\n ariaLabel: 'Cart Action',\n type: 'positive' as ButtonType,\n title: 'Cart',\n toggled: this.cartToggledState\n },\n {\n glyph: 'bell',\n callback: (event: MouseEvent) => this.actionNotificationCallback(event),\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home'),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n user: ShellbarUser = {\n fullName: 'William Willson',\n colorAccent: 6\n };\n\n userMenu: ShellbarUserMenu[] = [\n { text: 'Settings', callback: this.settingsCallback },\n { text: 'Sign Out', callback: this.signOutCallback }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n brandingClicked($event: Event): void {\n console.log($event);\n alert('Branding clicked');\n }\n\n settingsCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Settings Clicked');\n }\n\n signOutCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionAccountCallback(): void {\n this.accountToggledState.set(!this.accountToggledState());\n }\n\n actionFilterCallback(): void {\n this.filterToggledState.set(!this.filterToggledState());\n }\n\n actionCartCallback(): void {\n this.cartToggledState.set(!this.cartToggledState());\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n assistiveToolsCallback(): void {\n alert('Assistive Tools Clicked');\n }\n\n navClicked(event): void {\n console.log(event);\n alert('Navigation Button Clicked');\n }\n\n backClicked(event): void {\n console.log(event);\n alert('Back Button Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n toggleButton3(): void {\n this.showButtonWithPriority3 = !this.showButtonWithPriority3;\n }\n\n itemVisibilityChanged(event: any): void {\n console.log(event);\n }\n}\n", "html": "\n \n \n \n \n Product Identifier\n \n\n \n \n \n \n \n \n @if (showButtonWithPriority3) {\n \n }\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n\n\n
    \n\n\n" }, - { - "name": "shellbar-context-area-overflow-example", - "description": "Shellbar Context Area Overflow", - "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", - "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" - }, { "name": "shellbar-growing-group-example", "description": "Shellbar Growing Group", @@ -45766,10 +45832,10 @@ "html": "

    This example shows Shellbar groups taking only space needed for the content inside.

    \n\n \n \n \n \n Product Identifier\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n" }, { - "name": "shellbar-responsive-example", - "description": "Shellbar Responsive", - "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", - "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + "name": "shellbar-context-area-overflow-example", + "description": "Shellbar Context Area Overflow", + "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", + "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" } ] }, @@ -45806,18 +45872,18 @@ "typescript": "import { Component, inject, OnInit, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { IllustratedMessageModule, SvgConfig } from '@fundamental-ngx/core/illustrated-message';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { SegmentedButtonComponent } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\nimport { DataProvider, SearchFieldDataSource } from '@fundamental-ngx/platform/shared';\nimport { Observable, of } from 'rxjs';\n\n@Component({\n selector: 'fd-shellbar-complex-search-results-example',\n templateUrl: './shellbar-complex-search-results-example.component.html',\n imports: [\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarModule,\n BarRightDirective,\n MessageToastModule,\n SearchFieldComponent,\n ShellbarActionComponent,\n FormsModule,\n SegmentedButtonComponent,\n CheckboxComponent,\n IllustratedMessageModule\n ]\n})\nexport class ShellbarComplexSearchResultsExampleComponent implements OnInit {\n shellSearchField = viewChild('shellSearchField');\n\n dataSource: SearchFieldDataSource;\n\n expanded = true;\n\n exampleType: 'default' | 'advancedFilter' | 'mobile' = 'default';\n\n emptyResultsType: 'illustratedMessage' | 'customSuggestions' = 'illustratedMessage';\n\n emptyDefaultSuggestions: SuggestionItem[] = [\n {\n value: 'Peach',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Pear',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Plum',\n data: {\n type: 'fruit'\n }\n }\n ];\n\n categories: ValueLabelItem[] = [\n {\n value: 'fruit',\n label: 'Fruits'\n },\n {\n value: 'vegetable',\n label: 'Vegetables'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n label: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n label: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n smallConfig: SvgConfig = {\n small: { url: 'assets/images/sapIllus-Ice-Cream-Demo-Small.svg', id: 'sapIllus-Ice-Cream-Demo-Small' }\n };\n\n showCategories = true;\n\n suggestionsLoading = false;\n\n private _messageToastService = inject(MessageToastService);\n\n ngOnInit(): void {\n this.dataSource = new SearchFieldDataSource(new ShellSearchFieldDataProvider());\n SUGGESTIONS[0].children?.forEach((child) => {\n this.emptyDefaultSuggestions.push(child);\n });\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n showAllSearchResultsClicked(): void {\n this.suggestionsLoading = true;\n setTimeout(() => {\n this.suggestionsLoading = false;\n this.shellSearchField()?.resetCategory();\n this.shellSearchField()?.clearTextInput();\n }, 500);\n }\n\n submit(event: SearchInput): void {\n alert('Search submitted. See developer console for event');\n console.log(event);\n }\n}\n\nexport class ShellSearchFieldDataProvider extends DataProvider {\n constructor() {\n super();\n }\n\n fetch(params: Map): Observable {\n const data = SUGGESTIONS;\n const name = params.get('keyword');\n const category = params.get('category');\n if ((!name || name.trim() === '') && !category) {\n return of(data);\n } else {\n const filteredData = data.filter((suggestion) => {\n let foundMatchingChild = false;\n if (suggestion.children) {\n for (let i = 0; i < suggestion.children.length && !foundMatchingChild; i++) {\n foundMatchingChild = this._checkForMatches(suggestion.children[i], name, category);\n }\n } else {\n foundMatchingChild = this._checkForMatches(suggestion, name, category);\n }\n return foundMatchingChild;\n });\n return of(filteredData);\n }\n }\n\n private _checkForMatches(item: any, name: string | undefined, category: string | undefined): boolean {\n let foundMatchingItem = false;\n if (name && category) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1 && item.data?.type === category) {\n foundMatchingItem = true;\n }\n } else if (name) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1) {\n foundMatchingItem = true;\n }\n } else if (category) {\n if (item.data?.type === category) {\n foundMatchingItem = true;\n }\n }\n return foundMatchingItem;\n }\n}\n\nconst SUGGESTIONS: SuggestionItem[] = [\n {\n value: 'Fruits',\n isGroupHeader: true,\n children: [\n {\n value: 'Apple',\n data: {\n type: 'fruit',\n listIconGlyph: 'globe'\n }\n },\n {\n value: 'Banana',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Blueberry',\n data: {\n type: 'fruit',\n prefix: 'Prefix text:',\n actionButtons: [\n {\n actionButtonGlyph: 'refresh',\n actionButtonCallback: () => {\n alert('Blueberry refresh button clicked');\n },\n actionButtonId: 'refresh-button-1',\n actionButtonLabel: 'Refresh Item'\n },\n {\n actionButtonGlyph: 'settings',\n actionButtonCallback: () => {\n alert('Blueberry settings button clicked');\n },\n actionButtonLabel: 'Settings'\n }\n ],\n showDeleteButton: true,\n deleteCallback: () => {\n alert('Blueberry delete button clicked');\n }\n }\n },\n {\n value: 'Cherry',\n data: {\n type: 'fruit'\n }\n }\n ],\n searchInScopeText: 'Search in [Fruits]',\n searchInScopeCounter: 1234,\n searchInScopeCallback: () => {\n alert('Search in scope callback clicked');\n }\n },\n {\n value: 'Vegetables',\n isGroupHeader: true,\n children: [\n {\n value: 'Broccoli',\n data: {\n type: 'vegetable',\n subline: 'Flower vegetable',\n avatarLabel: 'John Doe'\n }\n },\n {\n value: 'Carrot',\n data: {\n type: 'vegetable',\n subline: 'Root vegetable',\n listIconGlyph: 'cart'\n }\n },\n {\n value: 'Corn',\n data: {\n type: 'vegetable'\n }\n },\n {\n value: 'Radish',\n data: {\n type: 'vegetable'\n }\n }\n ],\n showMoreText: 'Show More',\n showMoreCounter: 1234,\n showMoreCallback: () => {\n alert('Show more callback clicked');\n }\n }\n];\n", "html": "Shell search field example type:\n
    \n\n \n \n \n\n
    \nEmpty search results example type:\n
    \n\n \n \n\n
    \n\n\n
    \n \n \n \n \n \n Product Identifier\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n
    \n\n\n
    \n \n
    \n
    \n\n\n @if (emptyResultsType === 'illustratedMessage') {\n
    \n
    \n

    No Results

    \n

    Start by proiding your search criteria.

    \n
    \n
    \n }\n
    \n" }, + { + "name": "shellbar-responsive-example", + "description": "Shellbar Responsive", + "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", + "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, { "name": "shellbar-branding-context-area-example", "description": "Shellbar Branding Context Area", "typescript": "import { Component, ElementRef, signal, ViewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ClickedDirective } from '@fundamental-ngx/cdk';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport {\n ShellbarComponent,\n ShellbarMenuItem,\n ShellbarModule,\n ShellbarUser,\n ShellbarUserMenu\n} from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\n@Component({\n selector: 'fd-shellbar-branding-context-area-example',\n templateUrl: './shellbar-branding-context-area-example.component.html',\n imports: [\n ShellbarModule,\n MenuModule,\n AvatarComponent,\n ClickedDirective,\n ButtonComponent,\n FormsModule,\n ProductSwitchModule,\n SearchFieldComponent,\n ObjectStatusComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n PopoverModule,\n ListModule,\n PanelModule,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarBrandingContextAreaExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n @ViewChild(ShellbarComponent, { read: ElementRef })\n shellbar: ElementRef;\n\n expanded = true;\n\n isOpen = false;\n\n searchTerm = '';\n\n inputText = '';\n\n showButtonWithPriority3 = true;\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n productMenuItems: ShellbarMenuItem[] = [\n {\n name: 'Application A',\n callback: () => {\n alert('Application A Clicked');\n }\n },\n {\n name: 'Application B',\n callback: () => {\n alert('Application B Clicked');\n }\n },\n {\n name: 'Application C',\n callback: () => {\n alert('Application C Clicked');\n }\n },\n {\n name: 'Application D',\n callback: () => {\n alert('Application D Clicked');\n }\n }\n ];\n\n accountToggledState = signal(true);\n filterToggledState = signal(false);\n cartToggledState = signal(false);\n\n actions = [\n {\n glyph: 'account',\n callback: () => this.actionAccountCallback(),\n label: 'Account',\n ariaLabel: 'Account Action',\n title: 'Account',\n type: 'transparent' as ButtonType,\n toggled: this.accountToggledState\n },\n {\n glyph: 'filter',\n callback: () => this.actionFilterCallback(),\n label: 'Filter',\n ariaLabel: 'Filter Action',\n title: 'Filter',\n type: 'attention' as ButtonType,\n toggled: this.filterToggledState\n },\n {\n glyph: 'cart',\n callback: () => this.actionCartCallback(),\n label: 'Cart',\n ariaLabel: 'Cart Action',\n type: 'positive' as ButtonType,\n title: 'Cart',\n toggled: this.cartToggledState\n },\n {\n glyph: 'bell',\n callback: (event: MouseEvent) => this.actionNotificationCallback(event),\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home'),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n user: ShellbarUser = {\n fullName: 'William Willson',\n colorAccent: 6\n };\n\n userMenu: ShellbarUserMenu[] = [\n { text: 'Settings', callback: this.settingsCallback },\n { text: 'Sign Out', callback: this.signOutCallback }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n brandingClicked($event: Event): void {\n console.log($event);\n alert('Branding clicked');\n }\n\n settingsCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Settings Clicked');\n }\n\n signOutCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionAccountCallback(): void {\n this.accountToggledState.set(!this.accountToggledState());\n }\n\n actionFilterCallback(): void {\n this.filterToggledState.set(!this.filterToggledState());\n }\n\n actionCartCallback(): void {\n this.cartToggledState.set(!this.cartToggledState());\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n assistiveToolsCallback(): void {\n alert('Assistive Tools Clicked');\n }\n\n navClicked(event): void {\n console.log(event);\n alert('Navigation Button Clicked');\n }\n\n backClicked(event): void {\n console.log(event);\n alert('Back Button Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n toggleButton3(): void {\n this.showButtonWithPriority3 = !this.showButtonWithPriority3;\n }\n\n itemVisibilityChanged(event: any): void {\n console.log(event);\n }\n}\n", "html": "\n \n \n \n \n Product Identifier\n \n\n \n \n \n \n \n \n @if (showButtonWithPriority3) {\n \n }\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n\n\n
    \n\n\n" }, - { - "name": "shellbar-context-area-overflow-example", - "description": "Shellbar Context Area Overflow", - "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", - "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" - }, { "name": "shellbar-growing-group-example", "description": "Shellbar Growing Group", @@ -45825,10 +45891,10 @@ "html": "

    This example shows Shellbar groups taking only space needed for the content inside.

    \n\n \n \n \n \n Product Identifier\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n" }, { - "name": "shellbar-responsive-example", - "description": "Shellbar Responsive", - "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", - "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + "name": "shellbar-context-area-overflow-example", + "description": "Shellbar Context Area Overflow", + "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", + "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" } ] }, @@ -45864,18 +45930,18 @@ "typescript": "import { Component, inject, OnInit, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { IllustratedMessageModule, SvgConfig } from '@fundamental-ngx/core/illustrated-message';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { SegmentedButtonComponent } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\nimport { DataProvider, SearchFieldDataSource } from '@fundamental-ngx/platform/shared';\nimport { Observable, of } from 'rxjs';\n\n@Component({\n selector: 'fd-shellbar-complex-search-results-example',\n templateUrl: './shellbar-complex-search-results-example.component.html',\n imports: [\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarModule,\n BarRightDirective,\n MessageToastModule,\n SearchFieldComponent,\n ShellbarActionComponent,\n FormsModule,\n SegmentedButtonComponent,\n CheckboxComponent,\n IllustratedMessageModule\n ]\n})\nexport class ShellbarComplexSearchResultsExampleComponent implements OnInit {\n shellSearchField = viewChild('shellSearchField');\n\n dataSource: SearchFieldDataSource;\n\n expanded = true;\n\n exampleType: 'default' | 'advancedFilter' | 'mobile' = 'default';\n\n emptyResultsType: 'illustratedMessage' | 'customSuggestions' = 'illustratedMessage';\n\n emptyDefaultSuggestions: SuggestionItem[] = [\n {\n value: 'Peach',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Pear',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Plum',\n data: {\n type: 'fruit'\n }\n }\n ];\n\n categories: ValueLabelItem[] = [\n {\n value: 'fruit',\n label: 'Fruits'\n },\n {\n value: 'vegetable',\n label: 'Vegetables'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n label: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n label: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n smallConfig: SvgConfig = {\n small: { url: 'assets/images/sapIllus-Ice-Cream-Demo-Small.svg', id: 'sapIllus-Ice-Cream-Demo-Small' }\n };\n\n showCategories = true;\n\n suggestionsLoading = false;\n\n private _messageToastService = inject(MessageToastService);\n\n ngOnInit(): void {\n this.dataSource = new SearchFieldDataSource(new ShellSearchFieldDataProvider());\n SUGGESTIONS[0].children?.forEach((child) => {\n this.emptyDefaultSuggestions.push(child);\n });\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n showAllSearchResultsClicked(): void {\n this.suggestionsLoading = true;\n setTimeout(() => {\n this.suggestionsLoading = false;\n this.shellSearchField()?.resetCategory();\n this.shellSearchField()?.clearTextInput();\n }, 500);\n }\n\n submit(event: SearchInput): void {\n alert('Search submitted. See developer console for event');\n console.log(event);\n }\n}\n\nexport class ShellSearchFieldDataProvider extends DataProvider {\n constructor() {\n super();\n }\n\n fetch(params: Map): Observable {\n const data = SUGGESTIONS;\n const name = params.get('keyword');\n const category = params.get('category');\n if ((!name || name.trim() === '') && !category) {\n return of(data);\n } else {\n const filteredData = data.filter((suggestion) => {\n let foundMatchingChild = false;\n if (suggestion.children) {\n for (let i = 0; i < suggestion.children.length && !foundMatchingChild; i++) {\n foundMatchingChild = this._checkForMatches(suggestion.children[i], name, category);\n }\n } else {\n foundMatchingChild = this._checkForMatches(suggestion, name, category);\n }\n return foundMatchingChild;\n });\n return of(filteredData);\n }\n }\n\n private _checkForMatches(item: any, name: string | undefined, category: string | undefined): boolean {\n let foundMatchingItem = false;\n if (name && category) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1 && item.data?.type === category) {\n foundMatchingItem = true;\n }\n } else if (name) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1) {\n foundMatchingItem = true;\n }\n } else if (category) {\n if (item.data?.type === category) {\n foundMatchingItem = true;\n }\n }\n return foundMatchingItem;\n }\n}\n\nconst SUGGESTIONS: SuggestionItem[] = [\n {\n value: 'Fruits',\n isGroupHeader: true,\n children: [\n {\n value: 'Apple',\n data: {\n type: 'fruit',\n listIconGlyph: 'globe'\n }\n },\n {\n value: 'Banana',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Blueberry',\n data: {\n type: 'fruit',\n prefix: 'Prefix text:',\n actionButtons: [\n {\n actionButtonGlyph: 'refresh',\n actionButtonCallback: () => {\n alert('Blueberry refresh button clicked');\n },\n actionButtonId: 'refresh-button-1',\n actionButtonLabel: 'Refresh Item'\n },\n {\n actionButtonGlyph: 'settings',\n actionButtonCallback: () => {\n alert('Blueberry settings button clicked');\n },\n actionButtonLabel: 'Settings'\n }\n ],\n showDeleteButton: true,\n deleteCallback: () => {\n alert('Blueberry delete button clicked');\n }\n }\n },\n {\n value: 'Cherry',\n data: {\n type: 'fruit'\n }\n }\n ],\n searchInScopeText: 'Search in [Fruits]',\n searchInScopeCounter: 1234,\n searchInScopeCallback: () => {\n alert('Search in scope callback clicked');\n }\n },\n {\n value: 'Vegetables',\n isGroupHeader: true,\n children: [\n {\n value: 'Broccoli',\n data: {\n type: 'vegetable',\n subline: 'Flower vegetable',\n avatarLabel: 'John Doe'\n }\n },\n {\n value: 'Carrot',\n data: {\n type: 'vegetable',\n subline: 'Root vegetable',\n listIconGlyph: 'cart'\n }\n },\n {\n value: 'Corn',\n data: {\n type: 'vegetable'\n }\n },\n {\n value: 'Radish',\n data: {\n type: 'vegetable'\n }\n }\n ],\n showMoreText: 'Show More',\n showMoreCounter: 1234,\n showMoreCallback: () => {\n alert('Show more callback clicked');\n }\n }\n];\n", "html": "Shell search field example type:\n
    \n\n \n \n \n\n
    \nEmpty search results example type:\n
    \n\n \n \n\n
    \n\n\n
    \n \n \n \n \n \n Product Identifier\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n
    \n\n\n
    \n \n
    \n
    \n\n\n @if (emptyResultsType === 'illustratedMessage') {\n
    \n
    \n

    No Results

    \n

    Start by proiding your search criteria.

    \n
    \n
    \n }\n
    \n" }, + { + "name": "shellbar-responsive-example", + "description": "Shellbar Responsive", + "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", + "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, { "name": "shellbar-branding-context-area-example", "description": "Shellbar Branding Context Area", "typescript": "import { Component, ElementRef, signal, ViewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ClickedDirective } from '@fundamental-ngx/cdk';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport {\n ShellbarComponent,\n ShellbarMenuItem,\n ShellbarModule,\n ShellbarUser,\n ShellbarUserMenu\n} from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\n@Component({\n selector: 'fd-shellbar-branding-context-area-example',\n templateUrl: './shellbar-branding-context-area-example.component.html',\n imports: [\n ShellbarModule,\n MenuModule,\n AvatarComponent,\n ClickedDirective,\n ButtonComponent,\n FormsModule,\n ProductSwitchModule,\n SearchFieldComponent,\n ObjectStatusComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n PopoverModule,\n ListModule,\n PanelModule,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarBrandingContextAreaExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n @ViewChild(ShellbarComponent, { read: ElementRef })\n shellbar: ElementRef;\n\n expanded = true;\n\n isOpen = false;\n\n searchTerm = '';\n\n inputText = '';\n\n showButtonWithPriority3 = true;\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n productMenuItems: ShellbarMenuItem[] = [\n {\n name: 'Application A',\n callback: () => {\n alert('Application A Clicked');\n }\n },\n {\n name: 'Application B',\n callback: () => {\n alert('Application B Clicked');\n }\n },\n {\n name: 'Application C',\n callback: () => {\n alert('Application C Clicked');\n }\n },\n {\n name: 'Application D',\n callback: () => {\n alert('Application D Clicked');\n }\n }\n ];\n\n accountToggledState = signal(true);\n filterToggledState = signal(false);\n cartToggledState = signal(false);\n\n actions = [\n {\n glyph: 'account',\n callback: () => this.actionAccountCallback(),\n label: 'Account',\n ariaLabel: 'Account Action',\n title: 'Account',\n type: 'transparent' as ButtonType,\n toggled: this.accountToggledState\n },\n {\n glyph: 'filter',\n callback: () => this.actionFilterCallback(),\n label: 'Filter',\n ariaLabel: 'Filter Action',\n title: 'Filter',\n type: 'attention' as ButtonType,\n toggled: this.filterToggledState\n },\n {\n glyph: 'cart',\n callback: () => this.actionCartCallback(),\n label: 'Cart',\n ariaLabel: 'Cart Action',\n type: 'positive' as ButtonType,\n title: 'Cart',\n toggled: this.cartToggledState\n },\n {\n glyph: 'bell',\n callback: (event: MouseEvent) => this.actionNotificationCallback(event),\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home'),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n user: ShellbarUser = {\n fullName: 'William Willson',\n colorAccent: 6\n };\n\n userMenu: ShellbarUserMenu[] = [\n { text: 'Settings', callback: this.settingsCallback },\n { text: 'Sign Out', callback: this.signOutCallback }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n brandingClicked($event: Event): void {\n console.log($event);\n alert('Branding clicked');\n }\n\n settingsCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Settings Clicked');\n }\n\n signOutCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionAccountCallback(): void {\n this.accountToggledState.set(!this.accountToggledState());\n }\n\n actionFilterCallback(): void {\n this.filterToggledState.set(!this.filterToggledState());\n }\n\n actionCartCallback(): void {\n this.cartToggledState.set(!this.cartToggledState());\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n assistiveToolsCallback(): void {\n alert('Assistive Tools Clicked');\n }\n\n navClicked(event): void {\n console.log(event);\n alert('Navigation Button Clicked');\n }\n\n backClicked(event): void {\n console.log(event);\n alert('Back Button Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n toggleButton3(): void {\n this.showButtonWithPriority3 = !this.showButtonWithPriority3;\n }\n\n itemVisibilityChanged(event: any): void {\n console.log(event);\n }\n}\n", "html": "\n \n \n \n \n Product Identifier\n \n\n \n \n \n \n \n \n @if (showButtonWithPriority3) {\n \n }\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n\n\n
    \n\n\n" }, - { - "name": "shellbar-context-area-overflow-example", - "description": "Shellbar Context Area Overflow", - "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", - "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" - }, { "name": "shellbar-growing-group-example", "description": "Shellbar Growing Group", @@ -45883,10 +45949,10 @@ "html": "

    This example shows Shellbar groups taking only space needed for the content inside.

    \n\n \n \n \n \n Product Identifier\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n" }, { - "name": "shellbar-responsive-example", - "description": "Shellbar Responsive", - "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", - "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + "name": "shellbar-context-area-overflow-example", + "description": "Shellbar Context Area Overflow", + "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", + "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" } ] }, @@ -45988,18 +46054,18 @@ "typescript": "import { Component, inject, OnInit, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarModule, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { IllustratedMessageModule, SvgConfig } from '@fundamental-ngx/core/illustrated-message';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { SegmentedButtonComponent } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\nimport { DataProvider, SearchFieldDataSource } from '@fundamental-ngx/platform/shared';\nimport { Observable, of } from 'rxjs';\n\n@Component({\n selector: 'fd-shellbar-complex-search-results-example',\n templateUrl: './shellbar-complex-search-results-example.component.html',\n imports: [\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarTitleComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarModule,\n BarRightDirective,\n MessageToastModule,\n SearchFieldComponent,\n ShellbarActionComponent,\n FormsModule,\n SegmentedButtonComponent,\n CheckboxComponent,\n IllustratedMessageModule\n ]\n})\nexport class ShellbarComplexSearchResultsExampleComponent implements OnInit {\n shellSearchField = viewChild('shellSearchField');\n\n dataSource: SearchFieldDataSource;\n\n expanded = true;\n\n exampleType: 'default' | 'advancedFilter' | 'mobile' = 'default';\n\n emptyResultsType: 'illustratedMessage' | 'customSuggestions' = 'illustratedMessage';\n\n emptyDefaultSuggestions: SuggestionItem[] = [\n {\n value: 'Peach',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Pear',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Plum',\n data: {\n type: 'fruit'\n }\n }\n ];\n\n categories: ValueLabelItem[] = [\n {\n value: 'fruit',\n label: 'Fruits'\n },\n {\n value: 'vegetable',\n label: 'Vegetables'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n label: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n label: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n smallConfig: SvgConfig = {\n small: { url: 'assets/images/sapIllus-Ice-Cream-Demo-Small.svg', id: 'sapIllus-Ice-Cream-Demo-Small' }\n };\n\n showCategories = true;\n\n suggestionsLoading = false;\n\n private _messageToastService = inject(MessageToastService);\n\n ngOnInit(): void {\n this.dataSource = new SearchFieldDataSource(new ShellSearchFieldDataProvider());\n SUGGESTIONS[0].children?.forEach((child) => {\n this.emptyDefaultSuggestions.push(child);\n });\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n showAllSearchResultsClicked(): void {\n this.suggestionsLoading = true;\n setTimeout(() => {\n this.suggestionsLoading = false;\n this.shellSearchField()?.resetCategory();\n this.shellSearchField()?.clearTextInput();\n }, 500);\n }\n\n submit(event: SearchInput): void {\n alert('Search submitted. See developer console for event');\n console.log(event);\n }\n}\n\nexport class ShellSearchFieldDataProvider extends DataProvider {\n constructor() {\n super();\n }\n\n fetch(params: Map): Observable {\n const data = SUGGESTIONS;\n const name = params.get('keyword');\n const category = params.get('category');\n if ((!name || name.trim() === '') && !category) {\n return of(data);\n } else {\n const filteredData = data.filter((suggestion) => {\n let foundMatchingChild = false;\n if (suggestion.children) {\n for (let i = 0; i < suggestion.children.length && !foundMatchingChild; i++) {\n foundMatchingChild = this._checkForMatches(suggestion.children[i], name, category);\n }\n } else {\n foundMatchingChild = this._checkForMatches(suggestion, name, category);\n }\n return foundMatchingChild;\n });\n return of(filteredData);\n }\n }\n\n private _checkForMatches(item: any, name: string | undefined, category: string | undefined): boolean {\n let foundMatchingItem = false;\n if (name && category) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1 && item.data?.type === category) {\n foundMatchingItem = true;\n }\n } else if (name) {\n if (item.value.toLowerCase().indexOf(name.toLowerCase()) > -1) {\n foundMatchingItem = true;\n }\n } else if (category) {\n if (item.data?.type === category) {\n foundMatchingItem = true;\n }\n }\n return foundMatchingItem;\n }\n}\n\nconst SUGGESTIONS: SuggestionItem[] = [\n {\n value: 'Fruits',\n isGroupHeader: true,\n children: [\n {\n value: 'Apple',\n data: {\n type: 'fruit',\n listIconGlyph: 'globe'\n }\n },\n {\n value: 'Banana',\n data: {\n type: 'fruit'\n }\n },\n {\n value: 'Blueberry',\n data: {\n type: 'fruit',\n prefix: 'Prefix text:',\n actionButtons: [\n {\n actionButtonGlyph: 'refresh',\n actionButtonCallback: () => {\n alert('Blueberry refresh button clicked');\n },\n actionButtonId: 'refresh-button-1',\n actionButtonLabel: 'Refresh Item'\n },\n {\n actionButtonGlyph: 'settings',\n actionButtonCallback: () => {\n alert('Blueberry settings button clicked');\n },\n actionButtonLabel: 'Settings'\n }\n ],\n showDeleteButton: true,\n deleteCallback: () => {\n alert('Blueberry delete button clicked');\n }\n }\n },\n {\n value: 'Cherry',\n data: {\n type: 'fruit'\n }\n }\n ],\n searchInScopeText: 'Search in [Fruits]',\n searchInScopeCounter: 1234,\n searchInScopeCallback: () => {\n alert('Search in scope callback clicked');\n }\n },\n {\n value: 'Vegetables',\n isGroupHeader: true,\n children: [\n {\n value: 'Broccoli',\n data: {\n type: 'vegetable',\n subline: 'Flower vegetable',\n avatarLabel: 'John Doe'\n }\n },\n {\n value: 'Carrot',\n data: {\n type: 'vegetable',\n subline: 'Root vegetable',\n listIconGlyph: 'cart'\n }\n },\n {\n value: 'Corn',\n data: {\n type: 'vegetable'\n }\n },\n {\n value: 'Radish',\n data: {\n type: 'vegetable'\n }\n }\n ],\n showMoreText: 'Show More',\n showMoreCounter: 1234,\n showMoreCallback: () => {\n alert('Show more callback clicked');\n }\n }\n];\n", "html": "Shell search field example type:\n
    \n\n \n \n \n\n
    \nEmpty search results example type:\n
    \n\n \n \n\n
    \n\n\n
    \n \n \n \n \n \n Product Identifier\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n
    \n\n\n
    \n \n
    \n
    \n\n\n @if (emptyResultsType === 'illustratedMessage') {\n
    \n
    \n

    No Results

    \n

    Start by proiding your search criteria.

    \n
    \n
    \n }\n
    \n" }, + { + "name": "shellbar-responsive-example", + "description": "Shellbar Responsive", + "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", + "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, { "name": "shellbar-branding-context-area-example", "description": "Shellbar Branding Context Area", "typescript": "import { Component, ElementRef, signal, ViewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ClickedDirective } from '@fundamental-ngx/cdk';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport {\n ShellbarComponent,\n ShellbarMenuItem,\n ShellbarModule,\n ShellbarUser,\n ShellbarUserMenu\n} from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\nimport {\n SearchFieldComponent,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\n@Component({\n selector: 'fd-shellbar-branding-context-area-example',\n templateUrl: './shellbar-branding-context-area-example.component.html',\n imports: [\n ShellbarModule,\n MenuModule,\n AvatarComponent,\n ClickedDirective,\n ButtonComponent,\n FormsModule,\n ProductSwitchModule,\n SearchFieldComponent,\n ObjectStatusComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n PopoverModule,\n ListModule,\n PanelModule,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarBrandingContextAreaExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n @ViewChild(ShellbarComponent, { read: ElementRef })\n shellbar: ElementRef;\n\n expanded = true;\n\n isOpen = false;\n\n searchTerm = '';\n\n inputText = '';\n\n showButtonWithPriority3 = true;\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n productMenuItems: ShellbarMenuItem[] = [\n {\n name: 'Application A',\n callback: () => {\n alert('Application A Clicked');\n }\n },\n {\n name: 'Application B',\n callback: () => {\n alert('Application B Clicked');\n }\n },\n {\n name: 'Application C',\n callback: () => {\n alert('Application C Clicked');\n }\n },\n {\n name: 'Application D',\n callback: () => {\n alert('Application D Clicked');\n }\n }\n ];\n\n accountToggledState = signal(true);\n filterToggledState = signal(false);\n cartToggledState = signal(false);\n\n actions = [\n {\n glyph: 'account',\n callback: () => this.actionAccountCallback(),\n label: 'Account',\n ariaLabel: 'Account Action',\n title: 'Account',\n type: 'transparent' as ButtonType,\n toggled: this.accountToggledState\n },\n {\n glyph: 'filter',\n callback: () => this.actionFilterCallback(),\n label: 'Filter',\n ariaLabel: 'Filter Action',\n title: 'Filter',\n type: 'attention' as ButtonType,\n toggled: this.filterToggledState\n },\n {\n glyph: 'cart',\n callback: () => this.actionCartCallback(),\n label: 'Cart',\n ariaLabel: 'Cart Action',\n type: 'positive' as ButtonType,\n title: 'Cart',\n toggled: this.cartToggledState\n },\n {\n glyph: 'bell',\n callback: (event: MouseEvent) => this.actionNotificationCallback(event),\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home'),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n user: ShellbarUser = {\n fullName: 'William Willson',\n colorAccent: 6\n };\n\n userMenu: ShellbarUserMenu[] = [\n { text: 'Settings', callback: this.settingsCallback },\n { text: 'Sign Out', callback: this.signOutCallback }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n brandingClicked($event: Event): void {\n console.log($event);\n alert('Branding clicked');\n }\n\n settingsCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Settings Clicked');\n }\n\n signOutCallback($event: MouseEvent): void {\n console.log({ $event });\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionAccountCallback(): void {\n this.accountToggledState.set(!this.accountToggledState());\n }\n\n actionFilterCallback(): void {\n this.filterToggledState.set(!this.filterToggledState());\n }\n\n actionCartCallback(): void {\n this.cartToggledState.set(!this.cartToggledState());\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n assistiveToolsCallback(): void {\n alert('Assistive Tools Clicked');\n }\n\n navClicked(event): void {\n console.log(event);\n alert('Navigation Button Clicked');\n }\n\n backClicked(event): void {\n console.log(event);\n alert('Back Button Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n\n toggleButton3(): void {\n this.showButtonWithPriority3 = !this.showButtonWithPriority3;\n }\n\n itemVisibilityChanged(event: any): void {\n console.log(event);\n }\n}\n", "html": "\n \n \n \n \n Product Identifier\n \n\n \n \n \n \n \n \n @if (showButtonWithPriority3) {\n \n }\n \n\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n\n\n
    \n\n\n" }, - { - "name": "shellbar-context-area-overflow-example", - "description": "Shellbar Context Area Overflow", - "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", - "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" - }, { "name": "shellbar-growing-group-example", "description": "Shellbar Growing Group", @@ -46007,10 +46073,10 @@ "html": "

    This example shows Shellbar groups taking only space needed for the content inside.

    \n\n \n \n \n \n Product Identifier\n \n\n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n" }, { - "name": "shellbar-responsive-example", - "description": "Shellbar Responsive", - "typescript": "import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { ProductSwitchItem, ProductSwitchModule } from '@fundamental-ngx/core/product-switch';\nimport { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';\nimport {\n ShellbarActionComponent,\n ShellbarActionsComponent,\n ShellbarBrandingComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarSizes,\n ShellbarTitleComponent\n} from '@fundamental-ngx/core/shellbar';\nimport {\n PlatformSearchFieldModule,\n SearchInput,\n SuggestionItem,\n ValueLabelItem\n} from '@fundamental-ngx/platform/search-field';\n\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { BarComponent, BarRightDirective } from '@fundamental-ngx/core/bar';\nimport { ListModule } from '@fundamental-ngx/core/list';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { MessageToastModule, MessageToastService } from '@fundamental-ngx/core/message-toast';\nimport { PanelModule } from '@fundamental-ngx/core/panel';\nimport { PopoverModule } from '@fundamental-ngx/core/popover';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuContentContainerComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuFooterComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuListComponent,\n UserMenuListItemComponent,\n UserMenuSublineDirective,\n UserMenuSublistComponent,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-responsive-example',\n templateUrl: './shellbar-responsive-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n SegmentedButtonModule,\n FormsModule,\n ButtonComponent,\n ShellbarComponent,\n ShellbarLogoComponent,\n ShellbarBrandingComponent,\n ShellbarTitleComponent,\n PlatformSearchFieldModule,\n ContentDensityDirective,\n ShellbarActionsComponent,\n ShellbarActionComponent,\n ProductSwitchModule,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuFooterComponent,\n UserMenuContentContainerComponent,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective,\n UserMenuListComponent,\n UserMenuSublistComponent,\n UserMenuListItemComponent,\n UserMenuControlElementDirective,\n AvatarComponent,\n PopoverModule,\n ListModule,\n PanelModule,\n MenuModule,\n ButtonComponent,\n BarComponent,\n BarRightDirective,\n MessageToastModule\n ]\n})\nexport class ShellbarResponsiveExampleComponent {\n @ViewChild(UserMenuComponent)\n userMenuComponent: UserMenuComponent;\n\n expanded = true;\n isOpen = false;\n\n currentSize: ShellbarSizes = 'm';\n\n sizesWidth = {\n s: 320,\n m: 600,\n l: 1024,\n xl: 1900\n };\n\n searchTerm = '';\n\n inputText = '';\n\n productMenuControl = 'Corporate Portal';\n\n categories: ValueLabelItem[] = [\n {\n value: 'red',\n label: 'Red'\n },\n {\n value: 'orange',\n label: 'Orange'\n },\n {\n value: 'yellow',\n label: 'Yellow'\n },\n {\n value: 'green',\n label: 'Green'\n },\n {\n value: 'blue',\n label: 'Blue'\n },\n {\n value: 'indigo',\n label: 'Indigo'\n },\n {\n value: 'violet',\n label: 'Violet'\n }\n ];\n\n suggestions: SuggestionItem[] = [\n {\n value: 'Apple'\n },\n {\n value: 'Banana'\n },\n {\n value: 'Blueberry'\n },\n {\n value: 'Cherry'\n },\n {\n value: 'Grape'\n },\n {\n value: 'Lemon'\n },\n {\n value: 'Lime'\n },\n {\n value: 'Orange'\n },\n {\n value: 'Peach'\n },\n {\n value: 'Pineapple'\n },\n {\n value: 'Plum'\n },\n {\n value: 'Raspberry'\n }\n ];\n\n actions = [\n {\n glyph: 'pool',\n callback: this.actionPoolCallback,\n label: 'Pool',\n ariaLabel: 'Pool Action',\n title: 'Pool',\n notificationCount: 3,\n notificationLabel: 'Pool Count'\n },\n {\n glyph: 'bell',\n callback: this.actionNotificationCallback,\n label: 'Notifications',\n ariaLabel: 'Notifications Action',\n title: 'Notifications',\n notificationCount: 12,\n notificationLabel: 'Unread Notifications'\n }\n ];\n\n searchTerms = ['Apple', 'Banana', 'Kiwi', 'Strawberry'];\n\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n callback: () => this.productSwitcherCallback('Home '),\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n\n constructor(private _messageToastService: MessageToastService) {}\n\n settingsCallback($event): void {\n console.log($event);\n alert('Settings Clicked');\n }\n\n signOutCallback($event): void {\n console.log($event);\n alert('Sign Out Clicked');\n }\n\n actionNotificationCallback($event): void {\n console.log($event);\n alert('Notification Action Clicked');\n }\n\n actionPoolCallback($event): void {\n console.log($event);\n alert('Pool Action Clicked');\n }\n\n productSwitcherCallback(product): void {\n alert(product + 'Product Clicked');\n }\n\n onSearchSubmit($event: SearchInput): void {\n this.searchTerm = $event.text;\n }\n\n onInputChange($event: SearchInput): void {\n this.inputText = $event.text;\n }\n\n isOpenChange(isOpen: boolean): void {\n this.isOpen = isOpen;\n }\n\n onZoomGlyphClick(): void {\n alert('Edit profile');\n }\n\n actionPicked(action: string): void {\n this.openMessageToast(action);\n this.userMenuComponent.close();\n }\n\n openMessageToast(action: string): void {\n const content = `${action} action performed`;\n this._messageToastService.open(content, {\n duration: 5000\n });\n }\n}\n", - "html": "\n \n \n \n \n\n
    \n \n \n \n \n \n Product Identifier\n \n \n \n @for (action of actions; track action) {\n \n }\n \n \n \n \n\n \n \n \n \n\n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    \n \n
    \n
    \n \n
    Other Accounts
    \n \n
    \n
      \n
    • \n \n
      \n
      Lisa Miller
      \n
      lisa.miller@test.com
      \n
      User Experience Designer
      \n
      \n
    • \n
    • \n \n
      \n
      John Doe
      \n
      john.doe@test.com
      \n
      Project Manager
      \n
      \n
    • \n
    • \n \n
      \n
      Jane Doe
      \n
      jane.doe@test.com
      \n
      Delivery Manager
      \n
      \n
    • \n
    \n
    \n \n\n \n \n \n \n \n\n \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + "name": "shellbar-context-area-overflow-example", + "description": "Shellbar Context Area Overflow", + "typescript": "import { ChangeDetectionStrategy, Component, ElementRef, effect, signal, viewChild } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { ButtonComponent, ButtonType } from '@fundamental-ngx/core/button';\nimport { InfoLabelComponent } from '@fundamental-ngx/core/info-label';\nimport { PopoverBodyComponent, PopoverComponent, PopoverControlComponent } from '@fundamental-ngx/core/popover';\nimport { ShellbarModule } from '@fundamental-ngx/core/shellbar';\nimport {\n UserMenuBodyComponent,\n UserMenuComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuSublineDirective,\n UserMenuUserNameDirective\n} from '@fundamental-ngx/core/user-menu';\n\n@Component({\n selector: 'fd-shellbar-context-area-overflow-example',\n templateUrl: './shellbar-context-area-overflow-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ShellbarModule,\n ButtonComponent,\n InfoLabelComponent,\n PopoverComponent,\n PopoverControlComponent,\n PopoverBodyComponent,\n AvatarComponent,\n UserMenuComponent,\n UserMenuBodyComponent,\n UserMenuControlComponent,\n UserMenuControlElementDirective,\n UserMenuHeaderContainerDirective,\n UserMenuHeaderDirective,\n UserMenuUserNameDirective,\n UserMenuSublineDirective\n ]\n})\nexport class ShellbarContextAreaOverflowExampleComponent {\n hiddenItems = signal([]);\n\n isOverflowOpen = signal(false);\n\n readonly overflowContainer = viewChild>('overflowContainer');\n\n actions = [\n {\n glyph: 'bell',\n callback: () => {},\n label: 'Notifications',\n ariaLabel: 'Notifications',\n title: 'Notifications',\n type: 'transparent' as ButtonType\n },\n {\n glyph: 'sys-help',\n callback: () => {},\n label: 'Help',\n ariaLabel: 'Help',\n title: 'Help',\n type: 'transparent' as ButtonType\n }\n ];\n\n constructor() {\n effect(() => {\n const container = this.overflowContainer()?.nativeElement;\n if (!container) {\n return;\n }\n container.innerHTML = '';\n this.hiddenItems().forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.style.display = '';\n container.appendChild(clone);\n });\n });\n }\n\n onVisibilityChange(items: HTMLElement[]): void {\n this.hiddenItems.set(items);\n if (items.length === 0) {\n this.isOverflowOpen.set(false);\n }\n }\n}\n", + "html": "
    \n \n \n \n \n \n Product Name\n \n\n \n \n \n 0 ? 'visible' : 'hidden'\"\n >\n \n \n \n
    \n \n \n \n\n \n @for (action of actions; track action) {\n \n }\n\n \n \n \n \n \n
    \n \n
    \n
    Lisa Miller
    \n
    lisa.miller@test.com
    \n
    User Experience Designer
    \n
    Primary Employment
    \n
    \n
    \n
    \n
    \n
    \n \n\n" } ] }, @@ -46244,17 +46310,17 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { SliderComponent } from '@fundamental-ngx/core/slider';\n\n@Component({\n selector: 'fd-slider-ticks-and-labels-example',\n templateUrl: './slider-ticks-and-labels-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [SliderComponent, FormsModule]\n})\nexport class SliderTicksAndLabelsExampleComponent {\n value = 25;\n value1 = 25;\n}\n", "html": "
    \n

    \n You can apply tick marks to the slider. The tick marks are related to the step property and are responsive. If\n the distance between 2 tick marks is less than 8 px, all tick marks except for the first and last disappear.\n
    \n To apply tick marks to the slider set [showTicks] as true\n

    \n \n

    Value: {{ value }}

    \n
    \n
    \n\n
    \n

    \n If tick marks are set, you can define labels for the tick marks. The labels are displayed below the tick marks\n and show the corresponding value of the tick mark. You can also define labels only for specific tick marks if\n you don’t need a label for every tick mark on the slider.\n
    \n To apply tick marks to the slider set [showTicks] as true and\n [showTicksLabels] as true\n

    \n \n \n

    Value: {{ value1 }}

    \n
    \n" }, - { - "name": "slider-tooltip-example", - "description": "Slider Tooltip", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { SliderComponent } from '@fundamental-ngx/core/slider';\n\n@Component({\n selector: 'fd-slider-tooltip-example',\n templateUrl: './slider-tooltip-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [SliderComponent, FormsModule]\n})\nexport class SliderTooltipExampleComponent {\n value = 50;\n value1 = 0;\n}\n", - "html": "
    \n

    \n The slider can be used tooltip with the text field. In this case, the value of the grip is displayed.\n
    \n To use it set [tooltipMode] as readonly\n

    \n \n

    Value: {{ value }}

    \n
    \n
    \n\n
    \n

    \n The slider can be used tooltip with the input field instead of the text field. This allows entering a specific\n value.\n
    \n To use it set [tooltipMode] as editable\n

    \n \n

    Value: {{ value1 }}

    \n
    \n" - }, { "name": "vertical-slider-example", "description": "Vertical Slider", "typescript": "import { JsonPipe, NgStyle } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { SliderComponent, SliderCustomValue } from '@fundamental-ngx/core/slider';\n\n@Component({\n selector: 'fd-vertical-slider-example',\n templateUrl: './vertical-slider-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [SliderComponent, FormsModule, JsonPipe, NgStyle]\n})\nexport class VerticalSliderExampleComponent {\n value = [20, 70];\n\n customValues: SliderCustomValue[] = [\n { value: 1609452000000, label: 'Jan 1' },\n { value: 1609538400000, label: 'Jan 2' },\n { value: 1609624800000, label: 'Jan 3' },\n { value: 1609711200000, label: 'Jan 4' },\n { value: 1609797600000, label: 'Jan 5' },\n { value: 1609884000000, label: 'Jan 6' },\n { value: 1609970400000, label: 'Jan 7' },\n { value: 1610056800000, label: 'Jan 8' },\n { value: 1610143200000, label: 'Jan 9' },\n { value: 1610229600000, label: 'Jan 10' }\n ];\n\n value2 = [this.customValues[4], this.customValues[6]];\n}\n", "html": "
    \n

    \n To use Range Slider need to set [mode] as range (by default [mode] as\n single)\n

    \n
    \n \n
    \n\n

    \n Min value: {{ value[0] }}\n
    \n Max value: {{ value[1] }}\n

    \n
    \n
    \n\n
    \n

    Range slided with Custom Values.

    \n
    \n \n \n
    \n\n

    \n Min value: {{ value2[0] | json }}\n
    \n Max value: {{ value2[1] | json }}\n

    \n
    \n" + }, + { + "name": "slider-tooltip-example", + "description": "Slider Tooltip", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { SliderComponent } from '@fundamental-ngx/core/slider';\n\n@Component({\n selector: 'fd-slider-tooltip-example',\n templateUrl: './slider-tooltip-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [SliderComponent, FormsModule]\n})\nexport class SliderTooltipExampleComponent {\n value = 50;\n value1 = 0;\n}\n", + "html": "
    \n

    \n The slider can be used tooltip with the text field. In this case, the value of the grip is displayed.\n
    \n To use it set [tooltipMode] as readonly\n

    \n \n

    Value: {{ value }}

    \n
    \n
    \n\n
    \n

    \n The slider can be used tooltip with the input field instead of the text field. This allows entering a specific\n value.\n
    \n To use it set [tooltipMode] as editable\n

    \n \n

    Value: {{ value1 }}

    \n
    \n" } ] }, @@ -46781,24 +46847,24 @@ "typescript": "import { Component } from '@angular/core';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\n\n@Component({\n selector: 'fd-step-input-currency-example',\n template: `\n
    \n
    \n \n \n Value: {{ value1 }}\n
    \n\n
    \n \n \n Value: {{ value2 }}\n
    \n\n
    \n \n \n Value: {{ value3 }}\n
    \n
    \n `,\n imports: [FormLabelComponent, StepInputModule]\n})\nexport class StepInputCurrencyExampleComponent {\n value1: number | null = 0;\n value2: number | null = 0;\n value3: number | null = 0;\n}\n" }, { - "name": "step-input-form-example", - "description": "Step Input Form", - "typescript": "import { Component } from '@angular/core';\nimport { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\n\n@Component({\n selector: 'fd-step-input-form-example',\n template: `\n
    \n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    Value:{{ stepInputFormControl1.value }}
    Dirty:{{ stepInputFormControl1.dirty }}
    Touched:{{ stepInputFormControl1.touched }}
    Status:{{ stepInputFormControl1.status }}
    \n
    \n\n
    \n
    \n\n
    \n \n \n Value: {{ value1 }}\n
    \n\n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    Value:{{ stepInputFormControl2.value }}
    Dirty:{{ stepInputFormControl2.dirty }}
    Touched:{{ stepInputFormControl2.touched }}
    Status:{{ stepInputFormControl2.status }}
    \n \n
    \n\n
    \n \n \n Value: {{ value2 }}\n
    \n
    \n `,\n imports: [FormLabelComponent, StepInputModule, FormsModule, ReactiveFormsModule, ButtonComponent]\n})\nexport class StepInputFormExampleComponent {\n stepInputFormControl1 = new FormControl(null);\n stepInputFormControl1a = new FormControl(5);\n stepInputFormControl2 = new FormControl({ disabled: true, value: 100 });\n value1: number | null = 100;\n value2: number | null = 100;\n\n toggleDisabledState(): void {\n this.stepInputFormControl2.enabled ? this.stepInputFormControl2.disable() : this.stepInputFormControl2.enable();\n }\n}\n" + "name": "step-input-locale-example", + "description": "Step Input Locale", + "typescript": "import { Component } from '@angular/core';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\n\n@Component({\n selector: 'fd-step-input-locale-example',\n template: `\n
    \n
    \n \n \n Value: {{ value1 }}\n
    \n\n
    \n \n \n Value: {{ value2 }}\n
    \n\n
    \n \n \n Value: {{ value3 }}\n
    \n
    \n `,\n imports: [FormLabelComponent, StepInputModule]\n})\nexport class StepInputLocaleExampleComponent {\n value1: number | null = 0;\n value2: number | null = 0;\n value3: number | null = 0;\n}\n" }, { "name": "step-input-label-example", "description": "Step Input Label", "typescript": "import { Component } from '@angular/core';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\n\n@Component({\n selector: 'fd-step-input-label-example',\n template: `\n
    \n
    \n \n \n Value: {{ value1 }}\n
    \n\n
    \n \n \n Value: {{ value2 }}\n
    \n\n
    \n \n \n Value: {{ value3 }}\n
    \n
    \n `,\n imports: [FormLabelComponent, StepInputModule]\n})\nexport class StepInputLabelExampleComponent {\n value1: number | null = 0;\n value2: number | null = 0;\n value3: number | null = 0;\n}\n" }, - { - "name": "step-input-locale-example", - "description": "Step Input Locale", - "typescript": "import { Component } from '@angular/core';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\n\n@Component({\n selector: 'fd-step-input-locale-example',\n template: `\n
    \n
    \n \n \n Value: {{ value1 }}\n
    \n\n
    \n \n \n Value: {{ value2 }}\n
    \n\n
    \n \n \n Value: {{ value3 }}\n
    \n
    \n `,\n imports: [FormLabelComponent, StepInputModule]\n})\nexport class StepInputLocaleExampleComponent {\n value1: number | null = 0;\n value2: number | null = 0;\n value3: number | null = 0;\n}\n" - }, { "name": "step-input-state-example", "description": "Step Input State", "typescript": "import { Component } from '@angular/core';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\n\n@Component({\n selector: 'fd-step-input-state-example',\n template: `\n
    \n
    \n \n \n Value: {{ value1 }}\n
    \n\n
    \n \n \n Value: {{ value2 }}\n
    \n\n
    \n \n \n Value: {{ value3 }}\n
    \n\n
    \n \n \n Value: {{ value4 }}\n
    \n
    \n `,\n imports: [FormLabelComponent, StepInputModule]\n})\nexport class StepInputStateExampleComponent {\n value1: number | null = 0;\n value2: number | null = 0;\n value3: number | null = 0;\n value4: number | null = 0;\n}\n" + }, + { + "name": "step-input-form-example", + "description": "Step Input Form", + "typescript": "import { Component } from '@angular/core';\nimport { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\n\n@Component({\n selector: 'fd-step-input-form-example',\n template: `\n
    \n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    Value:{{ stepInputFormControl1.value }}
    Dirty:{{ stepInputFormControl1.dirty }}
    Touched:{{ stepInputFormControl1.touched }}
    Status:{{ stepInputFormControl1.status }}
    \n
    \n\n
    \n
    \n\n
    \n \n \n Value: {{ value1 }}\n
    \n\n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    Value:{{ stepInputFormControl2.value }}
    Dirty:{{ stepInputFormControl2.dirty }}
    Touched:{{ stepInputFormControl2.touched }}
    Status:{{ stepInputFormControl2.status }}
    \n \n
    \n\n
    \n \n \n Value: {{ value2 }}\n
    \n
    \n `,\n imports: [FormLabelComponent, StepInputModule, FormsModule, ReactiveFormsModule, ButtonComponent]\n})\nexport class StepInputFormExampleComponent {\n stepInputFormControl1 = new FormControl(null);\n stepInputFormControl1a = new FormControl(5);\n stepInputFormControl2 = new FormControl({ disabled: true, value: 100 });\n value1: number | null = 100;\n value2: number | null = 100;\n\n toggleDisabledState(): void {\n this.stepInputFormControl2.enabled ? this.stepInputFormControl2.disable() : this.stepInputFormControl2.enable();\n }\n}\n" } ] }, @@ -47252,17 +47318,17 @@ "typescript": "import { UpperCasePipe } from '@angular/common';\nimport { Component, ViewChild } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { DialogRef, DialogService } from '@fundamental-ngx/core/dialog';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableComponent, TableModule } from '@fundamental-ngx/core/table';\nimport { TableCustomDialogComponent } from './table-custom-dialog.component';\n\nexport interface DisplayedColumn {\n key: string;\n checked: boolean;\n}\n\nexport interface CellData {\n column1: string;\n column2: string;\n column3: string;\n date: string;\n type: string;\n}\n\nconst CELL_DATA: CellData[] = [\n { column1: 'Row 111', column2: 'Row 221', column3: 'Row 1', date: '09-07-18', type: 'search' },\n { column1: 'Row 112', column2: 'Row 222', column3: 'Row 2', date: '09-08-18', type: 'cart' },\n { column1: 'Row 113', column2: 'Row 223', column3: 'Row 3', date: '02-14-18', type: 'calendar' },\n { column1: 'Row 114', column2: 'Row 224', column3: 'Row 4', date: '12-30-17', type: 'search' },\n { column1: 'Row 115', column2: 'Row 225', column3: 'Row 5', date: '11-12-18', type: 'search' }\n];\n\n@Component({\n selector: 'fd-table-custom-columns-example',\n templateUrl: './table-custom-columns-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, IconComponent, ButtonComponent, UpperCasePipe]\n})\nexport class TableCustomColumnsExampleComponent {\n @ViewChild(TableComponent)\n tableComponent: TableComponent;\n\n displayedColumns: string[];\n originalDisplayedColumns: DisplayedColumn[];\n dataSource = CELL_DATA;\n dialogRef: DialogRef;\n\n constructor(private _dialogService: DialogService) {\n this.displayedColumns = Object.keys(this.dataSource[0]);\n this.originalDisplayedColumns = [];\n\n Object.keys(this.dataSource[0]).forEach((key) => {\n this.originalDisplayedColumns.push({ key, checked: true });\n });\n }\n\n openDialog(): void {\n const dialogRef = this._dialogService.open(TableCustomDialogComponent, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n data: {\n columns: this.originalDisplayedColumns\n }\n });\n\n dialogRef.afterClosed.subscribe(\n (columns) => {\n this.originalDisplayedColumns = [...columns];\n this._propagateChangeToDisplayedValue();\n },\n () => {\n console.log('closed without changes');\n }\n );\n }\n\n private _propagateChangeToDisplayedValue(): void {\n this.displayedColumns = [\n ...this.originalDisplayedColumns.filter((_col) => _col.checked).map((_col) => _col.key)\n ];\n this.tableComponent.reset(this.displayedColumns);\n }\n}\n", "html": "\n \n \n @for (column of displayedColumns; track column) {\n \n }\n \n \n \n @for (row of dataSource; track row) {\n \n \n \n \n \n \n \n }\n \n
    {{ column | uppercase }}
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}
    \n
    \n
    \nChosen Columns: {{ displayedColumns }}\n
    \n
    \n\n" }, - { - "name": "table-focusable-example", - "description": "Table Focusable", - "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", - "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" - }, { "name": "table-popin-example", "description": "Table Popin", "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-popin-example',\n templateUrl: './table-popin-example.component.html',\n styles: [\n `\n .table-example-popin-title {\n margin: 0 0 10px 0;\n }\n `\n ],\n imports: [\n FocusableGridDirective,\n TableModule,\n FormLabelComponent,\n ObjectStatusComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class TablePopinExampleComponent {\n masterCheckbox: boolean | null = false;\n\n fruits: any[] = [\n {\n name: 'Banana',\n status: 'positive',\n statusName: 'Available',\n dateOfExpire: '12.06.2020',\n price: '5 EUR',\n country: 'India',\n description: `A banana is an elongated, edible fruit – botanically a berry – produced by several kinds of large herbaceous\n flowering plants in the genus Musa.`,\n checked: false\n },\n {\n name: 'Apple',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '10.06.2020',\n price: '5,5 EUR',\n country: 'USA',\n description: `An apple is an edible fruit produced by an apple tree (Malus domestica).\n Apple trees are cultivated worldwide and are the most widely grown species in the genus Malus.`,\n checked: false\n },\n {\n name: 'Pineapple',\n status: 'negative',\n statusName: 'Out of stock',\n dateOfExpire: '08.06.2020',\n price: '6 EUR',\n country: 'Mexico',\n description: `The pineapple (Ananas comosus) is a tropical plant with an edible fruit and the most\n economically significant plant in the family Bromeliaceae.`,\n checked: false\n },\n {\n name: 'Orange',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '18.06.2020',\n price: '10 EUR',\n country: 'Spain',\n description: `The orange is the fruit of various citrus species in the family Rutaceae\n (see list of plants known as orange); it primarily refers to Citrus × sinensis.`,\n checked: false\n }\n ];\n\n constructor() {}\n\n select(index: number, checked: boolean): void {\n this.fruits[index].checked = checked;\n\n this._handleMasterCheckboxState();\n }\n\n selectMaster(checked: boolean): void {\n checked ? this._selectAll() : this._deselectAll();\n\n this._handleMasterCheckboxState();\n }\n\n private _handleMasterCheckboxState(): void {\n this.masterCheckbox = this._allSelected() ? true : this._anySelected() ? null : false;\n }\n\n private _selectAll(): void {\n this.fruits.forEach((row) => (row.checked = true));\n }\n\n private _deselectAll(): void {\n this.fruits.forEach((row) => (row.checked = false));\n }\n\n private _anySelected(): boolean {\n return this.fruits.some((_row) => _row.checked);\n }\n\n private _allSelected(): boolean {\n return this.fruits.every((_row) => _row.checked);\n }\n}\n", "html": "
    \n

    Mobile Mode

    \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Tablet Mode

    \n \n \n \n Fruit Description\n Price\n Status\n Date Of Expire\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n {{ fruit.dateOfExpire }}\n \n \n \n \n \n \n \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Desktop Mode

    \n \n \n \n \n \n \n \n \n \n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n \n \n \n \n \n \n \n }\n \n
    NamePriceCountryStatusDate Of ExpireDescription
    \n {{ fruit.name }}\n \n {{ fruit.country }}\n \n {{ fruit.price }}\n \n \n \n {{ fruit.dateOfExpire }}\n \n {{ fruit.description }}\n \n \n
    \n
    \n
    \n

    Popin Mobile Mode with Checkboxes

    \n \n \n \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit; let ind = $index) {\n \n \n \n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n" + }, + { + "name": "table-focusable-example", + "description": "Table Focusable", + "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", + "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" } ] }, @@ -47575,17 +47641,17 @@ "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { FdDate, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { TimeModule } from '@fundamental-ngx/core/time';\n\n@Component({\n selector: 'fd-time-sizes-example',\n templateUrl: './time-sizes-example.component.html',\n providers: [provideDateTimeFormats()],\n imports: [TimeModule, ContentDensityDirective, FormsModule]\n})\nexport class TimeSizesExampleComponent {\n timeCompact = new FdDate();\n timeTablet = new FdDate();\n}\n", "html": "\n\n" }, - { - "name": "time-no-spinners-example", - "description": "Time No Spinners", - "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FdDate, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { TimeModule } from '@fundamental-ngx/core/time';\n\n@Component({\n selector: 'fd-time-no-spinners-example',\n templateUrl: './time-no-spinners-example.component.html',\n providers: [provideDateTimeFormats()],\n imports: [TimeModule, FormsModule]\n})\nexport class TimeNoSpinnersExampleComponent {\n time = new FdDate().setTime(9, 0, 0);\n}\n", - "html": "\n" - }, { "name": "time-two-digits-example", "description": "Time Two Digits", "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FdDate, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { TimeModule } from '@fundamental-ngx/core/time';\n\n@Component({\n selector: 'fd-time-two-digits-example',\n templateUrl: './time-two-digits-example.component.html',\n providers: [provideDateTimeFormats()],\n imports: [TimeModule, FormsModule]\n})\nexport class TimeTwoDigitsExampleComponent {\n time = new FdDate().setTime(9, 0, 0);\n}\n", "html": " \n
    \nSelected Time: {{ time.hour }}h {{ time.minute }}m {{ time.second }}s\n" + }, + { + "name": "time-no-spinners-example", + "description": "Time No Spinners", + "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FdDate, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { TimeModule } from '@fundamental-ngx/core/time';\n\n@Component({\n selector: 'fd-time-no-spinners-example',\n templateUrl: './time-no-spinners-example.component.html',\n providers: [provideDateTimeFormats()],\n imports: [TimeModule, FormsModule]\n})\nexport class TimeNoSpinnersExampleComponent {\n time = new FdDate().setTime(9, 0, 0);\n}\n", + "html": "\n" } ] }, @@ -47767,17 +47833,17 @@ "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { FdDate, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { TimeModule } from '@fundamental-ngx/core/time';\n\n@Component({\n selector: 'fd-time-sizes-example',\n templateUrl: './time-sizes-example.component.html',\n providers: [provideDateTimeFormats()],\n imports: [TimeModule, ContentDensityDirective, FormsModule]\n})\nexport class TimeSizesExampleComponent {\n timeCompact = new FdDate();\n timeTablet = new FdDate();\n}\n", "html": "\n\n" }, - { - "name": "time-no-spinners-example", - "description": "Time No Spinners", - "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FdDate, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { TimeModule } from '@fundamental-ngx/core/time';\n\n@Component({\n selector: 'fd-time-no-spinners-example',\n templateUrl: './time-no-spinners-example.component.html',\n providers: [provideDateTimeFormats()],\n imports: [TimeModule, FormsModule]\n})\nexport class TimeNoSpinnersExampleComponent {\n time = new FdDate().setTime(9, 0, 0);\n}\n", - "html": "\n" - }, { "name": "time-two-digits-example", "description": "Time Two Digits", "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FdDate, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { TimeModule } from '@fundamental-ngx/core/time';\n\n@Component({\n selector: 'fd-time-two-digits-example',\n templateUrl: './time-two-digits-example.component.html',\n providers: [provideDateTimeFormats()],\n imports: [TimeModule, FormsModule]\n})\nexport class TimeTwoDigitsExampleComponent {\n time = new FdDate().setTime(9, 0, 0);\n}\n", "html": " \n
    \nSelected Time: {{ time.hour }}h {{ time.minute }}m {{ time.second }}s\n" + }, + { + "name": "time-no-spinners-example", + "description": "Time No Spinners", + "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FdDate, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { TimeModule } from '@fundamental-ngx/core/time';\n\n@Component({\n selector: 'fd-time-no-spinners-example',\n templateUrl: './time-no-spinners-example.component.html',\n providers: [provideDateTimeFormats()],\n imports: [TimeModule, FormsModule]\n})\nexport class TimeNoSpinnersExampleComponent {\n time = new FdDate().setTime(9, 0, 0);\n}\n", + "html": "\n" } ] }, @@ -50890,16 +50956,16 @@ "description": "Menu Button", "typescript": "import { Component } from '@angular/core';\nimport { SearchFieldComponent } from '@fundamental-ngx/btp/search-field';\nimport { ToolHeaderAutoModeDirective, ToolHeaderComponent } from '@fundamental-ngx/btp/tool-header';\n\n@Component({\n selector: 'fdb-tool-header-menu-button-example',\n template: `\n \n \n \n
    Last action: {{ lastAction }}
    \n `,\n imports: [SearchFieldComponent, ToolHeaderAutoModeDirective, ToolHeaderComponent]\n})\nexport class MenuButtonExampleComponent {\n lastAction: string;\n}\n" }, - { - "name": "product-switch-example", - "description": "Product Switch", - "typescript": "import { Component } from '@angular/core';\nimport { ToolHeaderComponent, ToolHeaderProductSwitchComponent } from '@fundamental-ngx/btp/tool-header';\nimport { ProductSwitchBodyComponent, ProductSwitchItem } from '@fundamental-ngx/core/product-switch';\n\n@Component({\n selector: 'fdb-tool-header-product-switch-example',\n template: `\n \n \n \n \n \n `,\n imports: [ToolHeaderComponent, ProductSwitchBodyComponent, ToolHeaderProductSwitchComponent]\n})\nexport class ProductSwitchExampleComponent {\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n}\n" - }, { "name": "usage-with-layout-example", "description": "Usage With Layout", "typescript": "import { AsyncPipe } from '@angular/common';\nimport { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { SearchFieldComponent } from '@fundamental-ngx/btp/search-field';\nimport {\n FdbToolHeaderActionButton,\n ToolHeaderAutoModeDirective,\n ToolHeaderComponent\n} from '@fundamental-ngx/btp/tool-header';\nimport {\n ToolLayoutComponent,\n ToolLayoutContainerDirective,\n ToolLayoutContentContainerDirective,\n ToolLayoutHeaderContainerDirective,\n ToolLayoutNavigationContainerDirective\n} from '@fundamental-ngx/btp/tool-layout';\n\n@Component({\n selector: 'fdb-tool-layout-usage-with-layout-example',\n templateUrl: './usage-with-layout-example.component.html',\n imports: [\n ToolLayoutComponent,\n ToolLayoutContainerDirective,\n ToolLayoutContentContainerDirective,\n ToolLayoutHeaderContainerDirective,\n ToolLayoutNavigationContainerDirective,\n SearchFieldComponent,\n ToolHeaderAutoModeDirective,\n ToolHeaderComponent,\n FormsModule,\n AsyncPipe\n ]\n})\nexport class UsageWithLayoutExampleComponent {\n searchValue = '';\n\n actions: Array = [\n [\n {\n label: 'Source Code',\n glyph: 'source-code',\n clickCallback: () => {\n console.log('Source code');\n },\n forceVisibility: false\n }\n ],\n [\n {\n label: 'Notifications',\n glyph: 'bell',\n clickCallback: () => {\n console.log('Action 1');\n },\n forceVisibility: true,\n hasBadge: true\n },\n {\n label: 'Settings',\n glyph: 'settings',\n clickCallback: () => {\n console.log('Settings');\n },\n forceVisibility: false\n }\n ]\n ];\n\n valueUpdate($event: any): void {}\n\n toggleMenu(b: boolean): void {}\n}\n", "html": "
    \n
    \n
    \n \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, + { + "name": "product-switch-example", + "description": "Product Switch", + "typescript": "import { Component } from '@angular/core';\nimport { ToolHeaderComponent, ToolHeaderProductSwitchComponent } from '@fundamental-ngx/btp/tool-header';\nimport { ProductSwitchBodyComponent, ProductSwitchItem } from '@fundamental-ngx/core/product-switch';\n\n@Component({\n selector: 'fdb-tool-header-product-switch-example',\n template: `\n \n \n \n \n \n `,\n imports: [ToolHeaderComponent, ProductSwitchBodyComponent, ToolHeaderProductSwitchComponent]\n})\nexport class ProductSwitchExampleComponent {\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n}\n" } ] }, @@ -50946,16 +51012,16 @@ "description": "Menu Button", "typescript": "import { Component } from '@angular/core';\nimport { SearchFieldComponent } from '@fundamental-ngx/btp/search-field';\nimport { ToolHeaderAutoModeDirective, ToolHeaderComponent } from '@fundamental-ngx/btp/tool-header';\n\n@Component({\n selector: 'fdb-tool-header-menu-button-example',\n template: `\n \n \n \n
    Last action: {{ lastAction }}
    \n `,\n imports: [SearchFieldComponent, ToolHeaderAutoModeDirective, ToolHeaderComponent]\n})\nexport class MenuButtonExampleComponent {\n lastAction: string;\n}\n" }, - { - "name": "product-switch-example", - "description": "Product Switch", - "typescript": "import { Component } from '@angular/core';\nimport { ToolHeaderComponent, ToolHeaderProductSwitchComponent } from '@fundamental-ngx/btp/tool-header';\nimport { ProductSwitchBodyComponent, ProductSwitchItem } from '@fundamental-ngx/core/product-switch';\n\n@Component({\n selector: 'fdb-tool-header-product-switch-example',\n template: `\n \n \n \n \n \n `,\n imports: [ToolHeaderComponent, ProductSwitchBodyComponent, ToolHeaderProductSwitchComponent]\n})\nexport class ProductSwitchExampleComponent {\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n}\n" - }, { "name": "usage-with-layout-example", "description": "Usage With Layout", "typescript": "import { AsyncPipe } from '@angular/common';\nimport { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { SearchFieldComponent } from '@fundamental-ngx/btp/search-field';\nimport {\n FdbToolHeaderActionButton,\n ToolHeaderAutoModeDirective,\n ToolHeaderComponent\n} from '@fundamental-ngx/btp/tool-header';\nimport {\n ToolLayoutComponent,\n ToolLayoutContainerDirective,\n ToolLayoutContentContainerDirective,\n ToolLayoutHeaderContainerDirective,\n ToolLayoutNavigationContainerDirective\n} from '@fundamental-ngx/btp/tool-layout';\n\n@Component({\n selector: 'fdb-tool-layout-usage-with-layout-example',\n templateUrl: './usage-with-layout-example.component.html',\n imports: [\n ToolLayoutComponent,\n ToolLayoutContainerDirective,\n ToolLayoutContentContainerDirective,\n ToolLayoutHeaderContainerDirective,\n ToolLayoutNavigationContainerDirective,\n SearchFieldComponent,\n ToolHeaderAutoModeDirective,\n ToolHeaderComponent,\n FormsModule,\n AsyncPipe\n ]\n})\nexport class UsageWithLayoutExampleComponent {\n searchValue = '';\n\n actions: Array = [\n [\n {\n label: 'Source Code',\n glyph: 'source-code',\n clickCallback: () => {\n console.log('Source code');\n },\n forceVisibility: false\n }\n ],\n [\n {\n label: 'Notifications',\n glyph: 'bell',\n clickCallback: () => {\n console.log('Action 1');\n },\n forceVisibility: true,\n hasBadge: true\n },\n {\n label: 'Settings',\n glyph: 'settings',\n clickCallback: () => {\n console.log('Settings');\n },\n forceVisibility: false\n }\n ]\n ];\n\n valueUpdate($event: any): void {}\n\n toggleMenu(b: boolean): void {}\n}\n", "html": "
    \n
    \n
    \n \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, + { + "name": "product-switch-example", + "description": "Product Switch", + "typescript": "import { Component } from '@angular/core';\nimport { ToolHeaderComponent, ToolHeaderProductSwitchComponent } from '@fundamental-ngx/btp/tool-header';\nimport { ProductSwitchBodyComponent, ProductSwitchItem } from '@fundamental-ngx/core/product-switch';\n\n@Component({\n selector: 'fdb-tool-header-product-switch-example',\n template: `\n \n \n \n \n \n `,\n imports: [ToolHeaderComponent, ProductSwitchBodyComponent, ToolHeaderProductSwitchComponent]\n})\nexport class ProductSwitchExampleComponent {\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n}\n" } ] }, @@ -51067,16 +51133,16 @@ "description": "Menu Button", "typescript": "import { Component } from '@angular/core';\nimport { SearchFieldComponent } from '@fundamental-ngx/btp/search-field';\nimport { ToolHeaderAutoModeDirective, ToolHeaderComponent } from '@fundamental-ngx/btp/tool-header';\n\n@Component({\n selector: 'fdb-tool-header-menu-button-example',\n template: `\n \n \n \n
    Last action: {{ lastAction }}
    \n `,\n imports: [SearchFieldComponent, ToolHeaderAutoModeDirective, ToolHeaderComponent]\n})\nexport class MenuButtonExampleComponent {\n lastAction: string;\n}\n" }, - { - "name": "product-switch-example", - "description": "Product Switch", - "typescript": "import { Component } from '@angular/core';\nimport { ToolHeaderComponent, ToolHeaderProductSwitchComponent } from '@fundamental-ngx/btp/tool-header';\nimport { ProductSwitchBodyComponent, ProductSwitchItem } from '@fundamental-ngx/core/product-switch';\n\n@Component({\n selector: 'fdb-tool-header-product-switch-example',\n template: `\n \n \n \n \n \n `,\n imports: [ToolHeaderComponent, ProductSwitchBodyComponent, ToolHeaderProductSwitchComponent]\n})\nexport class ProductSwitchExampleComponent {\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n}\n" - }, { "name": "usage-with-layout-example", "description": "Usage With Layout", "typescript": "import { AsyncPipe } from '@angular/common';\nimport { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { SearchFieldComponent } from '@fundamental-ngx/btp/search-field';\nimport {\n FdbToolHeaderActionButton,\n ToolHeaderAutoModeDirective,\n ToolHeaderComponent\n} from '@fundamental-ngx/btp/tool-header';\nimport {\n ToolLayoutComponent,\n ToolLayoutContainerDirective,\n ToolLayoutContentContainerDirective,\n ToolLayoutHeaderContainerDirective,\n ToolLayoutNavigationContainerDirective\n} from '@fundamental-ngx/btp/tool-layout';\n\n@Component({\n selector: 'fdb-tool-layout-usage-with-layout-example',\n templateUrl: './usage-with-layout-example.component.html',\n imports: [\n ToolLayoutComponent,\n ToolLayoutContainerDirective,\n ToolLayoutContentContainerDirective,\n ToolLayoutHeaderContainerDirective,\n ToolLayoutNavigationContainerDirective,\n SearchFieldComponent,\n ToolHeaderAutoModeDirective,\n ToolHeaderComponent,\n FormsModule,\n AsyncPipe\n ]\n})\nexport class UsageWithLayoutExampleComponent {\n searchValue = '';\n\n actions: Array = [\n [\n {\n label: 'Source Code',\n glyph: 'source-code',\n clickCallback: () => {\n console.log('Source code');\n },\n forceVisibility: false\n }\n ],\n [\n {\n label: 'Notifications',\n glyph: 'bell',\n clickCallback: () => {\n console.log('Action 1');\n },\n forceVisibility: true,\n hasBadge: true\n },\n {\n label: 'Settings',\n glyph: 'settings',\n clickCallback: () => {\n console.log('Settings');\n },\n forceVisibility: false\n }\n ]\n ];\n\n valueUpdate($event: any): void {}\n\n toggleMenu(b: boolean): void {}\n}\n", "html": "
    \n
    \n
    \n \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n" + }, + { + "name": "product-switch-example", + "description": "Product Switch", + "typescript": "import { Component } from '@angular/core';\nimport { ToolHeaderComponent, ToolHeaderProductSwitchComponent } from '@fundamental-ngx/btp/tool-header';\nimport { ProductSwitchBodyComponent, ProductSwitchItem } from '@fundamental-ngx/core/product-switch';\n\n@Component({\n selector: 'fdb-tool-header-product-switch-example',\n template: `\n \n \n \n \n \n `,\n imports: [ToolHeaderComponent, ProductSwitchBodyComponent, ToolHeaderProductSwitchComponent]\n})\nexport class ProductSwitchExampleComponent {\n productSwitcher: ProductSwitchItem[] = [\n {\n title: 'Home',\n subtitle: 'Central Home',\n icon: 'home',\n disabledDragAndDrop: true,\n stickToPosition: true\n },\n {\n title: 'Analytics Cloud',\n subtitle: 'Analytics Cloud',\n icon: 'business-objects-experience',\n selected: true\n },\n {\n title: 'Catalog',\n subtitle: 'Ariba',\n icon: 'contacts'\n },\n {\n title: 'Guided Buying',\n icon: 'credit-card'\n },\n {\n title: 'Strategic Procurement',\n icon: 'cart-3'\n },\n {\n title: 'Vendor Managemen',\n subtitle: 'Fieldglass',\n icon: 'shipping-status'\n },\n {\n title: 'Human Capital Management',\n icon: 'customer'\n },\n {\n title: 'Sales Cloud',\n subtitle: 'Sales Cloud',\n icon: 'sales-notification'\n },\n {\n title: 'Commerce Cloud',\n subtitle: 'Commerce Cloud',\n icon: 'retail-store'\n },\n {\n title: 'Marketing Cloud',\n subtitle: 'Marketing Cloud',\n icon: 'marketing-campaign'\n },\n {\n title: 'Service Cloud',\n icon: 'family-care'\n },\n {\n title: 'S/4HANA',\n icon: 'batch-payments'\n }\n ];\n}\n" } ] }, @@ -53289,12 +53355,6 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { JsonPipe } from '@angular/common';\nimport {\n ComboboxSelectionChangeEvent,\n FdpFormGroupModule,\n PlatformComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\n\n@Component({\n selector: 'fdp-combobox-columns-example',\n templateUrl: './combobox-columns-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, PlatformComboboxModule, JsonPipe]\n})\nexport class ComboboxColumnsExampleComponent {\n dataSource = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n {\n name: 'Biiiiiiiiiiiiiiiiiiiiiiggggggggggggggggggggggggg Banananananananananananananananananananananananananananananananananananananana',\n type: 'Fruits'\n },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n ];\n\n selectedItem = null;\n\n onSelect(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem = item.payload;\n }\n}\n", "html": "\n \n \n Selected Item: {{ selectedItem | json }} \n \n\n" }, - { - "name": "combobox-datasource-example", - "description": "Combobox Datasource", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { of } from 'rxjs';\n\nimport { JsonPipe } from '@angular/common';\nimport {\n ComboboxSelectionChangeEvent,\n FdpFormGroupModule,\n PlatformComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { ArrayComboBoxDataSource, DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\n\n@Component({\n selector: 'fdp-combobox-datasource-example',\n templateUrl: './combobox-datasource-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, PlatformComboboxModule, JsonPipe]\n})\nexport class ComboboxDatasourceExampleComponent {\n dataSourceStrings = ['Apple', 'Banana', 'Pineapple', 'Strawberry', 'Broccoli', 'Carrot', 'Jalapeño', 'Spinach'];\n\n dataSource = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n ];\n\n dataSourceOf = of(this.dataSource);\n ds = new ArrayComboBoxDataSource(this.dataSource);\n\n selectedItem1 = null;\n selectedItem2 = null;\n selectedItem3 = null;\n selectedItem4 = null;\n\n onSelect1(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem1 = item.payload;\n }\n\n onSelect2(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem2 = item.payload;\n }\n\n onSelect3(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem3 = item.payload;\n }\n\n onSelect4(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem4 = item.payload;\n }\n}\n", - "html": "\n \n \n Selected Item: {{ selectedItem1 }} \n \n\n \n \n Selected Item: {{ selectedItem2 | json }} \n \n\n \n \n Selected Item: {{ selectedItem3 | json }} \n \n\n \n \n Selected Item: {{ selectedItem4 | json }} \n \n\n" - }, { "name": "combobox-forms-example", "description": "Combobox Forms", @@ -53302,10 +53362,10 @@ "html": "\n \n \n \n Selected Item: {{ selectedItem | json }}\n
    \n Form Selected Item: {{ customForm.getRawValue() | json }}\n
    \n
    \n \n @if (errors.required) {\n Field is required\n }\n \n
    \n" }, { - "name": "combobox-group-example", - "description": "Combobox Group", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { JsonPipe } from '@angular/common';\nimport {\n ComboboxSelectionChangeEvent,\n FdpFormGroupModule,\n PlatformComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\n\n@Component({\n selector: 'fdp-combobox-group-example',\n templateUrl: './combobox-group-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, PlatformComboboxModule, JsonPipe]\n})\nexport class ComboboxGroupExampleComponent {\n dataSource = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n ];\n\n selectedItem = null;\n selectedItem1 = null;\n\n onSelect(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem = item.payload;\n }\n\n onSelect1(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem1 = item.payload;\n }\n}\n", - "html": "\n \n \n Selected: {{ selectedItem | json }} \n \n\n \n \n Selected: {{ selectedItem1 | json }} \n \n\n" + "name": "combobox-datasource-example", + "description": "Combobox Datasource", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { of } from 'rxjs';\n\nimport { JsonPipe } from '@angular/common';\nimport {\n ComboboxSelectionChangeEvent,\n FdpFormGroupModule,\n PlatformComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { ArrayComboBoxDataSource, DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\n\n@Component({\n selector: 'fdp-combobox-datasource-example',\n templateUrl: './combobox-datasource-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, PlatformComboboxModule, JsonPipe]\n})\nexport class ComboboxDatasourceExampleComponent {\n dataSourceStrings = ['Apple', 'Banana', 'Pineapple', 'Strawberry', 'Broccoli', 'Carrot', 'Jalapeño', 'Spinach'];\n\n dataSource = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n ];\n\n dataSourceOf = of(this.dataSource);\n ds = new ArrayComboBoxDataSource(this.dataSource);\n\n selectedItem1 = null;\n selectedItem2 = null;\n selectedItem3 = null;\n selectedItem4 = null;\n\n onSelect1(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem1 = item.payload;\n }\n\n onSelect2(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem2 = item.payload;\n }\n\n onSelect3(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem3 = item.payload;\n }\n\n onSelect4(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem4 = item.payload;\n }\n}\n", + "html": "\n \n \n Selected Item: {{ selectedItem1 }} \n \n\n \n \n Selected Item: {{ selectedItem2 | json }} \n \n\n \n \n Selected Item: {{ selectedItem3 | json }} \n \n\n \n \n Selected Item: {{ selectedItem4 | json }} \n \n\n" }, { "name": "combobox-loading-example", @@ -53313,23 +53373,29 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { FormsModule } from '@angular/forms';\nimport { BusyIndicatorComponent } from '@fundamental-ngx/core/busy-indicator';\nimport { FdpFormGroupModule, PlatformComboboxModule } from '@fundamental-ngx/platform/form';\nimport { BaseDataProvider, ComboBoxDataSource, DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\nimport { Observable } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-combobox-loading-example',\n templateUrl: './combobox-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, BusyIndicatorComponent, PlatformComboboxModule, FormsModule]\n})\nexport class ComboboxLoadingExampleComponent {\n options = ['Apple', 'Banana', 'Pineapple', 'Strawberry', 'Broccoli', 'Carrot', 'Jalapeño', 'Spinach'];\n readonly dataSource = new ComboBoxDataSource(new DelayedBaseDataProvider(this.options));\n\n selectedItem = this.options[3];\n\n loading = false;\n\n onDataRequested(): void {\n this.loading = true;\n }\n onDataReceived(): void {\n this.loading = false;\n }\n}\n\n// Simulating real http request by adding 300ms delay to the DataProvider's \"fetch\" method\nclass DelayedBaseDataProvider extends BaseDataProvider {\n fetch(params: Map): Observable {\n return super.fetch(params).pipe(delay(300));\n }\n}\n", "html": "\n \n \n \n \n Selected: {{ selectedItem }}\n \n\n" }, + { + "name": "combobox-group-example", + "description": "Combobox Group", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { JsonPipe } from '@angular/common';\nimport {\n ComboboxSelectionChangeEvent,\n FdpFormGroupModule,\n PlatformComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\n\n@Component({\n selector: 'fdp-combobox-group-example',\n templateUrl: './combobox-group-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, PlatformComboboxModule, JsonPipe]\n})\nexport class ComboboxGroupExampleComponent {\n dataSource = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n ];\n\n selectedItem = null;\n selectedItem1 = null;\n\n onSelect(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem = item.payload;\n }\n\n onSelect1(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem1 = item.payload;\n }\n}\n", + "html": "\n \n \n Selected: {{ selectedItem | json }} \n \n\n \n \n Selected: {{ selectedItem1 | json }} \n \n\n" + }, { "name": "combobox-mobile-example", "description": "Combobox Mobile", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { JsonPipe } from '@angular/common';\nimport { MobileModeConfig } from '@fundamental-ngx/core/mobile-mode';\nimport {\n ComboboxSelectionChangeEvent,\n FdpFormGroupModule,\n PlatformComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\n\n@Component({\n selector: 'fdp-combobox-mobile-example',\n templateUrl: './combobox-mobile-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, PlatformComboboxModule, JsonPipe]\n})\nexport class ComboboxMobileExampleComponent {\n dataSource = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n ];\n\n selectedItem = null;\n\n mobileConfig: MobileModeConfig = {\n title: 'Title',\n approveButtonText: 'Save',\n cancelButtonText: 'Cancel',\n hasCloseButton: true\n };\n\n onSelect(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem = item.payload;\n }\n}\n", "html": "\n \n \n Selected: {{ selectedItem | json }} \n \n\n" }, - { - "name": "combobox-states-example", - "description": "Combobox States", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { FormStates } from '@fundamental-ngx/cdk/forms';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n ComboboxSelectionChangeEvent,\n FdpFormGroupModule,\n PlatformComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\n\n@Component({\n selector: 'fdp-combobox-states-example',\n templateUrl: './combobox-states-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, ContentDensityDirective, PlatformComboboxModule]\n})\nexport class ComboboxStateComponent {\n dataSource = ['Apple', 'Banana', 'Pineapple', 'Strawberry', 'Broccoli', 'Carrot', 'Jalapeño', 'Spinach'];\n\n states: FormStates[] = ['default', 'success', 'error', 'warning', 'information'];\n selectedState = this.states[0];\n\n onSelectState(item: ComboboxSelectionChangeEvent): void {\n this.selectedState = item.payload;\n }\n}\n", - "html": "\n \n \n \n \n \n \n \n\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n\n" - }, { "name": "combobox-templates-example", "description": "Combobox Templates", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { JsonPipe } from '@angular/common';\nimport { TemplateDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport {\n ComboboxSelectionChangeEvent,\n FdpFormGroupModule,\n PlatformComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\n\ninterface ComboboxTemplateItem {\n name: string;\n type: string;\n}\n\n@Component({\n selector: 'fdp-combobox-templates-example',\n templateUrl: './combobox-templates-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n styles: [\n '.fd-template-container-div { display: flex; align-items: center; cursor: pointer;}',\n '.fd-template-text { margin-right: 12px; margin-left: 12px; }'\n ],\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, PlatformComboboxModule, TemplateDirective, IconComponent, JsonPipe]\n})\nexport class ComboboxTemplatesExampleComponent {\n dataSource: ComboboxTemplateItem[] = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n ];\n\n model: ComboboxTemplateItem;\n\n selectedItem = null;\n selectedItem1 = null;\n selectedItem2 = null;\n selectedItem3 = null;\n\n onSelect(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem = item.payload;\n }\n\n onSelect1(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem1 = item.payload;\n }\n\n onSelect2(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem2 = item.payload;\n }\n\n onSelect3(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem3 = item.payload;\n }\n}\n", "html": "\n \n \n \n \n
    \n \n {{ item.name }}\n
    \n
    \n \n Selected: {{ selectedItem | json }} \n
    \n\n \n \n \n
  • {{ 'Type: ' + group.label }}
  • \n
    \n \n Selected: {{ selectedItem1 | json }} \n
    \n\n \n \n \n {{ item.type }}\n \n \n Selected: {{ selectedItem2 | json }} \n \n\n \n \n \n
    \n \n {{ item.name }}\n
    \n
    \n \n Selected: {{ selectedItem3 | json }} \n
    \n
    \n" + }, + { + "name": "combobox-states-example", + "description": "Combobox States", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { FormStates } from '@fundamental-ngx/cdk/forms';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n ComboboxSelectionChangeEvent,\n FdpFormGroupModule,\n PlatformComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\n\n@Component({\n selector: 'fdp-combobox-states-example',\n templateUrl: './combobox-states-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, ContentDensityDirective, PlatformComboboxModule]\n})\nexport class ComboboxStateComponent {\n dataSource = ['Apple', 'Banana', 'Pineapple', 'Strawberry', 'Broccoli', 'Carrot', 'Jalapeño', 'Spinach'];\n\n states: FormStates[] = ['default', 'success', 'error', 'warning', 'information'];\n selectedState = this.states[0];\n\n onSelectState(item: ComboboxSelectionChangeEvent): void {\n this.selectedState = item.payload;\n }\n}\n", + "html": "\n \n \n \n \n \n \n \n\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n\n" } ] }, @@ -53359,12 +53425,6 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { JsonPipe } from '@angular/common';\nimport {\n ComboboxSelectionChangeEvent,\n FdpFormGroupModule,\n PlatformComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\n\n@Component({\n selector: 'fdp-combobox-columns-example',\n templateUrl: './combobox-columns-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, PlatformComboboxModule, JsonPipe]\n})\nexport class ComboboxColumnsExampleComponent {\n dataSource = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n {\n name: 'Biiiiiiiiiiiiiiiiiiiiiiggggggggggggggggggggggggg Banananananananananananananananananananananananananananananananananananananana',\n type: 'Fruits'\n },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n ];\n\n selectedItem = null;\n\n onSelect(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem = item.payload;\n }\n}\n", "html": "\n \n \n Selected Item: {{ selectedItem | json }} \n \n\n" }, - { - "name": "combobox-datasource-example", - "description": "Combobox Datasource", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { of } from 'rxjs';\n\nimport { JsonPipe } from '@angular/common';\nimport {\n ComboboxSelectionChangeEvent,\n FdpFormGroupModule,\n PlatformComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { ArrayComboBoxDataSource, DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\n\n@Component({\n selector: 'fdp-combobox-datasource-example',\n templateUrl: './combobox-datasource-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, PlatformComboboxModule, JsonPipe]\n})\nexport class ComboboxDatasourceExampleComponent {\n dataSourceStrings = ['Apple', 'Banana', 'Pineapple', 'Strawberry', 'Broccoli', 'Carrot', 'Jalapeño', 'Spinach'];\n\n dataSource = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n ];\n\n dataSourceOf = of(this.dataSource);\n ds = new ArrayComboBoxDataSource(this.dataSource);\n\n selectedItem1 = null;\n selectedItem2 = null;\n selectedItem3 = null;\n selectedItem4 = null;\n\n onSelect1(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem1 = item.payload;\n }\n\n onSelect2(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem2 = item.payload;\n }\n\n onSelect3(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem3 = item.payload;\n }\n\n onSelect4(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem4 = item.payload;\n }\n}\n", - "html": "\n \n \n Selected Item: {{ selectedItem1 }} \n \n\n \n \n Selected Item: {{ selectedItem2 | json }} \n \n\n \n \n Selected Item: {{ selectedItem3 | json }} \n \n\n \n \n Selected Item: {{ selectedItem4 | json }} \n \n\n" - }, { "name": "combobox-forms-example", "description": "Combobox Forms", @@ -53372,10 +53432,10 @@ "html": "\n \n \n \n Selected Item: {{ selectedItem | json }}\n
    \n Form Selected Item: {{ customForm.getRawValue() | json }}\n
    \n
    \n \n @if (errors.required) {\n Field is required\n }\n \n
    \n" }, { - "name": "combobox-group-example", - "description": "Combobox Group", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { JsonPipe } from '@angular/common';\nimport {\n ComboboxSelectionChangeEvent,\n FdpFormGroupModule,\n PlatformComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\n\n@Component({\n selector: 'fdp-combobox-group-example',\n templateUrl: './combobox-group-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, PlatformComboboxModule, JsonPipe]\n})\nexport class ComboboxGroupExampleComponent {\n dataSource = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n ];\n\n selectedItem = null;\n selectedItem1 = null;\n\n onSelect(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem = item.payload;\n }\n\n onSelect1(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem1 = item.payload;\n }\n}\n", - "html": "\n \n \n Selected: {{ selectedItem | json }} \n \n\n \n \n Selected: {{ selectedItem1 | json }} \n \n\n" + "name": "combobox-datasource-example", + "description": "Combobox Datasource", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { of } from 'rxjs';\n\nimport { JsonPipe } from '@angular/common';\nimport {\n ComboboxSelectionChangeEvent,\n FdpFormGroupModule,\n PlatformComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { ArrayComboBoxDataSource, DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\n\n@Component({\n selector: 'fdp-combobox-datasource-example',\n templateUrl: './combobox-datasource-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, PlatformComboboxModule, JsonPipe]\n})\nexport class ComboboxDatasourceExampleComponent {\n dataSourceStrings = ['Apple', 'Banana', 'Pineapple', 'Strawberry', 'Broccoli', 'Carrot', 'Jalapeño', 'Spinach'];\n\n dataSource = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n ];\n\n dataSourceOf = of(this.dataSource);\n ds = new ArrayComboBoxDataSource(this.dataSource);\n\n selectedItem1 = null;\n selectedItem2 = null;\n selectedItem3 = null;\n selectedItem4 = null;\n\n onSelect1(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem1 = item.payload;\n }\n\n onSelect2(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem2 = item.payload;\n }\n\n onSelect3(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem3 = item.payload;\n }\n\n onSelect4(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem4 = item.payload;\n }\n}\n", + "html": "\n \n \n Selected Item: {{ selectedItem1 }} \n \n\n \n \n Selected Item: {{ selectedItem2 | json }} \n \n\n \n \n Selected Item: {{ selectedItem3 | json }} \n \n\n \n \n Selected Item: {{ selectedItem4 | json }} \n \n\n" }, { "name": "combobox-loading-example", @@ -53383,23 +53443,29 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { FormsModule } from '@angular/forms';\nimport { BusyIndicatorComponent } from '@fundamental-ngx/core/busy-indicator';\nimport { FdpFormGroupModule, PlatformComboboxModule } from '@fundamental-ngx/platform/form';\nimport { BaseDataProvider, ComboBoxDataSource, DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\nimport { Observable } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-combobox-loading-example',\n templateUrl: './combobox-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, BusyIndicatorComponent, PlatformComboboxModule, FormsModule]\n})\nexport class ComboboxLoadingExampleComponent {\n options = ['Apple', 'Banana', 'Pineapple', 'Strawberry', 'Broccoli', 'Carrot', 'Jalapeño', 'Spinach'];\n readonly dataSource = new ComboBoxDataSource(new DelayedBaseDataProvider(this.options));\n\n selectedItem = this.options[3];\n\n loading = false;\n\n onDataRequested(): void {\n this.loading = true;\n }\n onDataReceived(): void {\n this.loading = false;\n }\n}\n\n// Simulating real http request by adding 300ms delay to the DataProvider's \"fetch\" method\nclass DelayedBaseDataProvider extends BaseDataProvider {\n fetch(params: Map): Observable {\n return super.fetch(params).pipe(delay(300));\n }\n}\n", "html": "\n \n \n \n \n Selected: {{ selectedItem }}\n \n\n" }, + { + "name": "combobox-group-example", + "description": "Combobox Group", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { JsonPipe } from '@angular/common';\nimport {\n ComboboxSelectionChangeEvent,\n FdpFormGroupModule,\n PlatformComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\n\n@Component({\n selector: 'fdp-combobox-group-example',\n templateUrl: './combobox-group-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, PlatformComboboxModule, JsonPipe]\n})\nexport class ComboboxGroupExampleComponent {\n dataSource = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n ];\n\n selectedItem = null;\n selectedItem1 = null;\n\n onSelect(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem = item.payload;\n }\n\n onSelect1(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem1 = item.payload;\n }\n}\n", + "html": "\n \n \n Selected: {{ selectedItem | json }} \n \n\n \n \n Selected: {{ selectedItem1 | json }} \n \n\n" + }, { "name": "combobox-mobile-example", "description": "Combobox Mobile", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { JsonPipe } from '@angular/common';\nimport { MobileModeConfig } from '@fundamental-ngx/core/mobile-mode';\nimport {\n ComboboxSelectionChangeEvent,\n FdpFormGroupModule,\n PlatformComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\n\n@Component({\n selector: 'fdp-combobox-mobile-example',\n templateUrl: './combobox-mobile-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, PlatformComboboxModule, JsonPipe]\n})\nexport class ComboboxMobileExampleComponent {\n dataSource = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n ];\n\n selectedItem = null;\n\n mobileConfig: MobileModeConfig = {\n title: 'Title',\n approveButtonText: 'Save',\n cancelButtonText: 'Cancel',\n hasCloseButton: true\n };\n\n onSelect(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem = item.payload;\n }\n}\n", "html": "\n \n \n Selected: {{ selectedItem | json }} \n \n\n" }, - { - "name": "combobox-states-example", - "description": "Combobox States", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { FormStates } from '@fundamental-ngx/cdk/forms';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n ComboboxSelectionChangeEvent,\n FdpFormGroupModule,\n PlatformComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\n\n@Component({\n selector: 'fdp-combobox-states-example',\n templateUrl: './combobox-states-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, ContentDensityDirective, PlatformComboboxModule]\n})\nexport class ComboboxStateComponent {\n dataSource = ['Apple', 'Banana', 'Pineapple', 'Strawberry', 'Broccoli', 'Carrot', 'Jalapeño', 'Spinach'];\n\n states: FormStates[] = ['default', 'success', 'error', 'warning', 'information'];\n selectedState = this.states[0];\n\n onSelectState(item: ComboboxSelectionChangeEvent): void {\n this.selectedState = item.payload;\n }\n}\n", - "html": "\n \n \n \n \n \n \n \n\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n\n" - }, { "name": "combobox-templates-example", "description": "Combobox Templates", "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { JsonPipe } from '@angular/common';\nimport { TemplateDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport {\n ComboboxSelectionChangeEvent,\n FdpFormGroupModule,\n PlatformComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\n\ninterface ComboboxTemplateItem {\n name: string;\n type: string;\n}\n\n@Component({\n selector: 'fdp-combobox-templates-example',\n templateUrl: './combobox-templates-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n styles: [\n '.fd-template-container-div { display: flex; align-items: center; cursor: pointer;}',\n '.fd-template-text { margin-right: 12px; margin-left: 12px; }'\n ],\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, PlatformComboboxModule, TemplateDirective, IconComponent, JsonPipe]\n})\nexport class ComboboxTemplatesExampleComponent {\n dataSource: ComboboxTemplateItem[] = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n ];\n\n model: ComboboxTemplateItem;\n\n selectedItem = null;\n selectedItem1 = null;\n selectedItem2 = null;\n selectedItem3 = null;\n\n onSelect(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem = item.payload;\n }\n\n onSelect1(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem1 = item.payload;\n }\n\n onSelect2(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem2 = item.payload;\n }\n\n onSelect3(item: ComboboxSelectionChangeEvent): void {\n this.selectedItem3 = item.payload;\n }\n}\n", "html": "\n \n \n \n \n
    \n \n {{ item.name }}\n
    \n
    \n \n Selected: {{ selectedItem | json }} \n
    \n\n \n \n \n
  • {{ 'Type: ' + group.label }}
  • \n
    \n \n Selected: {{ selectedItem1 | json }} \n
    \n\n \n \n \n {{ item.type }}\n \n \n Selected: {{ selectedItem2 | json }} \n \n\n \n \n \n
    \n \n {{ item.name }}\n
    \n
    \n \n Selected: {{ selectedItem3 | json }} \n
    \n
    \n" + }, + { + "name": "combobox-states-example", + "description": "Combobox States", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { FormStates } from '@fundamental-ngx/cdk/forms';\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport {\n ComboboxSelectionChangeEvent,\n FdpFormGroupModule,\n PlatformComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\n\n@Component({\n selector: 'fdp-combobox-states-example',\n templateUrl: './combobox-states-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, ContentDensityDirective, PlatformComboboxModule]\n})\nexport class ComboboxStateComponent {\n dataSource = ['Apple', 'Banana', 'Pineapple', 'Strawberry', 'Broccoli', 'Carrot', 'Jalapeño', 'Spinach'];\n\n states: FormStates[] = ['default', 'success', 'error', 'warning', 'information'];\n selectedState = this.states[0];\n\n onSelectState(item: ComboboxSelectionChangeEvent): void {\n this.selectedState = item.payload;\n }\n}\n", + "html": "\n \n \n \n \n \n \n \n\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n\n" } ] }, @@ -57556,18 +57622,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { textTypeConfig } from '../config-for-examples/text-type.config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-dynamic-overflow-example',\n templateUrl: './platform-icon-tab-bar-dynamic-overflow-example.component.html',\n imports: [IconTabBarComponent, ButtonComponent]\n})\nexport class PlatformIconTabBarDynamicOverflowExampleComponent {\n items: TabConfig[] = structuredClone(textTypeConfig);\n\n /** Whether the long labels variant is active. */\n useLongLabels = false;\n\n /** Toggle tab labels between short and long text to simulate a structure change (e.g. language switch). */\n toggleLabels(): void {\n this.useLongLabels = !this.useLongLabels;\n const base = structuredClone(textTypeConfig);\n if (this.useLongLabels) {\n base.forEach((item) => {\n item.label = `Very Long Label For ${item.label} With Extra Text`;\n });\n }\n this.items = base;\n }\n\n /** Add five more tabs dynamically to force overflow. */\n addMoreTabs(): void {\n const startIndex = this.items.length;\n const extra: TabConfig[] = Array.from({ length: 5 }, (_, i) => ({\n label: `New Tab ${startIndex + i}`,\n counter: Math.floor(Math.random() * 100),\n color: null\n }));\n this.items = [...this.items, ...extra];\n }\n}\n", "html": "
    \n \n \n
    \n\n\n" }, - { - "name": "platform-icon-tab-bar-filter-type-example", - "description": "Platform Icon Tab Bar Filter Type", - "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-filter-type-example',\n templateUrl: './platform-icon-tab-bar-filter-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarFilterTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", - "html": "\n" - }, { "name": "platform-icon-tab-bar-icon-only-type-example", "description": "Platform Icon Tab Bar Icon Only Type", "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-icon-only-type-example',\n templateUrl: './platform-icon-tab-bar-icon-only-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarIconOnlyTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", "html": "\n" }, + { + "name": "platform-icon-tab-bar-filter-type-example", + "description": "Platform Icon Tab Bar Filter Type", + "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-filter-type-example',\n templateUrl: './platform-icon-tab-bar-filter-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarFilterTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", + "html": "\n" + }, { "name": "platform-icon-tab-bar-icon-type-example", "description": "Platform Icon Tab Bar Icon Type", @@ -57692,18 +57758,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { textTypeConfig } from '../config-for-examples/text-type.config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-dynamic-overflow-example',\n templateUrl: './platform-icon-tab-bar-dynamic-overflow-example.component.html',\n imports: [IconTabBarComponent, ButtonComponent]\n})\nexport class PlatformIconTabBarDynamicOverflowExampleComponent {\n items: TabConfig[] = structuredClone(textTypeConfig);\n\n /** Whether the long labels variant is active. */\n useLongLabels = false;\n\n /** Toggle tab labels between short and long text to simulate a structure change (e.g. language switch). */\n toggleLabels(): void {\n this.useLongLabels = !this.useLongLabels;\n const base = structuredClone(textTypeConfig);\n if (this.useLongLabels) {\n base.forEach((item) => {\n item.label = `Very Long Label For ${item.label} With Extra Text`;\n });\n }\n this.items = base;\n }\n\n /** Add five more tabs dynamically to force overflow. */\n addMoreTabs(): void {\n const startIndex = this.items.length;\n const extra: TabConfig[] = Array.from({ length: 5 }, (_, i) => ({\n label: `New Tab ${startIndex + i}`,\n counter: Math.floor(Math.random() * 100),\n color: null\n }));\n this.items = [...this.items, ...extra];\n }\n}\n", "html": "
    \n \n \n
    \n\n\n" }, - { - "name": "platform-icon-tab-bar-filter-type-example", - "description": "Platform Icon Tab Bar Filter Type", - "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-filter-type-example',\n templateUrl: './platform-icon-tab-bar-filter-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarFilterTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", - "html": "\n" - }, { "name": "platform-icon-tab-bar-icon-only-type-example", "description": "Platform Icon Tab Bar Icon Only Type", "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-icon-only-type-example',\n templateUrl: './platform-icon-tab-bar-icon-only-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarIconOnlyTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", "html": "\n" }, + { + "name": "platform-icon-tab-bar-filter-type-example", + "description": "Platform Icon Tab Bar Filter Type", + "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-filter-type-example',\n templateUrl: './platform-icon-tab-bar-filter-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarFilterTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", + "html": "\n" + }, { "name": "platform-icon-tab-bar-icon-type-example", "description": "Platform Icon Tab Bar Icon Type", @@ -57827,18 +57893,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { textTypeConfig } from '../config-for-examples/text-type.config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-dynamic-overflow-example',\n templateUrl: './platform-icon-tab-bar-dynamic-overflow-example.component.html',\n imports: [IconTabBarComponent, ButtonComponent]\n})\nexport class PlatformIconTabBarDynamicOverflowExampleComponent {\n items: TabConfig[] = structuredClone(textTypeConfig);\n\n /** Whether the long labels variant is active. */\n useLongLabels = false;\n\n /** Toggle tab labels between short and long text to simulate a structure change (e.g. language switch). */\n toggleLabels(): void {\n this.useLongLabels = !this.useLongLabels;\n const base = structuredClone(textTypeConfig);\n if (this.useLongLabels) {\n base.forEach((item) => {\n item.label = `Very Long Label For ${item.label} With Extra Text`;\n });\n }\n this.items = base;\n }\n\n /** Add five more tabs dynamically to force overflow. */\n addMoreTabs(): void {\n const startIndex = this.items.length;\n const extra: TabConfig[] = Array.from({ length: 5 }, (_, i) => ({\n label: `New Tab ${startIndex + i}`,\n counter: Math.floor(Math.random() * 100),\n color: null\n }));\n this.items = [...this.items, ...extra];\n }\n}\n", "html": "
    \n \n \n
    \n\n\n" }, - { - "name": "platform-icon-tab-bar-filter-type-example", - "description": "Platform Icon Tab Bar Filter Type", - "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-filter-type-example',\n templateUrl: './platform-icon-tab-bar-filter-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarFilterTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", - "html": "\n" - }, { "name": "platform-icon-tab-bar-icon-only-type-example", "description": "Platform Icon Tab Bar Icon Only Type", "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-icon-only-type-example',\n templateUrl: './platform-icon-tab-bar-icon-only-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarIconOnlyTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", "html": "\n" }, + { + "name": "platform-icon-tab-bar-filter-type-example", + "description": "Platform Icon Tab Bar Filter Type", + "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-filter-type-example',\n templateUrl: './platform-icon-tab-bar-filter-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarFilterTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", + "html": "\n" + }, { "name": "platform-icon-tab-bar-icon-type-example", "description": "Platform Icon Tab Bar Icon Type", @@ -57987,18 +58053,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { textTypeConfig } from '../config-for-examples/text-type.config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-dynamic-overflow-example',\n templateUrl: './platform-icon-tab-bar-dynamic-overflow-example.component.html',\n imports: [IconTabBarComponent, ButtonComponent]\n})\nexport class PlatformIconTabBarDynamicOverflowExampleComponent {\n items: TabConfig[] = structuredClone(textTypeConfig);\n\n /** Whether the long labels variant is active. */\n useLongLabels = false;\n\n /** Toggle tab labels between short and long text to simulate a structure change (e.g. language switch). */\n toggleLabels(): void {\n this.useLongLabels = !this.useLongLabels;\n const base = structuredClone(textTypeConfig);\n if (this.useLongLabels) {\n base.forEach((item) => {\n item.label = `Very Long Label For ${item.label} With Extra Text`;\n });\n }\n this.items = base;\n }\n\n /** Add five more tabs dynamically to force overflow. */\n addMoreTabs(): void {\n const startIndex = this.items.length;\n const extra: TabConfig[] = Array.from({ length: 5 }, (_, i) => ({\n label: `New Tab ${startIndex + i}`,\n counter: Math.floor(Math.random() * 100),\n color: null\n }));\n this.items = [...this.items, ...extra];\n }\n}\n", "html": "
    \n \n \n
    \n\n\n" }, - { - "name": "platform-icon-tab-bar-filter-type-example", - "description": "Platform Icon Tab Bar Filter Type", - "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-filter-type-example',\n templateUrl: './platform-icon-tab-bar-filter-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarFilterTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", - "html": "\n" - }, { "name": "platform-icon-tab-bar-icon-only-type-example", "description": "Platform Icon Tab Bar Icon Only Type", "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-icon-only-type-example',\n templateUrl: './platform-icon-tab-bar-icon-only-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarIconOnlyTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", "html": "\n" }, + { + "name": "platform-icon-tab-bar-filter-type-example", + "description": "Platform Icon Tab Bar Filter Type", + "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-filter-type-example',\n templateUrl: './platform-icon-tab-bar-filter-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarFilterTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", + "html": "\n" + }, { "name": "platform-icon-tab-bar-icon-type-example", "description": "Platform Icon Tab Bar Icon Type", @@ -58116,18 +58182,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { textTypeConfig } from '../config-for-examples/text-type.config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-dynamic-overflow-example',\n templateUrl: './platform-icon-tab-bar-dynamic-overflow-example.component.html',\n imports: [IconTabBarComponent, ButtonComponent]\n})\nexport class PlatformIconTabBarDynamicOverflowExampleComponent {\n items: TabConfig[] = structuredClone(textTypeConfig);\n\n /** Whether the long labels variant is active. */\n useLongLabels = false;\n\n /** Toggle tab labels between short and long text to simulate a structure change (e.g. language switch). */\n toggleLabels(): void {\n this.useLongLabels = !this.useLongLabels;\n const base = structuredClone(textTypeConfig);\n if (this.useLongLabels) {\n base.forEach((item) => {\n item.label = `Very Long Label For ${item.label} With Extra Text`;\n });\n }\n this.items = base;\n }\n\n /** Add five more tabs dynamically to force overflow. */\n addMoreTabs(): void {\n const startIndex = this.items.length;\n const extra: TabConfig[] = Array.from({ length: 5 }, (_, i) => ({\n label: `New Tab ${startIndex + i}`,\n counter: Math.floor(Math.random() * 100),\n color: null\n }));\n this.items = [...this.items, ...extra];\n }\n}\n", "html": "
    \n \n \n
    \n\n\n" }, - { - "name": "platform-icon-tab-bar-filter-type-example", - "description": "Platform Icon Tab Bar Filter Type", - "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-filter-type-example',\n templateUrl: './platform-icon-tab-bar-filter-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarFilterTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", - "html": "\n" - }, { "name": "platform-icon-tab-bar-icon-only-type-example", "description": "Platform Icon Tab Bar Icon Only Type", "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-icon-only-type-example',\n templateUrl: './platform-icon-tab-bar-icon-only-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarIconOnlyTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", "html": "\n" }, + { + "name": "platform-icon-tab-bar-filter-type-example", + "description": "Platform Icon Tab Bar Filter Type", + "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-filter-type-example',\n templateUrl: './platform-icon-tab-bar-filter-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarFilterTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", + "html": "\n" + }, { "name": "platform-icon-tab-bar-icon-type-example", "description": "Platform Icon Tab Bar Icon Type", @@ -58259,18 +58325,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { textTypeConfig } from '../config-for-examples/text-type.config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-dynamic-overflow-example',\n templateUrl: './platform-icon-tab-bar-dynamic-overflow-example.component.html',\n imports: [IconTabBarComponent, ButtonComponent]\n})\nexport class PlatformIconTabBarDynamicOverflowExampleComponent {\n items: TabConfig[] = structuredClone(textTypeConfig);\n\n /** Whether the long labels variant is active. */\n useLongLabels = false;\n\n /** Toggle tab labels between short and long text to simulate a structure change (e.g. language switch). */\n toggleLabels(): void {\n this.useLongLabels = !this.useLongLabels;\n const base = structuredClone(textTypeConfig);\n if (this.useLongLabels) {\n base.forEach((item) => {\n item.label = `Very Long Label For ${item.label} With Extra Text`;\n });\n }\n this.items = base;\n }\n\n /** Add five more tabs dynamically to force overflow. */\n addMoreTabs(): void {\n const startIndex = this.items.length;\n const extra: TabConfig[] = Array.from({ length: 5 }, (_, i) => ({\n label: `New Tab ${startIndex + i}`,\n counter: Math.floor(Math.random() * 100),\n color: null\n }));\n this.items = [...this.items, ...extra];\n }\n}\n", "html": "
    \n \n \n
    \n\n\n" }, - { - "name": "platform-icon-tab-bar-filter-type-example", - "description": "Platform Icon Tab Bar Filter Type", - "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-filter-type-example',\n templateUrl: './platform-icon-tab-bar-filter-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarFilterTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", - "html": "\n" - }, { "name": "platform-icon-tab-bar-icon-only-type-example", "description": "Platform Icon Tab Bar Icon Only Type", "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-icon-only-type-example',\n templateUrl: './platform-icon-tab-bar-icon-only-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarIconOnlyTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", "html": "\n" }, + { + "name": "platform-icon-tab-bar-filter-type-example", + "description": "Platform Icon Tab Bar Filter Type", + "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-filter-type-example',\n templateUrl: './platform-icon-tab-bar-filter-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarFilterTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", + "html": "\n" + }, { "name": "platform-icon-tab-bar-icon-type-example", "description": "Platform Icon Tab Bar Icon Type", @@ -58360,18 +58426,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { textTypeConfig } from '../config-for-examples/text-type.config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-dynamic-overflow-example',\n templateUrl: './platform-icon-tab-bar-dynamic-overflow-example.component.html',\n imports: [IconTabBarComponent, ButtonComponent]\n})\nexport class PlatformIconTabBarDynamicOverflowExampleComponent {\n items: TabConfig[] = structuredClone(textTypeConfig);\n\n /** Whether the long labels variant is active. */\n useLongLabels = false;\n\n /** Toggle tab labels between short and long text to simulate a structure change (e.g. language switch). */\n toggleLabels(): void {\n this.useLongLabels = !this.useLongLabels;\n const base = structuredClone(textTypeConfig);\n if (this.useLongLabels) {\n base.forEach((item) => {\n item.label = `Very Long Label For ${item.label} With Extra Text`;\n });\n }\n this.items = base;\n }\n\n /** Add five more tabs dynamically to force overflow. */\n addMoreTabs(): void {\n const startIndex = this.items.length;\n const extra: TabConfig[] = Array.from({ length: 5 }, (_, i) => ({\n label: `New Tab ${startIndex + i}`,\n counter: Math.floor(Math.random() * 100),\n color: null\n }));\n this.items = [...this.items, ...extra];\n }\n}\n", "html": "
    \n \n \n
    \n\n\n" }, - { - "name": "platform-icon-tab-bar-filter-type-example", - "description": "Platform Icon Tab Bar Filter Type", - "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-filter-type-example',\n templateUrl: './platform-icon-tab-bar-filter-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarFilterTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", - "html": "\n" - }, { "name": "platform-icon-tab-bar-icon-only-type-example", "description": "Platform Icon Tab Bar Icon Only Type", "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-icon-only-type-example',\n templateUrl: './platform-icon-tab-bar-icon-only-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarIconOnlyTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", "html": "\n" }, + { + "name": "platform-icon-tab-bar-filter-type-example", + "description": "Platform Icon Tab Bar Filter Type", + "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-filter-type-example',\n templateUrl: './platform-icon-tab-bar-filter-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarFilterTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", + "html": "\n" + }, { "name": "platform-icon-tab-bar-icon-type-example", "description": "Platform Icon Tab Bar Icon Type", @@ -58514,18 +58580,18 @@ "typescript": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { textTypeConfig } from '../config-for-examples/text-type.config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-dynamic-overflow-example',\n templateUrl: './platform-icon-tab-bar-dynamic-overflow-example.component.html',\n imports: [IconTabBarComponent, ButtonComponent]\n})\nexport class PlatformIconTabBarDynamicOverflowExampleComponent {\n items: TabConfig[] = structuredClone(textTypeConfig);\n\n /** Whether the long labels variant is active. */\n useLongLabels = false;\n\n /** Toggle tab labels between short and long text to simulate a structure change (e.g. language switch). */\n toggleLabels(): void {\n this.useLongLabels = !this.useLongLabels;\n const base = structuredClone(textTypeConfig);\n if (this.useLongLabels) {\n base.forEach((item) => {\n item.label = `Very Long Label For ${item.label} With Extra Text`;\n });\n }\n this.items = base;\n }\n\n /** Add five more tabs dynamically to force overflow. */\n addMoreTabs(): void {\n const startIndex = this.items.length;\n const extra: TabConfig[] = Array.from({ length: 5 }, (_, i) => ({\n label: `New Tab ${startIndex + i}`,\n counter: Math.floor(Math.random() * 100),\n color: null\n }));\n this.items = [...this.items, ...extra];\n }\n}\n", "html": "
    \n \n \n
    \n\n\n" }, - { - "name": "platform-icon-tab-bar-filter-type-example", - "description": "Platform Icon Tab Bar Filter Type", - "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-filter-type-example',\n templateUrl: './platform-icon-tab-bar-filter-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarFilterTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", - "html": "\n" - }, { "name": "platform-icon-tab-bar-icon-only-type-example", "description": "Platform Icon Tab Bar Icon Only Type", "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-icon-only-type-example',\n templateUrl: './platform-icon-tab-bar-icon-only-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarIconOnlyTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", "html": "\n" }, + { + "name": "platform-icon-tab-bar-filter-type-example", + "description": "Platform Icon Tab Bar Filter Type", + "typescript": "import { Component, Input, OnInit } from '@angular/core';\nimport { IconTabBarComponent, TabConfig } from '@fundamental-ngx/platform/icon-tab-bar';\nimport { iconTypeConfig, longIconTypeConfig } from '../config-for-examples/icon-type-config';\n\n@Component({\n selector: 'fdp-platform-icon-tab-bar-filter-type-example',\n templateUrl: './platform-icon-tab-bar-filter-type-example.component.html',\n imports: [IconTabBarComponent]\n})\nexport class PlatformIconTabBarFilterTypeExampleComponent implements OnInit {\n @Input()\n withOverflowExample = false;\n\n items: TabConfig[];\n\n ngOnInit(): void {\n this.items = this.withOverflowExample ? structuredClone(longIconTypeConfig) : structuredClone(iconTypeConfig);\n }\n}\n", + "html": "\n" + }, { "name": "platform-icon-tab-bar-icon-type-example", "description": "Platform Icon Tab Bar Icon Type", @@ -60720,12 +60786,6 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { of } from 'rxjs';\n\nimport { JsonPipe } from '@angular/common';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n FdpFormGroupModule,\n MultiComboboxSelectionChangeEvent,\n PlatformMultiComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { ArrayComboBoxDataSource, DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\n\n@Component({\n selector: 'fdp-multi-combobox-datasource-example',\n templateUrl: './multi-combobox-datasource-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, PlatformMultiComboboxModule, ButtonComponent, JsonPipe]\n})\nexport class MultiComboboxDatasourceExampleComponent {\n isLimitless = true;\n\n dataSourceStrings = [\n '10 Apple',\n '20 Banana',\n '30 Pineapple',\n '40 Strawberry',\n 'Broccoli',\n 'Carrot',\n 'Jalapeño',\n 'Spinach'\n ];\n\n dataSource = [\n { id: '1', name: 'Apple', type: 'Fruits' },\n { id: '2', name: 'Pineapple', type: 'Fruits' },\n { id: '3', name: 'Strawberry', type: 'Fruits' },\n { id: '4', name: 'Broccoli', type: 'Vegetables' },\n { id: '5', name: 'Carrot', type: 'Vegetables' },\n { id: '6', name: 'Jalapeño', type: 'Vegetables' },\n { id: '7', name: 'Spinach', type: 'Vegetables' },\n { id: '8', name: 'Ukraine', type: 'Countries' },\n { id: '9', name: 'Georgia', type: 'Countries' },\n { id: '10', name: 'Poland', type: 'Countries' },\n { id: '11', name: 'Finland', type: 'Countries' },\n { id: '12', name: 'Denmark', type: 'Countries' },\n { id: '13', name: 'Sweden', type: 'Countries' },\n { id: '14', name: 'Lietuva', type: 'Countries' },\n { id: '15', name: 'Latvia', type: 'Countries' },\n { id: '16', name: 'Spain', type: 'Countries' },\n { id: '17', name: 'Switzerland', type: 'Countries' },\n { id: '18', name: 'USA', type: 'Countries' },\n { id: '19', name: 'Turkey', type: 'Countries' },\n { id: '20', name: 'Italy', type: 'Countries' },\n { id: '21', name: 'Azerbaijan', type: 'Countries' },\n { id: '22', name: 'Germany', type: 'Countries' },\n { id: '23', name: 'Audi', type: 'Cars' },\n { id: '24', name: 'Mercedes', type: 'Cars' },\n { id: '25', name: 'Tesla', type: 'Cars' },\n { id: '26', name: 'Porsche', type: 'Cars' },\n { id: '27', name: 'Toyota', type: 'Cars' },\n { id: '28', name: 'Ford', type: 'Cars' },\n { id: '29', name: 'Grapes', type: 'Fruits' },\n { id: '30', name: 'Watermelon', type: 'Fruits' },\n { id: '31', name: 'Orange', type: 'Fruits' },\n { id: '32', name: 'Cucumber', type: 'Vegetables' },\n { id: '33', name: 'Lettuce', type: 'Vegetables' },\n { id: '34', name: 'Potato', type: 'Vegetables' },\n { id: '35', name: 'Tomato', type: 'Vegetables' },\n { id: '36', name: 'China', type: 'Countries' },\n { id: '37', name: 'Japan', type: 'Countries' },\n { id: '38', name: 'Brazil', type: 'Countries' },\n { id: '39', name: 'Russia', type: 'Countries' },\n { id: '40', name: 'India', type: 'Countries' },\n { id: '41', name: 'Mexico', type: 'Countries' },\n { id: '42', name: 'Egypt', type: 'Countries' },\n { id: '43', name: 'Australia', type: 'Countries' },\n { id: '44', name: 'Netherlands', type: 'Countries' },\n { id: '45', name: 'Belgium', type: 'Countries' },\n { id: '46', name: 'UK', type: 'Countries' },\n { id: '47', name: 'France', type: 'Countries' },\n { id: '48', name: 'South Korea', type: 'Countries' },\n { id: '49', name: 'Malaysia', type: 'Countries' },\n { id: '50', name: 'Singapore', type: 'Countries' },\n { id: '51', name: 'Honda', type: 'Cars' },\n { id: '52', name: 'BMW', type: 'Cars' },\n { id: '53', name: 'Lamborghini', type: 'Cars' },\n { id: '54', name: 'Ferrari', type: 'Cars' },\n { id: '55', name: 'Chevrolet', type: 'Cars' },\n { id: '56', name: 'Mazda', type: 'Cars' },\n { id: '57', name: 'Cherry', type: 'Fruits' },\n { id: '58', name: 'Mango', type: 'Fruits' },\n { id: '59', name: 'Pear', type: 'Fruits' },\n { id: '60', name: 'Avocado', type: 'Fruits' },\n { id: '61', name: 'Cabbage', type: 'Vegetables' },\n { id: '62', name: 'Onion', type: 'Vegetables' },\n { id: '63', name: 'Garlic', type: 'Vegetables' },\n { id: '64', name: 'Pepper', type: 'Vegetables' },\n { id: '65', name: 'Germany', type: 'Countries' },\n { id: '66', name: 'France', type: 'Countries' },\n { id: '67', name: 'Spain', type: 'Countries' },\n { id: '68', name: 'Italy', type: 'Countries' },\n { id: '69', name: 'UK', type: 'Countries' },\n { id: '70', name: 'USA', type: 'Countries' },\n { id: '71', name: 'China', type: 'Countries' },\n { id: '72', name: 'Japan', type: 'Countries' },\n { id: '73', name: 'Brazil', type: 'Countries' },\n { id: '74', name: 'Russia', type: 'Countries' },\n { id: '75', name: 'India', type: 'Countries' },\n { id: '76', name: 'Mexico', type: 'Countries' },\n { id: '77', name: 'Egypt', type: 'Countries' },\n { id: '78', name: 'Australia', type: 'Countries' },\n { id: '79', name: 'Netherlands', type: 'Countries' },\n { id: '80', name: 'Belgium', type: 'Countries' },\n { id: '81', name: 'South Korea', type: 'Countries' },\n { id: '82', name: 'Malaysia', type: 'Countries' },\n { id: '83', name: 'Singapore', type: 'Countries' },\n { id: '84', name: 'Honda', type: 'Cars' },\n { id: '85', name: 'BMW', type: 'Cars' },\n { id: '86', name: 'Lamborghini', type: 'Cars' },\n { id: '87', name: 'Ferrari', type: 'Cars' },\n { id: '88', name: 'Chevrolet', type: 'Cars' },\n { id: '89', name: 'Mazda', type: 'Cars' },\n { id: '90', name: 'Grapes', type: 'Fruits' },\n { id: '91', name: 'Watermelon', type: 'Fruits' },\n { id: '92', name: 'Orange', type: 'Fruits' },\n { id: '93', name: 'Cucumber', type: 'Vegetables' },\n { id: '94', name: 'Lettuce', type: 'Vegetables' },\n { id: '95', name: 'Potato', type: 'Vegetables' },\n { id: '96', name: 'Tomato', type: 'Vegetables' },\n { id: '97', name: 'Ukraine', type: 'Countries' },\n { id: '98', name: 'Georgia', type: 'Countries' },\n { id: '99', name: 'Poland', type: 'Countries' },\n { id: '100', name: 'Finland', type: 'Countries' }\n ];\n\n dataSourceOf = of(this.dataSource);\n ds = new ArrayComboBoxDataSource(this.dataSource);\n dsl = new ArrayComboBoxDataSource(this.dataSource);\n\n selectedItems1 = [this.dataSourceStrings[1]];\n selectedItems2 = [this.dataSource[1]];\n selectedItems3 = [];\n selectedItems4 = [];\n selectedItems5 = [\n this.dataSourceStrings[1],\n this.dataSourceStrings[2],\n this.dataSourceStrings[3],\n this.dataSourceStrings[4]\n ];\n selectedItems6 = [];\n\n onSelect1(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems1 = item.selectedItems;\n }\n\n onSelect2(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems2 = item.selectedItems;\n }\n\n onSelect3(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems3 = item.selectedItems;\n }\n\n onSelect4(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems4 = item.selectedItems;\n }\n\n onSelect5(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems5 = item.selectedItems;\n }\n\n onSelect6(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems6 = item.selectedItems;\n }\n}\n", "html": "\n \n \n

    Selected: {{ selectedItems1 }}

    \n
    \n\n \n \n

    Selected: {{ selectedItems2 | json }}

    \n
    \n\n \n \n

    Selected: {{ selectedItems3 | json }}

    \n
    \n\n \n \n

    Selected: {{ selectedItems4 | json }}

    \n
    \n\n \n \n

    Limitless: {{ isLimitless }}

    \n

    Selected: {{ selectedItems6 | json }}

    \n \n
    \n\n \n \n

    Selected: {{ selectedItems5 }}

    \n
    \n
    \n" }, - { - "name": "multi-combobox-forms-example", - "description": "Multi Combobox Forms", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';\n\nimport { JsonPipe } from '@angular/common';\nimport {\n FdpFormGroupModule,\n MultiComboboxSelectionChangeEvent,\n PlatformMultiComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\n\n@Component({\n selector: 'fdp-multi-combobox-forms-example',\n templateUrl: './multi-combobox-forms-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, FormsModule, ReactiveFormsModule, PlatformMultiComboboxModule, JsonPipe]\n})\nexport class MultiComboboxFormsExampleComponent {\n dataSource = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n ];\n\n customForm = new FormGroup({\n field: new FormControl(this.dataSource[3])\n });\n\n selectedItems = [this.dataSource[3]];\n\n onSelect(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems = item.selectedItems;\n }\n}\n", - "html": "\n \n \n

    Selected Item: {{ selectedItems | json }}

    \n

    Form Selected Item: {{ customForm.getRawValue() | json }}

    \n

    Dirty: {{ customForm.controls.field.dirty }}

    \n

    Touched: {{ customForm.controls.field.touched }}

    \n

    Pristine: {{ customForm.controls.field.pristine }}

    \n
    \n
    \n" - }, { "name": "multi-combobox-group-example", "description": "Multi Combobox Group", @@ -60738,6 +60798,12 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { BaseDataProvider, MultiComboBoxDataSource } from '@fundamental-ngx/platform/shared';\n\nimport { JsonPipe } from '@angular/common';\nimport { BusyIndicatorComponent } from '@fundamental-ngx/core/busy-indicator';\nimport {\n FdpFormGroupModule,\n MultiComboboxSelectionChangeEvent,\n PlatformMultiComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { Observable } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\nconst OPTIONS = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n];\n\n@Component({\n selector: 'fdp-multi-combobox-loading-example',\n templateUrl: './multi-combobox-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [FdpFormGroupModule, BusyIndicatorComponent, PlatformMultiComboboxModule, JsonPipe]\n})\nexport class MultiComboboxLoadingExampleComponent {\n dataSource = new MultiComboBoxDataSource(new DelayedBaseDataProvider(OPTIONS));\n\n selectedItems = [];\n loading = false;\n\n onSelect(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems = item.selectedItems;\n }\n\n onDataRequested(): void {\n this.loading = true;\n }\n onDataReceived(): void {\n this.loading = false;\n }\n}\n\n// Simulating real http request by adding 300ms delay to the DataProvider's \"fetch\" method\nclass DelayedBaseDataProvider extends BaseDataProvider {\n fetch(params: Map): Observable {\n return super.fetch(params).pipe(delay(300));\n }\n}\n", "html": "\n \n \n \n

    Selected: {{ selectedItems | json }}

    \n
    \n
    \n
    \n" }, + { + "name": "multi-combobox-forms-example", + "description": "Multi Combobox Forms", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';\n\nimport { JsonPipe } from '@angular/common';\nimport {\n FdpFormGroupModule,\n MultiComboboxSelectionChangeEvent,\n PlatformMultiComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\n\n@Component({\n selector: 'fdp-multi-combobox-forms-example',\n templateUrl: './multi-combobox-forms-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, FormsModule, ReactiveFormsModule, PlatformMultiComboboxModule, JsonPipe]\n})\nexport class MultiComboboxFormsExampleComponent {\n dataSource = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n ];\n\n customForm = new FormGroup({\n field: new FormControl(this.dataSource[3])\n });\n\n selectedItems = [this.dataSource[3]];\n\n onSelect(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems = item.selectedItems;\n }\n}\n", + "html": "\n \n \n

    Selected Item: {{ selectedItems | json }}

    \n

    Form Selected Item: {{ customForm.getRawValue() | json }}

    \n

    Dirty: {{ customForm.controls.field.dirty }}

    \n

    Touched: {{ customForm.controls.field.touched }}

    \n

    Pristine: {{ customForm.controls.field.pristine }}

    \n
    \n
    \n" + }, { "name": "multi-combobox-mobile-example", "description": "Multi Combobox Mobile", @@ -60783,12 +60849,6 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { of } from 'rxjs';\n\nimport { JsonPipe } from '@angular/common';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport {\n FdpFormGroupModule,\n MultiComboboxSelectionChangeEvent,\n PlatformMultiComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { ArrayComboBoxDataSource, DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\n\n@Component({\n selector: 'fdp-multi-combobox-datasource-example',\n templateUrl: './multi-combobox-datasource-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, PlatformMultiComboboxModule, ButtonComponent, JsonPipe]\n})\nexport class MultiComboboxDatasourceExampleComponent {\n isLimitless = true;\n\n dataSourceStrings = [\n '10 Apple',\n '20 Banana',\n '30 Pineapple',\n '40 Strawberry',\n 'Broccoli',\n 'Carrot',\n 'Jalapeño',\n 'Spinach'\n ];\n\n dataSource = [\n { id: '1', name: 'Apple', type: 'Fruits' },\n { id: '2', name: 'Pineapple', type: 'Fruits' },\n { id: '3', name: 'Strawberry', type: 'Fruits' },\n { id: '4', name: 'Broccoli', type: 'Vegetables' },\n { id: '5', name: 'Carrot', type: 'Vegetables' },\n { id: '6', name: 'Jalapeño', type: 'Vegetables' },\n { id: '7', name: 'Spinach', type: 'Vegetables' },\n { id: '8', name: 'Ukraine', type: 'Countries' },\n { id: '9', name: 'Georgia', type: 'Countries' },\n { id: '10', name: 'Poland', type: 'Countries' },\n { id: '11', name: 'Finland', type: 'Countries' },\n { id: '12', name: 'Denmark', type: 'Countries' },\n { id: '13', name: 'Sweden', type: 'Countries' },\n { id: '14', name: 'Lietuva', type: 'Countries' },\n { id: '15', name: 'Latvia', type: 'Countries' },\n { id: '16', name: 'Spain', type: 'Countries' },\n { id: '17', name: 'Switzerland', type: 'Countries' },\n { id: '18', name: 'USA', type: 'Countries' },\n { id: '19', name: 'Turkey', type: 'Countries' },\n { id: '20', name: 'Italy', type: 'Countries' },\n { id: '21', name: 'Azerbaijan', type: 'Countries' },\n { id: '22', name: 'Germany', type: 'Countries' },\n { id: '23', name: 'Audi', type: 'Cars' },\n { id: '24', name: 'Mercedes', type: 'Cars' },\n { id: '25', name: 'Tesla', type: 'Cars' },\n { id: '26', name: 'Porsche', type: 'Cars' },\n { id: '27', name: 'Toyota', type: 'Cars' },\n { id: '28', name: 'Ford', type: 'Cars' },\n { id: '29', name: 'Grapes', type: 'Fruits' },\n { id: '30', name: 'Watermelon', type: 'Fruits' },\n { id: '31', name: 'Orange', type: 'Fruits' },\n { id: '32', name: 'Cucumber', type: 'Vegetables' },\n { id: '33', name: 'Lettuce', type: 'Vegetables' },\n { id: '34', name: 'Potato', type: 'Vegetables' },\n { id: '35', name: 'Tomato', type: 'Vegetables' },\n { id: '36', name: 'China', type: 'Countries' },\n { id: '37', name: 'Japan', type: 'Countries' },\n { id: '38', name: 'Brazil', type: 'Countries' },\n { id: '39', name: 'Russia', type: 'Countries' },\n { id: '40', name: 'India', type: 'Countries' },\n { id: '41', name: 'Mexico', type: 'Countries' },\n { id: '42', name: 'Egypt', type: 'Countries' },\n { id: '43', name: 'Australia', type: 'Countries' },\n { id: '44', name: 'Netherlands', type: 'Countries' },\n { id: '45', name: 'Belgium', type: 'Countries' },\n { id: '46', name: 'UK', type: 'Countries' },\n { id: '47', name: 'France', type: 'Countries' },\n { id: '48', name: 'South Korea', type: 'Countries' },\n { id: '49', name: 'Malaysia', type: 'Countries' },\n { id: '50', name: 'Singapore', type: 'Countries' },\n { id: '51', name: 'Honda', type: 'Cars' },\n { id: '52', name: 'BMW', type: 'Cars' },\n { id: '53', name: 'Lamborghini', type: 'Cars' },\n { id: '54', name: 'Ferrari', type: 'Cars' },\n { id: '55', name: 'Chevrolet', type: 'Cars' },\n { id: '56', name: 'Mazda', type: 'Cars' },\n { id: '57', name: 'Cherry', type: 'Fruits' },\n { id: '58', name: 'Mango', type: 'Fruits' },\n { id: '59', name: 'Pear', type: 'Fruits' },\n { id: '60', name: 'Avocado', type: 'Fruits' },\n { id: '61', name: 'Cabbage', type: 'Vegetables' },\n { id: '62', name: 'Onion', type: 'Vegetables' },\n { id: '63', name: 'Garlic', type: 'Vegetables' },\n { id: '64', name: 'Pepper', type: 'Vegetables' },\n { id: '65', name: 'Germany', type: 'Countries' },\n { id: '66', name: 'France', type: 'Countries' },\n { id: '67', name: 'Spain', type: 'Countries' },\n { id: '68', name: 'Italy', type: 'Countries' },\n { id: '69', name: 'UK', type: 'Countries' },\n { id: '70', name: 'USA', type: 'Countries' },\n { id: '71', name: 'China', type: 'Countries' },\n { id: '72', name: 'Japan', type: 'Countries' },\n { id: '73', name: 'Brazil', type: 'Countries' },\n { id: '74', name: 'Russia', type: 'Countries' },\n { id: '75', name: 'India', type: 'Countries' },\n { id: '76', name: 'Mexico', type: 'Countries' },\n { id: '77', name: 'Egypt', type: 'Countries' },\n { id: '78', name: 'Australia', type: 'Countries' },\n { id: '79', name: 'Netherlands', type: 'Countries' },\n { id: '80', name: 'Belgium', type: 'Countries' },\n { id: '81', name: 'South Korea', type: 'Countries' },\n { id: '82', name: 'Malaysia', type: 'Countries' },\n { id: '83', name: 'Singapore', type: 'Countries' },\n { id: '84', name: 'Honda', type: 'Cars' },\n { id: '85', name: 'BMW', type: 'Cars' },\n { id: '86', name: 'Lamborghini', type: 'Cars' },\n { id: '87', name: 'Ferrari', type: 'Cars' },\n { id: '88', name: 'Chevrolet', type: 'Cars' },\n { id: '89', name: 'Mazda', type: 'Cars' },\n { id: '90', name: 'Grapes', type: 'Fruits' },\n { id: '91', name: 'Watermelon', type: 'Fruits' },\n { id: '92', name: 'Orange', type: 'Fruits' },\n { id: '93', name: 'Cucumber', type: 'Vegetables' },\n { id: '94', name: 'Lettuce', type: 'Vegetables' },\n { id: '95', name: 'Potato', type: 'Vegetables' },\n { id: '96', name: 'Tomato', type: 'Vegetables' },\n { id: '97', name: 'Ukraine', type: 'Countries' },\n { id: '98', name: 'Georgia', type: 'Countries' },\n { id: '99', name: 'Poland', type: 'Countries' },\n { id: '100', name: 'Finland', type: 'Countries' }\n ];\n\n dataSourceOf = of(this.dataSource);\n ds = new ArrayComboBoxDataSource(this.dataSource);\n dsl = new ArrayComboBoxDataSource(this.dataSource);\n\n selectedItems1 = [this.dataSourceStrings[1]];\n selectedItems2 = [this.dataSource[1]];\n selectedItems3 = [];\n selectedItems4 = [];\n selectedItems5 = [\n this.dataSourceStrings[1],\n this.dataSourceStrings[2],\n this.dataSourceStrings[3],\n this.dataSourceStrings[4]\n ];\n selectedItems6 = [];\n\n onSelect1(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems1 = item.selectedItems;\n }\n\n onSelect2(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems2 = item.selectedItems;\n }\n\n onSelect3(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems3 = item.selectedItems;\n }\n\n onSelect4(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems4 = item.selectedItems;\n }\n\n onSelect5(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems5 = item.selectedItems;\n }\n\n onSelect6(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems6 = item.selectedItems;\n }\n}\n", "html": "\n \n \n

    Selected: {{ selectedItems1 }}

    \n
    \n\n \n \n

    Selected: {{ selectedItems2 | json }}

    \n
    \n\n \n \n

    Selected: {{ selectedItems3 | json }}

    \n
    \n\n \n \n

    Selected: {{ selectedItems4 | json }}

    \n
    \n\n \n \n

    Limitless: {{ isLimitless }}

    \n

    Selected: {{ selectedItems6 | json }}

    \n \n
    \n\n \n \n

    Selected: {{ selectedItems5 }}

    \n
    \n
    \n" }, - { - "name": "multi-combobox-forms-example", - "description": "Multi Combobox Forms", - "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';\n\nimport { JsonPipe } from '@angular/common';\nimport {\n FdpFormGroupModule,\n MultiComboboxSelectionChangeEvent,\n PlatformMultiComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\n\n@Component({\n selector: 'fdp-multi-combobox-forms-example',\n templateUrl: './multi-combobox-forms-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, FormsModule, ReactiveFormsModule, PlatformMultiComboboxModule, JsonPipe]\n})\nexport class MultiComboboxFormsExampleComponent {\n dataSource = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n ];\n\n customForm = new FormGroup({\n field: new FormControl(this.dataSource[3])\n });\n\n selectedItems = [this.dataSource[3]];\n\n onSelect(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems = item.selectedItems;\n }\n}\n", - "html": "\n \n \n

    Selected Item: {{ selectedItems | json }}

    \n

    Form Selected Item: {{ customForm.getRawValue() | json }}

    \n

    Dirty: {{ customForm.controls.field.dirty }}

    \n

    Touched: {{ customForm.controls.field.touched }}

    \n

    Pristine: {{ customForm.controls.field.pristine }}

    \n
    \n
    \n" - }, { "name": "multi-combobox-group-example", "description": "Multi Combobox Group", @@ -60801,6 +60861,12 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { BaseDataProvider, MultiComboBoxDataSource } from '@fundamental-ngx/platform/shared';\n\nimport { JsonPipe } from '@angular/common';\nimport { BusyIndicatorComponent } from '@fundamental-ngx/core/busy-indicator';\nimport {\n FdpFormGroupModule,\n MultiComboboxSelectionChangeEvent,\n PlatformMultiComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { Observable } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\nconst OPTIONS = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n];\n\n@Component({\n selector: 'fdp-multi-combobox-loading-example',\n templateUrl: './multi-combobox-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [FdpFormGroupModule, BusyIndicatorComponent, PlatformMultiComboboxModule, JsonPipe]\n})\nexport class MultiComboboxLoadingExampleComponent {\n dataSource = new MultiComboBoxDataSource(new DelayedBaseDataProvider(OPTIONS));\n\n selectedItems = [];\n loading = false;\n\n onSelect(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems = item.selectedItems;\n }\n\n onDataRequested(): void {\n this.loading = true;\n }\n onDataReceived(): void {\n this.loading = false;\n }\n}\n\n// Simulating real http request by adding 300ms delay to the DataProvider's \"fetch\" method\nclass DelayedBaseDataProvider extends BaseDataProvider {\n fetch(params: Map): Observable {\n return super.fetch(params).pipe(delay(300));\n }\n}\n", "html": "\n \n \n \n

    Selected: {{ selectedItems | json }}

    \n
    \n
    \n
    \n" }, + { + "name": "multi-combobox-forms-example", + "description": "Multi Combobox Forms", + "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';\n\nimport { JsonPipe } from '@angular/common';\nimport {\n FdpFormGroupModule,\n MultiComboboxSelectionChangeEvent,\n PlatformMultiComboboxModule\n} from '@fundamental-ngx/platform/form';\nimport { DATA_PROVIDERS } from '@fundamental-ngx/platform/shared';\n\n@Component({\n selector: 'fdp-multi-combobox-forms-example',\n templateUrl: './multi-combobox-forms-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: DATA_PROVIDERS, useValue: new Map() }],\n imports: [FdpFormGroupModule, FormsModule, ReactiveFormsModule, PlatformMultiComboboxModule, JsonPipe]\n})\nexport class MultiComboboxFormsExampleComponent {\n dataSource = [\n { name: 'Apple', type: 'Fruits' },\n { name: 'Banana', type: 'Fruits' },\n { name: 'Pineapple', type: 'Fruits' },\n { name: 'Strawberry', type: 'Fruits' },\n { name: 'Broccoli', type: 'Vegetables' },\n { name: 'Carrot', type: 'Vegetables' },\n { name: 'Jalapeño', type: 'Vegetables' },\n { name: 'Spinach', type: 'Vegetables' }\n ];\n\n customForm = new FormGroup({\n field: new FormControl(this.dataSource[3])\n });\n\n selectedItems = [this.dataSource[3]];\n\n onSelect(item: MultiComboboxSelectionChangeEvent): void {\n this.selectedItems = item.selectedItems;\n }\n}\n", + "html": "\n \n \n

    Selected Item: {{ selectedItems | json }}

    \n

    Form Selected Item: {{ customForm.getRawValue() | json }}

    \n

    Dirty: {{ customForm.controls.field.dirty }}

    \n

    Touched: {{ customForm.controls.field.touched }}

    \n

    Pristine: {{ customForm.controls.field.pristine }}

    \n
    \n
    \n" + }, { "name": "multi-combobox-mobile-example", "description": "Multi Combobox Mobile", @@ -63700,6 +63766,12 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';\n\nimport { JsonPipe } from '@angular/common';\nimport { FdpFormGroupModule, PlatformSelectModule } from '@fundamental-ngx/platform/form';\n\ninterface Country {\n id: number;\n name: string;\n region: string;\n}\n\n@Component({\n selector: 'fdp-platform-select-lookup-key-example',\n templateUrl: './platform-select-lookup-key-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [FdpFormGroupModule, ReactiveFormsModule, PlatformSelectModule, JsonPipe]\n})\nexport class PlatformSelectLookupKeyExampleComponent {\n countries: Country[] = [\n { id: 1, name: 'Germany', region: 'Europe' },\n { id: 2, name: 'France', region: 'Europe' },\n { id: 3, name: 'Japan', region: 'Asia' },\n { id: 4, name: 'Brazil', region: 'Americas' }\n ];\n\n form = new FormGroup({\n country: new FormControl({ id: 2, name: 'France', region: 'Europe' })\n });\n}\n", "html": "\n \n \n \n\n

    Form value: {{ form.get('country')?.value | json }}

    \n" }, + { + "name": "platform-select-none-example", + "description": "Platform Select None", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\n\nimport { JsonPipe } from '@angular/common';\nimport { FdpSelectionChangeEvent, PlatformSelectModule } from '@fundamental-ngx/platform/form';\nimport { OptionItem } from '@fundamental-ngx/platform/shared';\n\nexport class Fruit {\n id: string;\n name: string;\n age: number;\n\n constructor(id: string, name: string, age: number) {\n this.id = id;\n this.name = name;\n this.age = age;\n }\n}\n\n@Component({\n selector: 'fdp-platform-select-none-example',\n templateUrl: './platform-select-none-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [PlatformSelectModule, JsonPipe]\n})\nexport class PlatformSelectNoneExampleComponent {\n selectedValue: string;\n\n userList = [\n new Fruit('A', 'Apple', 10),\n new Fruit('B', 'orange', 70),\n new Fruit('C', 'Plums', 10),\n new Fruit('D', 'pineapple', 11),\n new Fruit('E', 'watermelon', 10)\n ];\n option = this.userList.map((item) => ({\n label: item.name + item.id,\n value: item.name,\n triggerValue: `(${item.id})`,\n icon: ''\n }));\n\n onSelect(item: FdpSelectionChangeEvent): void {\n if (item) {\n this.selectedValue = item.payload;\n }\n }\n}\n", + "html": "\n\nSelected value: {{ selectedValue | json }}\n" + }, { "name": "platform-select-mobile-example", "description": "Platform Select Mobile", @@ -63712,12 +63784,6 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { FdpSelectionChangeEvent, PlatformSelectModule, SelectOptionItem } from '@fundamental-ngx/platform/form';\n\nexport class Fruit {\n id: string;\n name: string;\n age: number;\n\n constructor(id: string, name: string, age: number) {\n this.id = id;\n this.name = name;\n this.age = age;\n }\n}\n\n@Component({\n selector: 'fdp-platform-select-mode-example',\n templateUrl: './platform-select-mode-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [PlatformSelectModule, ContentDensityDirective]\n})\nexport class PlatformSelectModeExampleComponent {\n userList = [\n new Fruit('A', 'Apple', 10),\n new Fruit('B', 'orange', 70),\n new Fruit('C', 'Plums', 10),\n new Fruit('D', 'pineapple', 11),\n new Fruit('E', 'watermelon', 10)\n ];\n option = this.userList.map((item) => ({\n label: item.name + item.id,\n value: item.name,\n disabled: item.id === 'B',\n icon: ''\n }));\n\n selectedValue1 = null;\n selectedValue3 = this.option[4].label;\n selectedValue4 = this.option[3].label;\n\n onSelect1(item: FdpSelectionChangeEvent): void {\n this.selectedValue1 = item.payload;\n }\n}\n", "html": "

    Default select

    \n \nSelected value: {{ selectedValue1 }}\n\n

    Select in disabled mode

    \n \nSelected value:{{ selectedValue3 }} \n\n

    Select in read-only mode

    \n \nSelected value: {{ selectedValue4 }}\n" }, - { - "name": "platform-select-none-example", - "description": "Platform Select None", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\n\nimport { JsonPipe } from '@angular/common';\nimport { FdpSelectionChangeEvent, PlatformSelectModule } from '@fundamental-ngx/platform/form';\nimport { OptionItem } from '@fundamental-ngx/platform/shared';\n\nexport class Fruit {\n id: string;\n name: string;\n age: number;\n\n constructor(id: string, name: string, age: number) {\n this.id = id;\n this.name = name;\n this.age = age;\n }\n}\n\n@Component({\n selector: 'fdp-platform-select-none-example',\n templateUrl: './platform-select-none-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [PlatformSelectModule, JsonPipe]\n})\nexport class PlatformSelectNoneExampleComponent {\n selectedValue: string;\n\n userList = [\n new Fruit('A', 'Apple', 10),\n new Fruit('B', 'orange', 70),\n new Fruit('C', 'Plums', 10),\n new Fruit('D', 'pineapple', 11),\n new Fruit('E', 'watermelon', 10)\n ];\n option = this.userList.map((item) => ({\n label: item.name + item.id,\n value: item.name,\n triggerValue: `(${item.id})`,\n icon: ''\n }));\n\n onSelect(item: FdpSelectionChangeEvent): void {\n if (item) {\n this.selectedValue = item.payload;\n }\n }\n}\n", - "html": "\n\nSelected value: {{ selectedValue | json }}\n" - }, { "name": "platform-select-nowrap-example", "description": "Platform Select Nowrap", @@ -63864,6 +63930,12 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';\n\nimport { JsonPipe } from '@angular/common';\nimport { FdpFormGroupModule, PlatformSelectModule } from '@fundamental-ngx/platform/form';\n\ninterface Country {\n id: number;\n name: string;\n region: string;\n}\n\n@Component({\n selector: 'fdp-platform-select-lookup-key-example',\n templateUrl: './platform-select-lookup-key-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [FdpFormGroupModule, ReactiveFormsModule, PlatformSelectModule, JsonPipe]\n})\nexport class PlatformSelectLookupKeyExampleComponent {\n countries: Country[] = [\n { id: 1, name: 'Germany', region: 'Europe' },\n { id: 2, name: 'France', region: 'Europe' },\n { id: 3, name: 'Japan', region: 'Asia' },\n { id: 4, name: 'Brazil', region: 'Americas' }\n ];\n\n form = new FormGroup({\n country: new FormControl({ id: 2, name: 'France', region: 'Europe' })\n });\n}\n", "html": "\n \n \n \n\n

    Form value: {{ form.get('country')?.value | json }}

    \n" }, + { + "name": "platform-select-none-example", + "description": "Platform Select None", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\n\nimport { JsonPipe } from '@angular/common';\nimport { FdpSelectionChangeEvent, PlatformSelectModule } from '@fundamental-ngx/platform/form';\nimport { OptionItem } from '@fundamental-ngx/platform/shared';\n\nexport class Fruit {\n id: string;\n name: string;\n age: number;\n\n constructor(id: string, name: string, age: number) {\n this.id = id;\n this.name = name;\n this.age = age;\n }\n}\n\n@Component({\n selector: 'fdp-platform-select-none-example',\n templateUrl: './platform-select-none-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [PlatformSelectModule, JsonPipe]\n})\nexport class PlatformSelectNoneExampleComponent {\n selectedValue: string;\n\n userList = [\n new Fruit('A', 'Apple', 10),\n new Fruit('B', 'orange', 70),\n new Fruit('C', 'Plums', 10),\n new Fruit('D', 'pineapple', 11),\n new Fruit('E', 'watermelon', 10)\n ];\n option = this.userList.map((item) => ({\n label: item.name + item.id,\n value: item.name,\n triggerValue: `(${item.id})`,\n icon: ''\n }));\n\n onSelect(item: FdpSelectionChangeEvent): void {\n if (item) {\n this.selectedValue = item.payload;\n }\n }\n}\n", + "html": "\n\nSelected value: {{ selectedValue | json }}\n" + }, { "name": "platform-select-mobile-example", "description": "Platform Select Mobile", @@ -63876,12 +63948,6 @@ "typescript": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { ContentDensityDirective } from '@fundamental-ngx/core/content-density';\nimport { FdpSelectionChangeEvent, PlatformSelectModule, SelectOptionItem } from '@fundamental-ngx/platform/form';\n\nexport class Fruit {\n id: string;\n name: string;\n age: number;\n\n constructor(id: string, name: string, age: number) {\n this.id = id;\n this.name = name;\n this.age = age;\n }\n}\n\n@Component({\n selector: 'fdp-platform-select-mode-example',\n templateUrl: './platform-select-mode-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [PlatformSelectModule, ContentDensityDirective]\n})\nexport class PlatformSelectModeExampleComponent {\n userList = [\n new Fruit('A', 'Apple', 10),\n new Fruit('B', 'orange', 70),\n new Fruit('C', 'Plums', 10),\n new Fruit('D', 'pineapple', 11),\n new Fruit('E', 'watermelon', 10)\n ];\n option = this.userList.map((item) => ({\n label: item.name + item.id,\n value: item.name,\n disabled: item.id === 'B',\n icon: ''\n }));\n\n selectedValue1 = null;\n selectedValue3 = this.option[4].label;\n selectedValue4 = this.option[3].label;\n\n onSelect1(item: FdpSelectionChangeEvent): void {\n this.selectedValue1 = item.payload;\n }\n}\n", "html": "

    Default select

    \n \nSelected value: {{ selectedValue1 }}\n\n

    Select in disabled mode

    \n \nSelected value:{{ selectedValue3 }} \n\n

    Select in read-only mode

    \n \nSelected value: {{ selectedValue4 }}\n" }, - { - "name": "platform-select-none-example", - "description": "Platform Select None", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\n\nimport { JsonPipe } from '@angular/common';\nimport { FdpSelectionChangeEvent, PlatformSelectModule } from '@fundamental-ngx/platform/form';\nimport { OptionItem } from '@fundamental-ngx/platform/shared';\n\nexport class Fruit {\n id: string;\n name: string;\n age: number;\n\n constructor(id: string, name: string, age: number) {\n this.id = id;\n this.name = name;\n this.age = age;\n }\n}\n\n@Component({\n selector: 'fdp-platform-select-none-example',\n templateUrl: './platform-select-none-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [PlatformSelectModule, JsonPipe]\n})\nexport class PlatformSelectNoneExampleComponent {\n selectedValue: string;\n\n userList = [\n new Fruit('A', 'Apple', 10),\n new Fruit('B', 'orange', 70),\n new Fruit('C', 'Plums', 10),\n new Fruit('D', 'pineapple', 11),\n new Fruit('E', 'watermelon', 10)\n ];\n option = this.userList.map((item) => ({\n label: item.name + item.id,\n value: item.name,\n triggerValue: `(${item.id})`,\n icon: ''\n }));\n\n onSelect(item: FdpSelectionChangeEvent): void {\n if (item) {\n this.selectedValue = item.payload;\n }\n }\n}\n", - "html": "\n\nSelected value: {{ selectedValue | json }}\n" - }, { "name": "platform-select-nowrap-example", "description": "Platform Select Nowrap", @@ -66984,6 +67050,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule } from '@fundamental-ngx/platform/table';\nimport {\n ChildTableDataSource,\n CollectionNumberFilter,\n CollectionStringFilter,\n FdpTableDataSource,\n FilterType,\n FilterableColumnDataType,\n SortDirection,\n TableChildrenDataProvider,\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableRow,\n TableState,\n TableVirtualScrollDirective,\n TreeTableItem\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, of } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-doc-advanced-scrolling-example',\n templateUrl: './advanced-scrolling-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule\n ]\n})\nexport class AdvancedScrollingExampleComponent {\n source: TableDataSource;\n childSource: ChildTableDataSource;\n readonly filterTypeEnum = FilterType;\n readonly dataTypeEnum = FilterableColumnDataType;\n readonly selectOptions = ['Laptops 1 (Level 1)', 'Laptops 12 (Level 1)'];\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n this.childSource = new ChildTableDataSource(new ChildTableProviderExample());\n }\n}\n\nexport interface ExampleItem extends TreeTableItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n hasChildren: boolean;\n children?: FdpTableDataSource;\n}\n\nclass ChildTableProviderExample extends TableChildrenDataProvider {\n items: Map, ExampleItem[]> = new Map();\n totalItems = 200;\n startIndex = 0;\n allItemsMap = new Map, ExampleItem[]>();\n\n rowChildrenCount(row: TableRow): Observable {\n return of(this.totalItems);\n }\n\n /**\n * Unlike default dataSource, childDataSource accepts array of table rows as a second argument.\n * This is done to load child rows in bulk for the cases when multiple rows being expanded at the same time.\n * @param tableState\n * @param tableRows\n */\n fetch(\n tableState?: TableState,\n tableRows?: TableRow[]\n ): Observable, ExampleItem[]>> {\n const itemsMap = new Map, ExampleItem[]>();\n\n /** Logic of retrieving the child rows for a particular row in tableRows array. */\n tableRows?.forEach((row) => {\n let allItems = this.allItemsMap.get(row);\n const currentPage = tableState?.page.currentPage;\n if (!allItems) {\n allItems = generateItems(this.totalItems, row.level + 1);\n this.allItemsMap.set(row, allItems);\n }\n\n // apply searching\n if (tableState?.searchInput) {\n allItems = this.search(allItems, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n allItems = this.sort(allItems, tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n allItems = this.filter(allItems, tableState);\n }\n\n // Apply paging\n if (currentPage && tableState?.page) {\n const startIndex = (currentPage - 1) * tableState.page.pageSize;\n allItems = allItems.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n itemsMap.set(row, allItems);\n });\n\n return of(itemsMap).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort(items: ExampleItem[], { sortBy }: TableState): ExampleItem[] {\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 5000;\n startIndex = 0;\n allItems: ExampleItem[];\n\n constructor(public level = 0) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.allItems = this.allItems || generateItems(this.totalItems, this.level);\n this.items = [...this.allItems];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(this.items, tableState);\n }\n\n // Apply paging\n if (tableState?.page?.currentPage) {\n const startIndex = (tableState.page.currentPage - 1) * tableState.page.pageSize;\n this.items = this.items.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n return of(this.items).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\nfunction generateItems(size = 5000, level = 0, startIndex = 0): ExampleItem[] {\n return new Array(size).fill(null).map(() => ({\n name: `Laptops ${startIndex++} (Level ${level + 1})`,\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true,\n hasChildren: level < 2 ? true : false\n }));\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => (a ? a[b] : null), object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n", "html": "\n \n\n \n \n\n \n\n \n \n\n \n \n\n\n\n\n" }, + { + "name": "platform-table-initial-loading-example", + "description": "Platform Table Initial Loading", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", + "html": "\n \n\n \n\n \n\n \n\n" + }, + { + "name": "platform-table-editable-rows-example", + "description": "Platform Table Editable Rows", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", + "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" + }, { "name": "table-custom-pagination-example", "description": "Table Custom Pagination", @@ -66996,18 +67074,6 @@ "typescript": "import { ChangeDetectionStrategy, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { PlatformTableModule, TableComponent } from '@fundamental-ngx/platform/table';\nimport {\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableState,\n TableVirtualScrollDirective\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, delay, of } from 'rxjs';\n\n@Component({\n selector: 'fdp-table-custom-pagination-outer-scroll-example',\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule,\n PaginationModule\n ],\n templateUrl: './table-custom-pagination-outer-scroll-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class TableCustomPaginationOuterScrollExampleComponent implements OnInit {\n @ViewChild(TableComponent)\n table: TableComponent;\n\n source: TableDataSource;\n state: TableState;\n currentPage = 1;\n pageSize = 50;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n\n ngOnInit(): void {\n this.state = this._getDefaultState();\n }\n\n pageChanged(currentPage: number): void {\n this.currentPage = currentPage;\n this.table.setCurrentPage(this.currentPage);\n }\n\n itemsPerPageChanged(itemsPerPage: number): void {\n this.pageSize = itemsPerPage;\n this.table.setPageSize(this.pageSize, true);\n }\n\n /**\n * Simulating scroll position update. Once table is initialized app can set back preserved scrolling table\n * position so table can scroll it its original state.\n *\n * Note: Bellow scrollTopPosition property is set based on the scrolling position that was read from\n * this table example. Just some number to showcase this.\n */\n _getDefaultState(): TableState {\n return {\n columnKeys: [],\n sortBy: [],\n filterBy: [],\n groupBy: [],\n columns: [],\n searchInput: {\n category: null,\n text: ''\n },\n freezeToColumn: null,\n freezeToEndColumn: null,\n page: {\n pageSize: this.pageSize,\n currentPage: this.currentPage\n },\n scrollTopPosition: 0\n };\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n children?: ExampleItem[];\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [...ITEMS];\n totalItems = ITEMS.length;\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n this.totalItems = this.items.length;\n\n const currentPage = tableState?.page.currentPage || 1;\n const size = tableState?.page.pageSize || 50;\n const skip = (currentPage - 1) * size;\n\n const paginatedItems = this.items.slice(skip, size * currentPage);\n\n return of(paginatedItems).pipe(delay(1000));\n }\n}\n\n// Example items\nconst ITEMS: ExampleItem[] = new Array(5000).fill(null).map((_, index) => ({\n name: 'Laptops ' + index,\n price: {\n value: Math.floor(Math.random() * 1000),\n currency: 'USD'\n }\n}));\n", "html": "
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n


    \n \n \n \n\n \n\n \n\n \n\n \n \n
    \n" }, - { - "name": "platform-table-editable-rows-example", - "description": "Platform Table Editable Rows", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", - "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" - }, - { - "name": "platform-table-initial-loading-example", - "description": "Platform Table Initial Loading", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", - "html": "\n \n\n \n\n \n\n \n\n" - }, { "name": "platform-table-preserved-state-example", "description": "Platform Table Preserved State", @@ -67274,6 +67340,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule } from '@fundamental-ngx/platform/table';\nimport {\n ChildTableDataSource,\n CollectionNumberFilter,\n CollectionStringFilter,\n FdpTableDataSource,\n FilterType,\n FilterableColumnDataType,\n SortDirection,\n TableChildrenDataProvider,\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableRow,\n TableState,\n TableVirtualScrollDirective,\n TreeTableItem\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, of } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-doc-advanced-scrolling-example',\n templateUrl: './advanced-scrolling-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule\n ]\n})\nexport class AdvancedScrollingExampleComponent {\n source: TableDataSource;\n childSource: ChildTableDataSource;\n readonly filterTypeEnum = FilterType;\n readonly dataTypeEnum = FilterableColumnDataType;\n readonly selectOptions = ['Laptops 1 (Level 1)', 'Laptops 12 (Level 1)'];\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n this.childSource = new ChildTableDataSource(new ChildTableProviderExample());\n }\n}\n\nexport interface ExampleItem extends TreeTableItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n hasChildren: boolean;\n children?: FdpTableDataSource;\n}\n\nclass ChildTableProviderExample extends TableChildrenDataProvider {\n items: Map, ExampleItem[]> = new Map();\n totalItems = 200;\n startIndex = 0;\n allItemsMap = new Map, ExampleItem[]>();\n\n rowChildrenCount(row: TableRow): Observable {\n return of(this.totalItems);\n }\n\n /**\n * Unlike default dataSource, childDataSource accepts array of table rows as a second argument.\n * This is done to load child rows in bulk for the cases when multiple rows being expanded at the same time.\n * @param tableState\n * @param tableRows\n */\n fetch(\n tableState?: TableState,\n tableRows?: TableRow[]\n ): Observable, ExampleItem[]>> {\n const itemsMap = new Map, ExampleItem[]>();\n\n /** Logic of retrieving the child rows for a particular row in tableRows array. */\n tableRows?.forEach((row) => {\n let allItems = this.allItemsMap.get(row);\n const currentPage = tableState?.page.currentPage;\n if (!allItems) {\n allItems = generateItems(this.totalItems, row.level + 1);\n this.allItemsMap.set(row, allItems);\n }\n\n // apply searching\n if (tableState?.searchInput) {\n allItems = this.search(allItems, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n allItems = this.sort(allItems, tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n allItems = this.filter(allItems, tableState);\n }\n\n // Apply paging\n if (currentPage && tableState?.page) {\n const startIndex = (currentPage - 1) * tableState.page.pageSize;\n allItems = allItems.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n itemsMap.set(row, allItems);\n });\n\n return of(itemsMap).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort(items: ExampleItem[], { sortBy }: TableState): ExampleItem[] {\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 5000;\n startIndex = 0;\n allItems: ExampleItem[];\n\n constructor(public level = 0) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.allItems = this.allItems || generateItems(this.totalItems, this.level);\n this.items = [...this.allItems];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(this.items, tableState);\n }\n\n // Apply paging\n if (tableState?.page?.currentPage) {\n const startIndex = (tableState.page.currentPage - 1) * tableState.page.pageSize;\n this.items = this.items.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n return of(this.items).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\nfunction generateItems(size = 5000, level = 0, startIndex = 0): ExampleItem[] {\n return new Array(size).fill(null).map(() => ({\n name: `Laptops ${startIndex++} (Level ${level + 1})`,\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true,\n hasChildren: level < 2 ? true : false\n }));\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => (a ? a[b] : null), object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n", "html": "\n \n\n \n \n\n \n\n \n \n\n \n \n\n\n\n\n" }, + { + "name": "platform-table-initial-loading-example", + "description": "Platform Table Initial Loading", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", + "html": "\n \n\n \n\n \n\n \n\n" + }, + { + "name": "platform-table-editable-rows-example", + "description": "Platform Table Editable Rows", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", + "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" + }, { "name": "table-custom-pagination-example", "description": "Table Custom Pagination", @@ -67286,18 +67364,6 @@ "typescript": "import { ChangeDetectionStrategy, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { PlatformTableModule, TableComponent } from '@fundamental-ngx/platform/table';\nimport {\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableState,\n TableVirtualScrollDirective\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, delay, of } from 'rxjs';\n\n@Component({\n selector: 'fdp-table-custom-pagination-outer-scroll-example',\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule,\n PaginationModule\n ],\n templateUrl: './table-custom-pagination-outer-scroll-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class TableCustomPaginationOuterScrollExampleComponent implements OnInit {\n @ViewChild(TableComponent)\n table: TableComponent;\n\n source: TableDataSource;\n state: TableState;\n currentPage = 1;\n pageSize = 50;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n\n ngOnInit(): void {\n this.state = this._getDefaultState();\n }\n\n pageChanged(currentPage: number): void {\n this.currentPage = currentPage;\n this.table.setCurrentPage(this.currentPage);\n }\n\n itemsPerPageChanged(itemsPerPage: number): void {\n this.pageSize = itemsPerPage;\n this.table.setPageSize(this.pageSize, true);\n }\n\n /**\n * Simulating scroll position update. Once table is initialized app can set back preserved scrolling table\n * position so table can scroll it its original state.\n *\n * Note: Bellow scrollTopPosition property is set based on the scrolling position that was read from\n * this table example. Just some number to showcase this.\n */\n _getDefaultState(): TableState {\n return {\n columnKeys: [],\n sortBy: [],\n filterBy: [],\n groupBy: [],\n columns: [],\n searchInput: {\n category: null,\n text: ''\n },\n freezeToColumn: null,\n freezeToEndColumn: null,\n page: {\n pageSize: this.pageSize,\n currentPage: this.currentPage\n },\n scrollTopPosition: 0\n };\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n children?: ExampleItem[];\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [...ITEMS];\n totalItems = ITEMS.length;\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n this.totalItems = this.items.length;\n\n const currentPage = tableState?.page.currentPage || 1;\n const size = tableState?.page.pageSize || 50;\n const skip = (currentPage - 1) * size;\n\n const paginatedItems = this.items.slice(skip, size * currentPage);\n\n return of(paginatedItems).pipe(delay(1000));\n }\n}\n\n// Example items\nconst ITEMS: ExampleItem[] = new Array(5000).fill(null).map((_, index) => ({\n name: 'Laptops ' + index,\n price: {\n value: Math.floor(Math.random() * 1000),\n currency: 'USD'\n }\n}));\n", "html": "
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n


    \n \n \n \n\n \n\n \n\n \n\n \n \n
    \n" }, - { - "name": "platform-table-editable-rows-example", - "description": "Platform Table Editable Rows", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", - "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" - }, - { - "name": "platform-table-initial-loading-example", - "description": "Platform Table Initial Loading", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", - "html": "\n \n\n \n\n \n\n \n\n" - }, { "name": "platform-table-preserved-state-example", "description": "Platform Table Preserved State", @@ -67524,6 +67590,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule } from '@fundamental-ngx/platform/table';\nimport {\n ChildTableDataSource,\n CollectionNumberFilter,\n CollectionStringFilter,\n FdpTableDataSource,\n FilterType,\n FilterableColumnDataType,\n SortDirection,\n TableChildrenDataProvider,\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableRow,\n TableState,\n TableVirtualScrollDirective,\n TreeTableItem\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, of } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-doc-advanced-scrolling-example',\n templateUrl: './advanced-scrolling-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule\n ]\n})\nexport class AdvancedScrollingExampleComponent {\n source: TableDataSource;\n childSource: ChildTableDataSource;\n readonly filterTypeEnum = FilterType;\n readonly dataTypeEnum = FilterableColumnDataType;\n readonly selectOptions = ['Laptops 1 (Level 1)', 'Laptops 12 (Level 1)'];\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n this.childSource = new ChildTableDataSource(new ChildTableProviderExample());\n }\n}\n\nexport interface ExampleItem extends TreeTableItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n hasChildren: boolean;\n children?: FdpTableDataSource;\n}\n\nclass ChildTableProviderExample extends TableChildrenDataProvider {\n items: Map, ExampleItem[]> = new Map();\n totalItems = 200;\n startIndex = 0;\n allItemsMap = new Map, ExampleItem[]>();\n\n rowChildrenCount(row: TableRow): Observable {\n return of(this.totalItems);\n }\n\n /**\n * Unlike default dataSource, childDataSource accepts array of table rows as a second argument.\n * This is done to load child rows in bulk for the cases when multiple rows being expanded at the same time.\n * @param tableState\n * @param tableRows\n */\n fetch(\n tableState?: TableState,\n tableRows?: TableRow[]\n ): Observable, ExampleItem[]>> {\n const itemsMap = new Map, ExampleItem[]>();\n\n /** Logic of retrieving the child rows for a particular row in tableRows array. */\n tableRows?.forEach((row) => {\n let allItems = this.allItemsMap.get(row);\n const currentPage = tableState?.page.currentPage;\n if (!allItems) {\n allItems = generateItems(this.totalItems, row.level + 1);\n this.allItemsMap.set(row, allItems);\n }\n\n // apply searching\n if (tableState?.searchInput) {\n allItems = this.search(allItems, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n allItems = this.sort(allItems, tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n allItems = this.filter(allItems, tableState);\n }\n\n // Apply paging\n if (currentPage && tableState?.page) {\n const startIndex = (currentPage - 1) * tableState.page.pageSize;\n allItems = allItems.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n itemsMap.set(row, allItems);\n });\n\n return of(itemsMap).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort(items: ExampleItem[], { sortBy }: TableState): ExampleItem[] {\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 5000;\n startIndex = 0;\n allItems: ExampleItem[];\n\n constructor(public level = 0) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.allItems = this.allItems || generateItems(this.totalItems, this.level);\n this.items = [...this.allItems];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(this.items, tableState);\n }\n\n // Apply paging\n if (tableState?.page?.currentPage) {\n const startIndex = (tableState.page.currentPage - 1) * tableState.page.pageSize;\n this.items = this.items.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n return of(this.items).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\nfunction generateItems(size = 5000, level = 0, startIndex = 0): ExampleItem[] {\n return new Array(size).fill(null).map(() => ({\n name: `Laptops ${startIndex++} (Level ${level + 1})`,\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true,\n hasChildren: level < 2 ? true : false\n }));\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => (a ? a[b] : null), object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n", "html": "\n \n\n \n \n\n \n\n \n \n\n \n \n\n\n\n\n" }, + { + "name": "platform-table-initial-loading-example", + "description": "Platform Table Initial Loading", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", + "html": "\n \n\n \n\n \n\n \n\n" + }, + { + "name": "platform-table-editable-rows-example", + "description": "Platform Table Editable Rows", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", + "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" + }, { "name": "table-custom-pagination-example", "description": "Table Custom Pagination", @@ -67536,18 +67614,6 @@ "typescript": "import { ChangeDetectionStrategy, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { PlatformTableModule, TableComponent } from '@fundamental-ngx/platform/table';\nimport {\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableState,\n TableVirtualScrollDirective\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, delay, of } from 'rxjs';\n\n@Component({\n selector: 'fdp-table-custom-pagination-outer-scroll-example',\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule,\n PaginationModule\n ],\n templateUrl: './table-custom-pagination-outer-scroll-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class TableCustomPaginationOuterScrollExampleComponent implements OnInit {\n @ViewChild(TableComponent)\n table: TableComponent;\n\n source: TableDataSource;\n state: TableState;\n currentPage = 1;\n pageSize = 50;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n\n ngOnInit(): void {\n this.state = this._getDefaultState();\n }\n\n pageChanged(currentPage: number): void {\n this.currentPage = currentPage;\n this.table.setCurrentPage(this.currentPage);\n }\n\n itemsPerPageChanged(itemsPerPage: number): void {\n this.pageSize = itemsPerPage;\n this.table.setPageSize(this.pageSize, true);\n }\n\n /**\n * Simulating scroll position update. Once table is initialized app can set back preserved scrolling table\n * position so table can scroll it its original state.\n *\n * Note: Bellow scrollTopPosition property is set based on the scrolling position that was read from\n * this table example. Just some number to showcase this.\n */\n _getDefaultState(): TableState {\n return {\n columnKeys: [],\n sortBy: [],\n filterBy: [],\n groupBy: [],\n columns: [],\n searchInput: {\n category: null,\n text: ''\n },\n freezeToColumn: null,\n freezeToEndColumn: null,\n page: {\n pageSize: this.pageSize,\n currentPage: this.currentPage\n },\n scrollTopPosition: 0\n };\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n children?: ExampleItem[];\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [...ITEMS];\n totalItems = ITEMS.length;\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n this.totalItems = this.items.length;\n\n const currentPage = tableState?.page.currentPage || 1;\n const size = tableState?.page.pageSize || 50;\n const skip = (currentPage - 1) * size;\n\n const paginatedItems = this.items.slice(skip, size * currentPage);\n\n return of(paginatedItems).pipe(delay(1000));\n }\n}\n\n// Example items\nconst ITEMS: ExampleItem[] = new Array(5000).fill(null).map((_, index) => ({\n name: 'Laptops ' + index,\n price: {\n value: Math.floor(Math.random() * 1000),\n currency: 'USD'\n }\n}));\n", "html": "
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n


    \n \n \n \n\n \n\n \n\n \n\n \n \n
    \n" }, - { - "name": "platform-table-editable-rows-example", - "description": "Platform Table Editable Rows", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", - "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" - }, - { - "name": "platform-table-initial-loading-example", - "description": "Platform Table Initial Loading", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", - "html": "\n \n\n \n\n \n\n \n\n" - }, { "name": "platform-table-preserved-state-example", "description": "Platform Table Preserved State", @@ -67793,6 +67859,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule } from '@fundamental-ngx/platform/table';\nimport {\n ChildTableDataSource,\n CollectionNumberFilter,\n CollectionStringFilter,\n FdpTableDataSource,\n FilterType,\n FilterableColumnDataType,\n SortDirection,\n TableChildrenDataProvider,\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableRow,\n TableState,\n TableVirtualScrollDirective,\n TreeTableItem\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, of } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-doc-advanced-scrolling-example',\n templateUrl: './advanced-scrolling-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule\n ]\n})\nexport class AdvancedScrollingExampleComponent {\n source: TableDataSource;\n childSource: ChildTableDataSource;\n readonly filterTypeEnum = FilterType;\n readonly dataTypeEnum = FilterableColumnDataType;\n readonly selectOptions = ['Laptops 1 (Level 1)', 'Laptops 12 (Level 1)'];\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n this.childSource = new ChildTableDataSource(new ChildTableProviderExample());\n }\n}\n\nexport interface ExampleItem extends TreeTableItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n hasChildren: boolean;\n children?: FdpTableDataSource;\n}\n\nclass ChildTableProviderExample extends TableChildrenDataProvider {\n items: Map, ExampleItem[]> = new Map();\n totalItems = 200;\n startIndex = 0;\n allItemsMap = new Map, ExampleItem[]>();\n\n rowChildrenCount(row: TableRow): Observable {\n return of(this.totalItems);\n }\n\n /**\n * Unlike default dataSource, childDataSource accepts array of table rows as a second argument.\n * This is done to load child rows in bulk for the cases when multiple rows being expanded at the same time.\n * @param tableState\n * @param tableRows\n */\n fetch(\n tableState?: TableState,\n tableRows?: TableRow[]\n ): Observable, ExampleItem[]>> {\n const itemsMap = new Map, ExampleItem[]>();\n\n /** Logic of retrieving the child rows for a particular row in tableRows array. */\n tableRows?.forEach((row) => {\n let allItems = this.allItemsMap.get(row);\n const currentPage = tableState?.page.currentPage;\n if (!allItems) {\n allItems = generateItems(this.totalItems, row.level + 1);\n this.allItemsMap.set(row, allItems);\n }\n\n // apply searching\n if (tableState?.searchInput) {\n allItems = this.search(allItems, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n allItems = this.sort(allItems, tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n allItems = this.filter(allItems, tableState);\n }\n\n // Apply paging\n if (currentPage && tableState?.page) {\n const startIndex = (currentPage - 1) * tableState.page.pageSize;\n allItems = allItems.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n itemsMap.set(row, allItems);\n });\n\n return of(itemsMap).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort(items: ExampleItem[], { sortBy }: TableState): ExampleItem[] {\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 5000;\n startIndex = 0;\n allItems: ExampleItem[];\n\n constructor(public level = 0) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.allItems = this.allItems || generateItems(this.totalItems, this.level);\n this.items = [...this.allItems];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(this.items, tableState);\n }\n\n // Apply paging\n if (tableState?.page?.currentPage) {\n const startIndex = (tableState.page.currentPage - 1) * tableState.page.pageSize;\n this.items = this.items.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n return of(this.items).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\nfunction generateItems(size = 5000, level = 0, startIndex = 0): ExampleItem[] {\n return new Array(size).fill(null).map(() => ({\n name: `Laptops ${startIndex++} (Level ${level + 1})`,\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true,\n hasChildren: level < 2 ? true : false\n }));\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => (a ? a[b] : null), object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n", "html": "\n \n\n \n \n\n \n\n \n \n\n \n \n\n\n\n\n" }, + { + "name": "platform-table-initial-loading-example", + "description": "Platform Table Initial Loading", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", + "html": "\n \n\n \n\n \n\n \n\n" + }, + { + "name": "platform-table-editable-rows-example", + "description": "Platform Table Editable Rows", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", + "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" + }, { "name": "table-custom-pagination-example", "description": "Table Custom Pagination", @@ -67805,18 +67883,6 @@ "typescript": "import { ChangeDetectionStrategy, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { PlatformTableModule, TableComponent } from '@fundamental-ngx/platform/table';\nimport {\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableState,\n TableVirtualScrollDirective\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, delay, of } from 'rxjs';\n\n@Component({\n selector: 'fdp-table-custom-pagination-outer-scroll-example',\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule,\n PaginationModule\n ],\n templateUrl: './table-custom-pagination-outer-scroll-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class TableCustomPaginationOuterScrollExampleComponent implements OnInit {\n @ViewChild(TableComponent)\n table: TableComponent;\n\n source: TableDataSource;\n state: TableState;\n currentPage = 1;\n pageSize = 50;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n\n ngOnInit(): void {\n this.state = this._getDefaultState();\n }\n\n pageChanged(currentPage: number): void {\n this.currentPage = currentPage;\n this.table.setCurrentPage(this.currentPage);\n }\n\n itemsPerPageChanged(itemsPerPage: number): void {\n this.pageSize = itemsPerPage;\n this.table.setPageSize(this.pageSize, true);\n }\n\n /**\n * Simulating scroll position update. Once table is initialized app can set back preserved scrolling table\n * position so table can scroll it its original state.\n *\n * Note: Bellow scrollTopPosition property is set based on the scrolling position that was read from\n * this table example. Just some number to showcase this.\n */\n _getDefaultState(): TableState {\n return {\n columnKeys: [],\n sortBy: [],\n filterBy: [],\n groupBy: [],\n columns: [],\n searchInput: {\n category: null,\n text: ''\n },\n freezeToColumn: null,\n freezeToEndColumn: null,\n page: {\n pageSize: this.pageSize,\n currentPage: this.currentPage\n },\n scrollTopPosition: 0\n };\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n children?: ExampleItem[];\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [...ITEMS];\n totalItems = ITEMS.length;\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n this.totalItems = this.items.length;\n\n const currentPage = tableState?.page.currentPage || 1;\n const size = tableState?.page.pageSize || 50;\n const skip = (currentPage - 1) * size;\n\n const paginatedItems = this.items.slice(skip, size * currentPage);\n\n return of(paginatedItems).pipe(delay(1000));\n }\n}\n\n// Example items\nconst ITEMS: ExampleItem[] = new Array(5000).fill(null).map((_, index) => ({\n name: 'Laptops ' + index,\n price: {\n value: Math.floor(Math.random() * 1000),\n currency: 'USD'\n }\n}));\n", "html": "
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n


    \n \n \n \n\n \n\n \n\n \n\n \n \n
    \n" }, - { - "name": "platform-table-editable-rows-example", - "description": "Platform Table Editable Rows", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", - "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" - }, - { - "name": "platform-table-initial-loading-example", - "description": "Platform Table Initial Loading", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", - "html": "\n \n\n \n\n \n\n \n\n" - }, { "name": "platform-table-preserved-state-example", "description": "Platform Table Preserved State", @@ -68061,6 +68127,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule } from '@fundamental-ngx/platform/table';\nimport {\n ChildTableDataSource,\n CollectionNumberFilter,\n CollectionStringFilter,\n FdpTableDataSource,\n FilterType,\n FilterableColumnDataType,\n SortDirection,\n TableChildrenDataProvider,\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableRow,\n TableState,\n TableVirtualScrollDirective,\n TreeTableItem\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, of } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-doc-advanced-scrolling-example',\n templateUrl: './advanced-scrolling-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule\n ]\n})\nexport class AdvancedScrollingExampleComponent {\n source: TableDataSource;\n childSource: ChildTableDataSource;\n readonly filterTypeEnum = FilterType;\n readonly dataTypeEnum = FilterableColumnDataType;\n readonly selectOptions = ['Laptops 1 (Level 1)', 'Laptops 12 (Level 1)'];\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n this.childSource = new ChildTableDataSource(new ChildTableProviderExample());\n }\n}\n\nexport interface ExampleItem extends TreeTableItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n hasChildren: boolean;\n children?: FdpTableDataSource;\n}\n\nclass ChildTableProviderExample extends TableChildrenDataProvider {\n items: Map, ExampleItem[]> = new Map();\n totalItems = 200;\n startIndex = 0;\n allItemsMap = new Map, ExampleItem[]>();\n\n rowChildrenCount(row: TableRow): Observable {\n return of(this.totalItems);\n }\n\n /**\n * Unlike default dataSource, childDataSource accepts array of table rows as a second argument.\n * This is done to load child rows in bulk for the cases when multiple rows being expanded at the same time.\n * @param tableState\n * @param tableRows\n */\n fetch(\n tableState?: TableState,\n tableRows?: TableRow[]\n ): Observable, ExampleItem[]>> {\n const itemsMap = new Map, ExampleItem[]>();\n\n /** Logic of retrieving the child rows for a particular row in tableRows array. */\n tableRows?.forEach((row) => {\n let allItems = this.allItemsMap.get(row);\n const currentPage = tableState?.page.currentPage;\n if (!allItems) {\n allItems = generateItems(this.totalItems, row.level + 1);\n this.allItemsMap.set(row, allItems);\n }\n\n // apply searching\n if (tableState?.searchInput) {\n allItems = this.search(allItems, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n allItems = this.sort(allItems, tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n allItems = this.filter(allItems, tableState);\n }\n\n // Apply paging\n if (currentPage && tableState?.page) {\n const startIndex = (currentPage - 1) * tableState.page.pageSize;\n allItems = allItems.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n itemsMap.set(row, allItems);\n });\n\n return of(itemsMap).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort(items: ExampleItem[], { sortBy }: TableState): ExampleItem[] {\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 5000;\n startIndex = 0;\n allItems: ExampleItem[];\n\n constructor(public level = 0) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.allItems = this.allItems || generateItems(this.totalItems, this.level);\n this.items = [...this.allItems];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(this.items, tableState);\n }\n\n // Apply paging\n if (tableState?.page?.currentPage) {\n const startIndex = (tableState.page.currentPage - 1) * tableState.page.pageSize;\n this.items = this.items.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n return of(this.items).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\nfunction generateItems(size = 5000, level = 0, startIndex = 0): ExampleItem[] {\n return new Array(size).fill(null).map(() => ({\n name: `Laptops ${startIndex++} (Level ${level + 1})`,\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true,\n hasChildren: level < 2 ? true : false\n }));\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => (a ? a[b] : null), object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n", "html": "\n \n\n \n \n\n \n\n \n \n\n \n \n\n\n\n\n" }, + { + "name": "platform-table-initial-loading-example", + "description": "Platform Table Initial Loading", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", + "html": "\n \n\n \n\n \n\n \n\n" + }, + { + "name": "platform-table-editable-rows-example", + "description": "Platform Table Editable Rows", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", + "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" + }, { "name": "table-custom-pagination-example", "description": "Table Custom Pagination", @@ -68073,18 +68151,6 @@ "typescript": "import { ChangeDetectionStrategy, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { PlatformTableModule, TableComponent } from '@fundamental-ngx/platform/table';\nimport {\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableState,\n TableVirtualScrollDirective\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, delay, of } from 'rxjs';\n\n@Component({\n selector: 'fdp-table-custom-pagination-outer-scroll-example',\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule,\n PaginationModule\n ],\n templateUrl: './table-custom-pagination-outer-scroll-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class TableCustomPaginationOuterScrollExampleComponent implements OnInit {\n @ViewChild(TableComponent)\n table: TableComponent;\n\n source: TableDataSource;\n state: TableState;\n currentPage = 1;\n pageSize = 50;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n\n ngOnInit(): void {\n this.state = this._getDefaultState();\n }\n\n pageChanged(currentPage: number): void {\n this.currentPage = currentPage;\n this.table.setCurrentPage(this.currentPage);\n }\n\n itemsPerPageChanged(itemsPerPage: number): void {\n this.pageSize = itemsPerPage;\n this.table.setPageSize(this.pageSize, true);\n }\n\n /**\n * Simulating scroll position update. Once table is initialized app can set back preserved scrolling table\n * position so table can scroll it its original state.\n *\n * Note: Bellow scrollTopPosition property is set based on the scrolling position that was read from\n * this table example. Just some number to showcase this.\n */\n _getDefaultState(): TableState {\n return {\n columnKeys: [],\n sortBy: [],\n filterBy: [],\n groupBy: [],\n columns: [],\n searchInput: {\n category: null,\n text: ''\n },\n freezeToColumn: null,\n freezeToEndColumn: null,\n page: {\n pageSize: this.pageSize,\n currentPage: this.currentPage\n },\n scrollTopPosition: 0\n };\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n children?: ExampleItem[];\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [...ITEMS];\n totalItems = ITEMS.length;\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n this.totalItems = this.items.length;\n\n const currentPage = tableState?.page.currentPage || 1;\n const size = tableState?.page.pageSize || 50;\n const skip = (currentPage - 1) * size;\n\n const paginatedItems = this.items.slice(skip, size * currentPage);\n\n return of(paginatedItems).pipe(delay(1000));\n }\n}\n\n// Example items\nconst ITEMS: ExampleItem[] = new Array(5000).fill(null).map((_, index) => ({\n name: 'Laptops ' + index,\n price: {\n value: Math.floor(Math.random() * 1000),\n currency: 'USD'\n }\n}));\n", "html": "
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n


    \n \n \n \n\n \n\n \n\n \n\n \n \n
    \n" }, - { - "name": "platform-table-editable-rows-example", - "description": "Platform Table Editable Rows", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", - "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" - }, - { - "name": "platform-table-initial-loading-example", - "description": "Platform Table Initial Loading", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", - "html": "\n \n\n \n\n \n\n \n\n" - }, { "name": "platform-table-preserved-state-example", "description": "Platform Table Preserved State", @@ -68319,6 +68385,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule } from '@fundamental-ngx/platform/table';\nimport {\n ChildTableDataSource,\n CollectionNumberFilter,\n CollectionStringFilter,\n FdpTableDataSource,\n FilterType,\n FilterableColumnDataType,\n SortDirection,\n TableChildrenDataProvider,\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableRow,\n TableState,\n TableVirtualScrollDirective,\n TreeTableItem\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, of } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-doc-advanced-scrolling-example',\n templateUrl: './advanced-scrolling-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule\n ]\n})\nexport class AdvancedScrollingExampleComponent {\n source: TableDataSource;\n childSource: ChildTableDataSource;\n readonly filterTypeEnum = FilterType;\n readonly dataTypeEnum = FilterableColumnDataType;\n readonly selectOptions = ['Laptops 1 (Level 1)', 'Laptops 12 (Level 1)'];\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n this.childSource = new ChildTableDataSource(new ChildTableProviderExample());\n }\n}\n\nexport interface ExampleItem extends TreeTableItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n hasChildren: boolean;\n children?: FdpTableDataSource;\n}\n\nclass ChildTableProviderExample extends TableChildrenDataProvider {\n items: Map, ExampleItem[]> = new Map();\n totalItems = 200;\n startIndex = 0;\n allItemsMap = new Map, ExampleItem[]>();\n\n rowChildrenCount(row: TableRow): Observable {\n return of(this.totalItems);\n }\n\n /**\n * Unlike default dataSource, childDataSource accepts array of table rows as a second argument.\n * This is done to load child rows in bulk for the cases when multiple rows being expanded at the same time.\n * @param tableState\n * @param tableRows\n */\n fetch(\n tableState?: TableState,\n tableRows?: TableRow[]\n ): Observable, ExampleItem[]>> {\n const itemsMap = new Map, ExampleItem[]>();\n\n /** Logic of retrieving the child rows for a particular row in tableRows array. */\n tableRows?.forEach((row) => {\n let allItems = this.allItemsMap.get(row);\n const currentPage = tableState?.page.currentPage;\n if (!allItems) {\n allItems = generateItems(this.totalItems, row.level + 1);\n this.allItemsMap.set(row, allItems);\n }\n\n // apply searching\n if (tableState?.searchInput) {\n allItems = this.search(allItems, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n allItems = this.sort(allItems, tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n allItems = this.filter(allItems, tableState);\n }\n\n // Apply paging\n if (currentPage && tableState?.page) {\n const startIndex = (currentPage - 1) * tableState.page.pageSize;\n allItems = allItems.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n itemsMap.set(row, allItems);\n });\n\n return of(itemsMap).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort(items: ExampleItem[], { sortBy }: TableState): ExampleItem[] {\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 5000;\n startIndex = 0;\n allItems: ExampleItem[];\n\n constructor(public level = 0) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.allItems = this.allItems || generateItems(this.totalItems, this.level);\n this.items = [...this.allItems];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(this.items, tableState);\n }\n\n // Apply paging\n if (tableState?.page?.currentPage) {\n const startIndex = (tableState.page.currentPage - 1) * tableState.page.pageSize;\n this.items = this.items.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n return of(this.items).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\nfunction generateItems(size = 5000, level = 0, startIndex = 0): ExampleItem[] {\n return new Array(size).fill(null).map(() => ({\n name: `Laptops ${startIndex++} (Level ${level + 1})`,\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true,\n hasChildren: level < 2 ? true : false\n }));\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => (a ? a[b] : null), object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n", "html": "\n \n\n \n \n\n \n\n \n \n\n \n \n\n\n\n\n" }, + { + "name": "platform-table-initial-loading-example", + "description": "Platform Table Initial Loading", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", + "html": "\n \n\n \n\n \n\n \n\n" + }, + { + "name": "platform-table-editable-rows-example", + "description": "Platform Table Editable Rows", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", + "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" + }, { "name": "table-custom-pagination-example", "description": "Table Custom Pagination", @@ -68331,18 +68409,6 @@ "typescript": "import { ChangeDetectionStrategy, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { PlatformTableModule, TableComponent } from '@fundamental-ngx/platform/table';\nimport {\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableState,\n TableVirtualScrollDirective\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, delay, of } from 'rxjs';\n\n@Component({\n selector: 'fdp-table-custom-pagination-outer-scroll-example',\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule,\n PaginationModule\n ],\n templateUrl: './table-custom-pagination-outer-scroll-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class TableCustomPaginationOuterScrollExampleComponent implements OnInit {\n @ViewChild(TableComponent)\n table: TableComponent;\n\n source: TableDataSource;\n state: TableState;\n currentPage = 1;\n pageSize = 50;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n\n ngOnInit(): void {\n this.state = this._getDefaultState();\n }\n\n pageChanged(currentPage: number): void {\n this.currentPage = currentPage;\n this.table.setCurrentPage(this.currentPage);\n }\n\n itemsPerPageChanged(itemsPerPage: number): void {\n this.pageSize = itemsPerPage;\n this.table.setPageSize(this.pageSize, true);\n }\n\n /**\n * Simulating scroll position update. Once table is initialized app can set back preserved scrolling table\n * position so table can scroll it its original state.\n *\n * Note: Bellow scrollTopPosition property is set based on the scrolling position that was read from\n * this table example. Just some number to showcase this.\n */\n _getDefaultState(): TableState {\n return {\n columnKeys: [],\n sortBy: [],\n filterBy: [],\n groupBy: [],\n columns: [],\n searchInput: {\n category: null,\n text: ''\n },\n freezeToColumn: null,\n freezeToEndColumn: null,\n page: {\n pageSize: this.pageSize,\n currentPage: this.currentPage\n },\n scrollTopPosition: 0\n };\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n children?: ExampleItem[];\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [...ITEMS];\n totalItems = ITEMS.length;\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n this.totalItems = this.items.length;\n\n const currentPage = tableState?.page.currentPage || 1;\n const size = tableState?.page.pageSize || 50;\n const skip = (currentPage - 1) * size;\n\n const paginatedItems = this.items.slice(skip, size * currentPage);\n\n return of(paginatedItems).pipe(delay(1000));\n }\n}\n\n// Example items\nconst ITEMS: ExampleItem[] = new Array(5000).fill(null).map((_, index) => ({\n name: 'Laptops ' + index,\n price: {\n value: Math.floor(Math.random() * 1000),\n currency: 'USD'\n }\n}));\n", "html": "
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n


    \n \n \n \n\n \n\n \n\n \n\n \n \n
    \n" }, - { - "name": "platform-table-editable-rows-example", - "description": "Platform Table Editable Rows", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", - "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" - }, - { - "name": "platform-table-initial-loading-example", - "description": "Platform Table Initial Loading", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", - "html": "\n \n\n \n\n \n\n \n\n" - }, { "name": "platform-table-preserved-state-example", "description": "Platform Table Preserved State", @@ -68576,6 +68642,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule } from '@fundamental-ngx/platform/table';\nimport {\n ChildTableDataSource,\n CollectionNumberFilter,\n CollectionStringFilter,\n FdpTableDataSource,\n FilterType,\n FilterableColumnDataType,\n SortDirection,\n TableChildrenDataProvider,\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableRow,\n TableState,\n TableVirtualScrollDirective,\n TreeTableItem\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, of } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-doc-advanced-scrolling-example',\n templateUrl: './advanced-scrolling-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule\n ]\n})\nexport class AdvancedScrollingExampleComponent {\n source: TableDataSource;\n childSource: ChildTableDataSource;\n readonly filterTypeEnum = FilterType;\n readonly dataTypeEnum = FilterableColumnDataType;\n readonly selectOptions = ['Laptops 1 (Level 1)', 'Laptops 12 (Level 1)'];\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n this.childSource = new ChildTableDataSource(new ChildTableProviderExample());\n }\n}\n\nexport interface ExampleItem extends TreeTableItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n hasChildren: boolean;\n children?: FdpTableDataSource;\n}\n\nclass ChildTableProviderExample extends TableChildrenDataProvider {\n items: Map, ExampleItem[]> = new Map();\n totalItems = 200;\n startIndex = 0;\n allItemsMap = new Map, ExampleItem[]>();\n\n rowChildrenCount(row: TableRow): Observable {\n return of(this.totalItems);\n }\n\n /**\n * Unlike default dataSource, childDataSource accepts array of table rows as a second argument.\n * This is done to load child rows in bulk for the cases when multiple rows being expanded at the same time.\n * @param tableState\n * @param tableRows\n */\n fetch(\n tableState?: TableState,\n tableRows?: TableRow[]\n ): Observable, ExampleItem[]>> {\n const itemsMap = new Map, ExampleItem[]>();\n\n /** Logic of retrieving the child rows for a particular row in tableRows array. */\n tableRows?.forEach((row) => {\n let allItems = this.allItemsMap.get(row);\n const currentPage = tableState?.page.currentPage;\n if (!allItems) {\n allItems = generateItems(this.totalItems, row.level + 1);\n this.allItemsMap.set(row, allItems);\n }\n\n // apply searching\n if (tableState?.searchInput) {\n allItems = this.search(allItems, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n allItems = this.sort(allItems, tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n allItems = this.filter(allItems, tableState);\n }\n\n // Apply paging\n if (currentPage && tableState?.page) {\n const startIndex = (currentPage - 1) * tableState.page.pageSize;\n allItems = allItems.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n itemsMap.set(row, allItems);\n });\n\n return of(itemsMap).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort(items: ExampleItem[], { sortBy }: TableState): ExampleItem[] {\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 5000;\n startIndex = 0;\n allItems: ExampleItem[];\n\n constructor(public level = 0) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.allItems = this.allItems || generateItems(this.totalItems, this.level);\n this.items = [...this.allItems];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(this.items, tableState);\n }\n\n // Apply paging\n if (tableState?.page?.currentPage) {\n const startIndex = (tableState.page.currentPage - 1) * tableState.page.pageSize;\n this.items = this.items.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n return of(this.items).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\nfunction generateItems(size = 5000, level = 0, startIndex = 0): ExampleItem[] {\n return new Array(size).fill(null).map(() => ({\n name: `Laptops ${startIndex++} (Level ${level + 1})`,\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true,\n hasChildren: level < 2 ? true : false\n }));\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => (a ? a[b] : null), object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n", "html": "\n \n\n \n \n\n \n\n \n \n\n \n \n\n\n\n\n" }, + { + "name": "platform-table-initial-loading-example", + "description": "Platform Table Initial Loading", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", + "html": "\n \n\n \n\n \n\n \n\n" + }, + { + "name": "platform-table-editable-rows-example", + "description": "Platform Table Editable Rows", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", + "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" + }, { "name": "table-custom-pagination-example", "description": "Table Custom Pagination", @@ -68588,18 +68666,6 @@ "typescript": "import { ChangeDetectionStrategy, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { PlatformTableModule, TableComponent } from '@fundamental-ngx/platform/table';\nimport {\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableState,\n TableVirtualScrollDirective\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, delay, of } from 'rxjs';\n\n@Component({\n selector: 'fdp-table-custom-pagination-outer-scroll-example',\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule,\n PaginationModule\n ],\n templateUrl: './table-custom-pagination-outer-scroll-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class TableCustomPaginationOuterScrollExampleComponent implements OnInit {\n @ViewChild(TableComponent)\n table: TableComponent;\n\n source: TableDataSource;\n state: TableState;\n currentPage = 1;\n pageSize = 50;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n\n ngOnInit(): void {\n this.state = this._getDefaultState();\n }\n\n pageChanged(currentPage: number): void {\n this.currentPage = currentPage;\n this.table.setCurrentPage(this.currentPage);\n }\n\n itemsPerPageChanged(itemsPerPage: number): void {\n this.pageSize = itemsPerPage;\n this.table.setPageSize(this.pageSize, true);\n }\n\n /**\n * Simulating scroll position update. Once table is initialized app can set back preserved scrolling table\n * position so table can scroll it its original state.\n *\n * Note: Bellow scrollTopPosition property is set based on the scrolling position that was read from\n * this table example. Just some number to showcase this.\n */\n _getDefaultState(): TableState {\n return {\n columnKeys: [],\n sortBy: [],\n filterBy: [],\n groupBy: [],\n columns: [],\n searchInput: {\n category: null,\n text: ''\n },\n freezeToColumn: null,\n freezeToEndColumn: null,\n page: {\n pageSize: this.pageSize,\n currentPage: this.currentPage\n },\n scrollTopPosition: 0\n };\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n children?: ExampleItem[];\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [...ITEMS];\n totalItems = ITEMS.length;\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n this.totalItems = this.items.length;\n\n const currentPage = tableState?.page.currentPage || 1;\n const size = tableState?.page.pageSize || 50;\n const skip = (currentPage - 1) * size;\n\n const paginatedItems = this.items.slice(skip, size * currentPage);\n\n return of(paginatedItems).pipe(delay(1000));\n }\n}\n\n// Example items\nconst ITEMS: ExampleItem[] = new Array(5000).fill(null).map((_, index) => ({\n name: 'Laptops ' + index,\n price: {\n value: Math.floor(Math.random() * 1000),\n currency: 'USD'\n }\n}));\n", "html": "
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n


    \n \n \n \n\n \n\n \n\n \n\n \n \n
    \n" }, - { - "name": "platform-table-editable-rows-example", - "description": "Platform Table Editable Rows", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", - "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" - }, - { - "name": "platform-table-initial-loading-example", - "description": "Platform Table Initial Loading", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", - "html": "\n \n\n \n\n \n\n \n\n" - }, { "name": "platform-table-preserved-state-example", "description": "Platform Table Preserved State", @@ -68826,6 +68892,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule } from '@fundamental-ngx/platform/table';\nimport {\n ChildTableDataSource,\n CollectionNumberFilter,\n CollectionStringFilter,\n FdpTableDataSource,\n FilterType,\n FilterableColumnDataType,\n SortDirection,\n TableChildrenDataProvider,\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableRow,\n TableState,\n TableVirtualScrollDirective,\n TreeTableItem\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, of } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-doc-advanced-scrolling-example',\n templateUrl: './advanced-scrolling-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule\n ]\n})\nexport class AdvancedScrollingExampleComponent {\n source: TableDataSource;\n childSource: ChildTableDataSource;\n readonly filterTypeEnum = FilterType;\n readonly dataTypeEnum = FilterableColumnDataType;\n readonly selectOptions = ['Laptops 1 (Level 1)', 'Laptops 12 (Level 1)'];\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n this.childSource = new ChildTableDataSource(new ChildTableProviderExample());\n }\n}\n\nexport interface ExampleItem extends TreeTableItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n hasChildren: boolean;\n children?: FdpTableDataSource;\n}\n\nclass ChildTableProviderExample extends TableChildrenDataProvider {\n items: Map, ExampleItem[]> = new Map();\n totalItems = 200;\n startIndex = 0;\n allItemsMap = new Map, ExampleItem[]>();\n\n rowChildrenCount(row: TableRow): Observable {\n return of(this.totalItems);\n }\n\n /**\n * Unlike default dataSource, childDataSource accepts array of table rows as a second argument.\n * This is done to load child rows in bulk for the cases when multiple rows being expanded at the same time.\n * @param tableState\n * @param tableRows\n */\n fetch(\n tableState?: TableState,\n tableRows?: TableRow[]\n ): Observable, ExampleItem[]>> {\n const itemsMap = new Map, ExampleItem[]>();\n\n /** Logic of retrieving the child rows for a particular row in tableRows array. */\n tableRows?.forEach((row) => {\n let allItems = this.allItemsMap.get(row);\n const currentPage = tableState?.page.currentPage;\n if (!allItems) {\n allItems = generateItems(this.totalItems, row.level + 1);\n this.allItemsMap.set(row, allItems);\n }\n\n // apply searching\n if (tableState?.searchInput) {\n allItems = this.search(allItems, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n allItems = this.sort(allItems, tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n allItems = this.filter(allItems, tableState);\n }\n\n // Apply paging\n if (currentPage && tableState?.page) {\n const startIndex = (currentPage - 1) * tableState.page.pageSize;\n allItems = allItems.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n itemsMap.set(row, allItems);\n });\n\n return of(itemsMap).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort(items: ExampleItem[], { sortBy }: TableState): ExampleItem[] {\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 5000;\n startIndex = 0;\n allItems: ExampleItem[];\n\n constructor(public level = 0) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.allItems = this.allItems || generateItems(this.totalItems, this.level);\n this.items = [...this.allItems];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(this.items, tableState);\n }\n\n // Apply paging\n if (tableState?.page?.currentPage) {\n const startIndex = (tableState.page.currentPage - 1) * tableState.page.pageSize;\n this.items = this.items.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n return of(this.items).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\nfunction generateItems(size = 5000, level = 0, startIndex = 0): ExampleItem[] {\n return new Array(size).fill(null).map(() => ({\n name: `Laptops ${startIndex++} (Level ${level + 1})`,\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true,\n hasChildren: level < 2 ? true : false\n }));\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => (a ? a[b] : null), object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n", "html": "\n \n\n \n \n\n \n\n \n \n\n \n \n\n\n\n\n" }, + { + "name": "platform-table-initial-loading-example", + "description": "Platform Table Initial Loading", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", + "html": "\n \n\n \n\n \n\n \n\n" + }, + { + "name": "platform-table-editable-rows-example", + "description": "Platform Table Editable Rows", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", + "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" + }, { "name": "table-custom-pagination-example", "description": "Table Custom Pagination", @@ -68838,18 +68916,6 @@ "typescript": "import { ChangeDetectionStrategy, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { PlatformTableModule, TableComponent } from '@fundamental-ngx/platform/table';\nimport {\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableState,\n TableVirtualScrollDirective\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, delay, of } from 'rxjs';\n\n@Component({\n selector: 'fdp-table-custom-pagination-outer-scroll-example',\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule,\n PaginationModule\n ],\n templateUrl: './table-custom-pagination-outer-scroll-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class TableCustomPaginationOuterScrollExampleComponent implements OnInit {\n @ViewChild(TableComponent)\n table: TableComponent;\n\n source: TableDataSource;\n state: TableState;\n currentPage = 1;\n pageSize = 50;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n\n ngOnInit(): void {\n this.state = this._getDefaultState();\n }\n\n pageChanged(currentPage: number): void {\n this.currentPage = currentPage;\n this.table.setCurrentPage(this.currentPage);\n }\n\n itemsPerPageChanged(itemsPerPage: number): void {\n this.pageSize = itemsPerPage;\n this.table.setPageSize(this.pageSize, true);\n }\n\n /**\n * Simulating scroll position update. Once table is initialized app can set back preserved scrolling table\n * position so table can scroll it its original state.\n *\n * Note: Bellow scrollTopPosition property is set based on the scrolling position that was read from\n * this table example. Just some number to showcase this.\n */\n _getDefaultState(): TableState {\n return {\n columnKeys: [],\n sortBy: [],\n filterBy: [],\n groupBy: [],\n columns: [],\n searchInput: {\n category: null,\n text: ''\n },\n freezeToColumn: null,\n freezeToEndColumn: null,\n page: {\n pageSize: this.pageSize,\n currentPage: this.currentPage\n },\n scrollTopPosition: 0\n };\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n children?: ExampleItem[];\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [...ITEMS];\n totalItems = ITEMS.length;\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n this.totalItems = this.items.length;\n\n const currentPage = tableState?.page.currentPage || 1;\n const size = tableState?.page.pageSize || 50;\n const skip = (currentPage - 1) * size;\n\n const paginatedItems = this.items.slice(skip, size * currentPage);\n\n return of(paginatedItems).pipe(delay(1000));\n }\n}\n\n// Example items\nconst ITEMS: ExampleItem[] = new Array(5000).fill(null).map((_, index) => ({\n name: 'Laptops ' + index,\n price: {\n value: Math.floor(Math.random() * 1000),\n currency: 'USD'\n }\n}));\n", "html": "
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n


    \n \n \n \n\n \n\n \n\n \n\n \n \n
    \n" }, - { - "name": "platform-table-editable-rows-example", - "description": "Platform Table Editable Rows", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", - "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" - }, - { - "name": "platform-table-initial-loading-example", - "description": "Platform Table Initial Loading", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", - "html": "\n \n\n \n\n \n\n \n\n" - }, { "name": "platform-table-preserved-state-example", "description": "Platform Table Preserved State", @@ -69076,6 +69142,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule } from '@fundamental-ngx/platform/table';\nimport {\n ChildTableDataSource,\n CollectionNumberFilter,\n CollectionStringFilter,\n FdpTableDataSource,\n FilterType,\n FilterableColumnDataType,\n SortDirection,\n TableChildrenDataProvider,\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableRow,\n TableState,\n TableVirtualScrollDirective,\n TreeTableItem\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, of } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-doc-advanced-scrolling-example',\n templateUrl: './advanced-scrolling-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule\n ]\n})\nexport class AdvancedScrollingExampleComponent {\n source: TableDataSource;\n childSource: ChildTableDataSource;\n readonly filterTypeEnum = FilterType;\n readonly dataTypeEnum = FilterableColumnDataType;\n readonly selectOptions = ['Laptops 1 (Level 1)', 'Laptops 12 (Level 1)'];\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n this.childSource = new ChildTableDataSource(new ChildTableProviderExample());\n }\n}\n\nexport interface ExampleItem extends TreeTableItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n hasChildren: boolean;\n children?: FdpTableDataSource;\n}\n\nclass ChildTableProviderExample extends TableChildrenDataProvider {\n items: Map, ExampleItem[]> = new Map();\n totalItems = 200;\n startIndex = 0;\n allItemsMap = new Map, ExampleItem[]>();\n\n rowChildrenCount(row: TableRow): Observable {\n return of(this.totalItems);\n }\n\n /**\n * Unlike default dataSource, childDataSource accepts array of table rows as a second argument.\n * This is done to load child rows in bulk for the cases when multiple rows being expanded at the same time.\n * @param tableState\n * @param tableRows\n */\n fetch(\n tableState?: TableState,\n tableRows?: TableRow[]\n ): Observable, ExampleItem[]>> {\n const itemsMap = new Map, ExampleItem[]>();\n\n /** Logic of retrieving the child rows for a particular row in tableRows array. */\n tableRows?.forEach((row) => {\n let allItems = this.allItemsMap.get(row);\n const currentPage = tableState?.page.currentPage;\n if (!allItems) {\n allItems = generateItems(this.totalItems, row.level + 1);\n this.allItemsMap.set(row, allItems);\n }\n\n // apply searching\n if (tableState?.searchInput) {\n allItems = this.search(allItems, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n allItems = this.sort(allItems, tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n allItems = this.filter(allItems, tableState);\n }\n\n // Apply paging\n if (currentPage && tableState?.page) {\n const startIndex = (currentPage - 1) * tableState.page.pageSize;\n allItems = allItems.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n itemsMap.set(row, allItems);\n });\n\n return of(itemsMap).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort(items: ExampleItem[], { sortBy }: TableState): ExampleItem[] {\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 5000;\n startIndex = 0;\n allItems: ExampleItem[];\n\n constructor(public level = 0) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.allItems = this.allItems || generateItems(this.totalItems, this.level);\n this.items = [...this.allItems];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(this.items, tableState);\n }\n\n // Apply paging\n if (tableState?.page?.currentPage) {\n const startIndex = (tableState.page.currentPage - 1) * tableState.page.pageSize;\n this.items = this.items.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n return of(this.items).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\nfunction generateItems(size = 5000, level = 0, startIndex = 0): ExampleItem[] {\n return new Array(size).fill(null).map(() => ({\n name: `Laptops ${startIndex++} (Level ${level + 1})`,\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true,\n hasChildren: level < 2 ? true : false\n }));\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => (a ? a[b] : null), object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n", "html": "\n \n\n \n \n\n \n\n \n \n\n \n \n\n\n\n\n" }, + { + "name": "platform-table-initial-loading-example", + "description": "Platform Table Initial Loading", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", + "html": "\n \n\n \n\n \n\n \n\n" + }, + { + "name": "platform-table-editable-rows-example", + "description": "Platform Table Editable Rows", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", + "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" + }, { "name": "table-custom-pagination-example", "description": "Table Custom Pagination", @@ -69088,18 +69166,6 @@ "typescript": "import { ChangeDetectionStrategy, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { PlatformTableModule, TableComponent } from '@fundamental-ngx/platform/table';\nimport {\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableState,\n TableVirtualScrollDirective\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, delay, of } from 'rxjs';\n\n@Component({\n selector: 'fdp-table-custom-pagination-outer-scroll-example',\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule,\n PaginationModule\n ],\n templateUrl: './table-custom-pagination-outer-scroll-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class TableCustomPaginationOuterScrollExampleComponent implements OnInit {\n @ViewChild(TableComponent)\n table: TableComponent;\n\n source: TableDataSource;\n state: TableState;\n currentPage = 1;\n pageSize = 50;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n\n ngOnInit(): void {\n this.state = this._getDefaultState();\n }\n\n pageChanged(currentPage: number): void {\n this.currentPage = currentPage;\n this.table.setCurrentPage(this.currentPage);\n }\n\n itemsPerPageChanged(itemsPerPage: number): void {\n this.pageSize = itemsPerPage;\n this.table.setPageSize(this.pageSize, true);\n }\n\n /**\n * Simulating scroll position update. Once table is initialized app can set back preserved scrolling table\n * position so table can scroll it its original state.\n *\n * Note: Bellow scrollTopPosition property is set based on the scrolling position that was read from\n * this table example. Just some number to showcase this.\n */\n _getDefaultState(): TableState {\n return {\n columnKeys: [],\n sortBy: [],\n filterBy: [],\n groupBy: [],\n columns: [],\n searchInput: {\n category: null,\n text: ''\n },\n freezeToColumn: null,\n freezeToEndColumn: null,\n page: {\n pageSize: this.pageSize,\n currentPage: this.currentPage\n },\n scrollTopPosition: 0\n };\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n children?: ExampleItem[];\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [...ITEMS];\n totalItems = ITEMS.length;\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n this.totalItems = this.items.length;\n\n const currentPage = tableState?.page.currentPage || 1;\n const size = tableState?.page.pageSize || 50;\n const skip = (currentPage - 1) * size;\n\n const paginatedItems = this.items.slice(skip, size * currentPage);\n\n return of(paginatedItems).pipe(delay(1000));\n }\n}\n\n// Example items\nconst ITEMS: ExampleItem[] = new Array(5000).fill(null).map((_, index) => ({\n name: 'Laptops ' + index,\n price: {\n value: Math.floor(Math.random() * 1000),\n currency: 'USD'\n }\n}));\n", "html": "
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n


    \n \n \n \n\n \n\n \n\n \n\n \n \n
    \n" }, - { - "name": "platform-table-editable-rows-example", - "description": "Platform Table Editable Rows", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", - "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" - }, - { - "name": "platform-table-initial-loading-example", - "description": "Platform Table Initial Loading", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", - "html": "\n \n\n \n\n \n\n \n\n" - }, { "name": "platform-table-preserved-state-example", "description": "Platform Table Preserved State", @@ -69357,6 +69423,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule } from '@fundamental-ngx/platform/table';\nimport {\n ChildTableDataSource,\n CollectionNumberFilter,\n CollectionStringFilter,\n FdpTableDataSource,\n FilterType,\n FilterableColumnDataType,\n SortDirection,\n TableChildrenDataProvider,\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableRow,\n TableState,\n TableVirtualScrollDirective,\n TreeTableItem\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, of } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-doc-advanced-scrolling-example',\n templateUrl: './advanced-scrolling-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule\n ]\n})\nexport class AdvancedScrollingExampleComponent {\n source: TableDataSource;\n childSource: ChildTableDataSource;\n readonly filterTypeEnum = FilterType;\n readonly dataTypeEnum = FilterableColumnDataType;\n readonly selectOptions = ['Laptops 1 (Level 1)', 'Laptops 12 (Level 1)'];\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n this.childSource = new ChildTableDataSource(new ChildTableProviderExample());\n }\n}\n\nexport interface ExampleItem extends TreeTableItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n hasChildren: boolean;\n children?: FdpTableDataSource;\n}\n\nclass ChildTableProviderExample extends TableChildrenDataProvider {\n items: Map, ExampleItem[]> = new Map();\n totalItems = 200;\n startIndex = 0;\n allItemsMap = new Map, ExampleItem[]>();\n\n rowChildrenCount(row: TableRow): Observable {\n return of(this.totalItems);\n }\n\n /**\n * Unlike default dataSource, childDataSource accepts array of table rows as a second argument.\n * This is done to load child rows in bulk for the cases when multiple rows being expanded at the same time.\n * @param tableState\n * @param tableRows\n */\n fetch(\n tableState?: TableState,\n tableRows?: TableRow[]\n ): Observable, ExampleItem[]>> {\n const itemsMap = new Map, ExampleItem[]>();\n\n /** Logic of retrieving the child rows for a particular row in tableRows array. */\n tableRows?.forEach((row) => {\n let allItems = this.allItemsMap.get(row);\n const currentPage = tableState?.page.currentPage;\n if (!allItems) {\n allItems = generateItems(this.totalItems, row.level + 1);\n this.allItemsMap.set(row, allItems);\n }\n\n // apply searching\n if (tableState?.searchInput) {\n allItems = this.search(allItems, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n allItems = this.sort(allItems, tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n allItems = this.filter(allItems, tableState);\n }\n\n // Apply paging\n if (currentPage && tableState?.page) {\n const startIndex = (currentPage - 1) * tableState.page.pageSize;\n allItems = allItems.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n itemsMap.set(row, allItems);\n });\n\n return of(itemsMap).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort(items: ExampleItem[], { sortBy }: TableState): ExampleItem[] {\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 5000;\n startIndex = 0;\n allItems: ExampleItem[];\n\n constructor(public level = 0) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.allItems = this.allItems || generateItems(this.totalItems, this.level);\n this.items = [...this.allItems];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(this.items, tableState);\n }\n\n // Apply paging\n if (tableState?.page?.currentPage) {\n const startIndex = (tableState.page.currentPage - 1) * tableState.page.pageSize;\n this.items = this.items.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n return of(this.items).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\nfunction generateItems(size = 5000, level = 0, startIndex = 0): ExampleItem[] {\n return new Array(size).fill(null).map(() => ({\n name: `Laptops ${startIndex++} (Level ${level + 1})`,\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true,\n hasChildren: level < 2 ? true : false\n }));\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => (a ? a[b] : null), object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n", "html": "\n \n\n \n \n\n \n\n \n \n\n \n \n\n\n\n\n" }, + { + "name": "platform-table-initial-loading-example", + "description": "Platform Table Initial Loading", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", + "html": "\n \n\n \n\n \n\n \n\n" + }, + { + "name": "platform-table-editable-rows-example", + "description": "Platform Table Editable Rows", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", + "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" + }, { "name": "table-custom-pagination-example", "description": "Table Custom Pagination", @@ -69369,18 +69447,6 @@ "typescript": "import { ChangeDetectionStrategy, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { PlatformTableModule, TableComponent } from '@fundamental-ngx/platform/table';\nimport {\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableState,\n TableVirtualScrollDirective\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, delay, of } from 'rxjs';\n\n@Component({\n selector: 'fdp-table-custom-pagination-outer-scroll-example',\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule,\n PaginationModule\n ],\n templateUrl: './table-custom-pagination-outer-scroll-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class TableCustomPaginationOuterScrollExampleComponent implements OnInit {\n @ViewChild(TableComponent)\n table: TableComponent;\n\n source: TableDataSource;\n state: TableState;\n currentPage = 1;\n pageSize = 50;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n\n ngOnInit(): void {\n this.state = this._getDefaultState();\n }\n\n pageChanged(currentPage: number): void {\n this.currentPage = currentPage;\n this.table.setCurrentPage(this.currentPage);\n }\n\n itemsPerPageChanged(itemsPerPage: number): void {\n this.pageSize = itemsPerPage;\n this.table.setPageSize(this.pageSize, true);\n }\n\n /**\n * Simulating scroll position update. Once table is initialized app can set back preserved scrolling table\n * position so table can scroll it its original state.\n *\n * Note: Bellow scrollTopPosition property is set based on the scrolling position that was read from\n * this table example. Just some number to showcase this.\n */\n _getDefaultState(): TableState {\n return {\n columnKeys: [],\n sortBy: [],\n filterBy: [],\n groupBy: [],\n columns: [],\n searchInput: {\n category: null,\n text: ''\n },\n freezeToColumn: null,\n freezeToEndColumn: null,\n page: {\n pageSize: this.pageSize,\n currentPage: this.currentPage\n },\n scrollTopPosition: 0\n };\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n children?: ExampleItem[];\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [...ITEMS];\n totalItems = ITEMS.length;\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n this.totalItems = this.items.length;\n\n const currentPage = tableState?.page.currentPage || 1;\n const size = tableState?.page.pageSize || 50;\n const skip = (currentPage - 1) * size;\n\n const paginatedItems = this.items.slice(skip, size * currentPage);\n\n return of(paginatedItems).pipe(delay(1000));\n }\n}\n\n// Example items\nconst ITEMS: ExampleItem[] = new Array(5000).fill(null).map((_, index) => ({\n name: 'Laptops ' + index,\n price: {\n value: Math.floor(Math.random() * 1000),\n currency: 'USD'\n }\n}));\n", "html": "
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n


    \n \n \n \n\n \n\n \n\n \n\n \n \n
    \n" }, - { - "name": "platform-table-editable-rows-example", - "description": "Platform Table Editable Rows", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", - "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" - }, - { - "name": "platform-table-initial-loading-example", - "description": "Platform Table Initial Loading", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", - "html": "\n \n\n \n\n \n\n \n\n" - }, { "name": "platform-table-preserved-state-example", "description": "Platform Table Preserved State", @@ -69614,6 +69680,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule } from '@fundamental-ngx/platform/table';\nimport {\n ChildTableDataSource,\n CollectionNumberFilter,\n CollectionStringFilter,\n FdpTableDataSource,\n FilterType,\n FilterableColumnDataType,\n SortDirection,\n TableChildrenDataProvider,\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableRow,\n TableState,\n TableVirtualScrollDirective,\n TreeTableItem\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, of } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-doc-advanced-scrolling-example',\n templateUrl: './advanced-scrolling-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule\n ]\n})\nexport class AdvancedScrollingExampleComponent {\n source: TableDataSource;\n childSource: ChildTableDataSource;\n readonly filterTypeEnum = FilterType;\n readonly dataTypeEnum = FilterableColumnDataType;\n readonly selectOptions = ['Laptops 1 (Level 1)', 'Laptops 12 (Level 1)'];\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n this.childSource = new ChildTableDataSource(new ChildTableProviderExample());\n }\n}\n\nexport interface ExampleItem extends TreeTableItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n hasChildren: boolean;\n children?: FdpTableDataSource;\n}\n\nclass ChildTableProviderExample extends TableChildrenDataProvider {\n items: Map, ExampleItem[]> = new Map();\n totalItems = 200;\n startIndex = 0;\n allItemsMap = new Map, ExampleItem[]>();\n\n rowChildrenCount(row: TableRow): Observable {\n return of(this.totalItems);\n }\n\n /**\n * Unlike default dataSource, childDataSource accepts array of table rows as a second argument.\n * This is done to load child rows in bulk for the cases when multiple rows being expanded at the same time.\n * @param tableState\n * @param tableRows\n */\n fetch(\n tableState?: TableState,\n tableRows?: TableRow[]\n ): Observable, ExampleItem[]>> {\n const itemsMap = new Map, ExampleItem[]>();\n\n /** Logic of retrieving the child rows for a particular row in tableRows array. */\n tableRows?.forEach((row) => {\n let allItems = this.allItemsMap.get(row);\n const currentPage = tableState?.page.currentPage;\n if (!allItems) {\n allItems = generateItems(this.totalItems, row.level + 1);\n this.allItemsMap.set(row, allItems);\n }\n\n // apply searching\n if (tableState?.searchInput) {\n allItems = this.search(allItems, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n allItems = this.sort(allItems, tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n allItems = this.filter(allItems, tableState);\n }\n\n // Apply paging\n if (currentPage && tableState?.page) {\n const startIndex = (currentPage - 1) * tableState.page.pageSize;\n allItems = allItems.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n itemsMap.set(row, allItems);\n });\n\n return of(itemsMap).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort(items: ExampleItem[], { sortBy }: TableState): ExampleItem[] {\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 5000;\n startIndex = 0;\n allItems: ExampleItem[];\n\n constructor(public level = 0) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.allItems = this.allItems || generateItems(this.totalItems, this.level);\n this.items = [...this.allItems];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(this.items, tableState);\n }\n\n // Apply paging\n if (tableState?.page?.currentPage) {\n const startIndex = (tableState.page.currentPage - 1) * tableState.page.pageSize;\n this.items = this.items.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n return of(this.items).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\nfunction generateItems(size = 5000, level = 0, startIndex = 0): ExampleItem[] {\n return new Array(size).fill(null).map(() => ({\n name: `Laptops ${startIndex++} (Level ${level + 1})`,\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true,\n hasChildren: level < 2 ? true : false\n }));\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => (a ? a[b] : null), object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n", "html": "\n \n\n \n \n\n \n\n \n \n\n \n \n\n\n\n\n" }, + { + "name": "platform-table-initial-loading-example", + "description": "Platform Table Initial Loading", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", + "html": "\n \n\n \n\n \n\n \n\n" + }, + { + "name": "platform-table-editable-rows-example", + "description": "Platform Table Editable Rows", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", + "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" + }, { "name": "table-custom-pagination-example", "description": "Table Custom Pagination", @@ -69626,18 +69704,6 @@ "typescript": "import { ChangeDetectionStrategy, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { PlatformTableModule, TableComponent } from '@fundamental-ngx/platform/table';\nimport {\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableState,\n TableVirtualScrollDirective\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, delay, of } from 'rxjs';\n\n@Component({\n selector: 'fdp-table-custom-pagination-outer-scroll-example',\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule,\n PaginationModule\n ],\n templateUrl: './table-custom-pagination-outer-scroll-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class TableCustomPaginationOuterScrollExampleComponent implements OnInit {\n @ViewChild(TableComponent)\n table: TableComponent;\n\n source: TableDataSource;\n state: TableState;\n currentPage = 1;\n pageSize = 50;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n\n ngOnInit(): void {\n this.state = this._getDefaultState();\n }\n\n pageChanged(currentPage: number): void {\n this.currentPage = currentPage;\n this.table.setCurrentPage(this.currentPage);\n }\n\n itemsPerPageChanged(itemsPerPage: number): void {\n this.pageSize = itemsPerPage;\n this.table.setPageSize(this.pageSize, true);\n }\n\n /**\n * Simulating scroll position update. Once table is initialized app can set back preserved scrolling table\n * position so table can scroll it its original state.\n *\n * Note: Bellow scrollTopPosition property is set based on the scrolling position that was read from\n * this table example. Just some number to showcase this.\n */\n _getDefaultState(): TableState {\n return {\n columnKeys: [],\n sortBy: [],\n filterBy: [],\n groupBy: [],\n columns: [],\n searchInput: {\n category: null,\n text: ''\n },\n freezeToColumn: null,\n freezeToEndColumn: null,\n page: {\n pageSize: this.pageSize,\n currentPage: this.currentPage\n },\n scrollTopPosition: 0\n };\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n children?: ExampleItem[];\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [...ITEMS];\n totalItems = ITEMS.length;\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n this.totalItems = this.items.length;\n\n const currentPage = tableState?.page.currentPage || 1;\n const size = tableState?.page.pageSize || 50;\n const skip = (currentPage - 1) * size;\n\n const paginatedItems = this.items.slice(skip, size * currentPage);\n\n return of(paginatedItems).pipe(delay(1000));\n }\n}\n\n// Example items\nconst ITEMS: ExampleItem[] = new Array(5000).fill(null).map((_, index) => ({\n name: 'Laptops ' + index,\n price: {\n value: Math.floor(Math.random() * 1000),\n currency: 'USD'\n }\n}));\n", "html": "
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n


    \n \n \n \n\n \n\n \n\n \n\n \n \n
    \n" }, - { - "name": "platform-table-editable-rows-example", - "description": "Platform Table Editable Rows", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", - "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" - }, - { - "name": "platform-table-initial-loading-example", - "description": "Platform Table Initial Loading", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", - "html": "\n \n\n \n\n \n\n \n\n" - }, { "name": "platform-table-preserved-state-example", "description": "Platform Table Preserved State", @@ -69864,6 +69930,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule } from '@fundamental-ngx/platform/table';\nimport {\n ChildTableDataSource,\n CollectionNumberFilter,\n CollectionStringFilter,\n FdpTableDataSource,\n FilterType,\n FilterableColumnDataType,\n SortDirection,\n TableChildrenDataProvider,\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableRow,\n TableState,\n TableVirtualScrollDirective,\n TreeTableItem\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, of } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-doc-advanced-scrolling-example',\n templateUrl: './advanced-scrolling-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule\n ]\n})\nexport class AdvancedScrollingExampleComponent {\n source: TableDataSource;\n childSource: ChildTableDataSource;\n readonly filterTypeEnum = FilterType;\n readonly dataTypeEnum = FilterableColumnDataType;\n readonly selectOptions = ['Laptops 1 (Level 1)', 'Laptops 12 (Level 1)'];\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n this.childSource = new ChildTableDataSource(new ChildTableProviderExample());\n }\n}\n\nexport interface ExampleItem extends TreeTableItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n hasChildren: boolean;\n children?: FdpTableDataSource;\n}\n\nclass ChildTableProviderExample extends TableChildrenDataProvider {\n items: Map, ExampleItem[]> = new Map();\n totalItems = 200;\n startIndex = 0;\n allItemsMap = new Map, ExampleItem[]>();\n\n rowChildrenCount(row: TableRow): Observable {\n return of(this.totalItems);\n }\n\n /**\n * Unlike default dataSource, childDataSource accepts array of table rows as a second argument.\n * This is done to load child rows in bulk for the cases when multiple rows being expanded at the same time.\n * @param tableState\n * @param tableRows\n */\n fetch(\n tableState?: TableState,\n tableRows?: TableRow[]\n ): Observable, ExampleItem[]>> {\n const itemsMap = new Map, ExampleItem[]>();\n\n /** Logic of retrieving the child rows for a particular row in tableRows array. */\n tableRows?.forEach((row) => {\n let allItems = this.allItemsMap.get(row);\n const currentPage = tableState?.page.currentPage;\n if (!allItems) {\n allItems = generateItems(this.totalItems, row.level + 1);\n this.allItemsMap.set(row, allItems);\n }\n\n // apply searching\n if (tableState?.searchInput) {\n allItems = this.search(allItems, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n allItems = this.sort(allItems, tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n allItems = this.filter(allItems, tableState);\n }\n\n // Apply paging\n if (currentPage && tableState?.page) {\n const startIndex = (currentPage - 1) * tableState.page.pageSize;\n allItems = allItems.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n itemsMap.set(row, allItems);\n });\n\n return of(itemsMap).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort(items: ExampleItem[], { sortBy }: TableState): ExampleItem[] {\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 5000;\n startIndex = 0;\n allItems: ExampleItem[];\n\n constructor(public level = 0) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.allItems = this.allItems || generateItems(this.totalItems, this.level);\n this.items = [...this.allItems];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(this.items, tableState);\n }\n\n // Apply paging\n if (tableState?.page?.currentPage) {\n const startIndex = (tableState.page.currentPage - 1) * tableState.page.pageSize;\n this.items = this.items.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n return of(this.items).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\nfunction generateItems(size = 5000, level = 0, startIndex = 0): ExampleItem[] {\n return new Array(size).fill(null).map(() => ({\n name: `Laptops ${startIndex++} (Level ${level + 1})`,\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true,\n hasChildren: level < 2 ? true : false\n }));\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => (a ? a[b] : null), object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n", "html": "\n \n\n \n \n\n \n\n \n \n\n \n \n\n\n\n\n" }, + { + "name": "platform-table-initial-loading-example", + "description": "Platform Table Initial Loading", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", + "html": "\n \n\n \n\n \n\n \n\n" + }, + { + "name": "platform-table-editable-rows-example", + "description": "Platform Table Editable Rows", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", + "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" + }, { "name": "table-custom-pagination-example", "description": "Table Custom Pagination", @@ -69876,18 +69954,6 @@ "typescript": "import { ChangeDetectionStrategy, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { PlatformTableModule, TableComponent } from '@fundamental-ngx/platform/table';\nimport {\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableState,\n TableVirtualScrollDirective\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, delay, of } from 'rxjs';\n\n@Component({\n selector: 'fdp-table-custom-pagination-outer-scroll-example',\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule,\n PaginationModule\n ],\n templateUrl: './table-custom-pagination-outer-scroll-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class TableCustomPaginationOuterScrollExampleComponent implements OnInit {\n @ViewChild(TableComponent)\n table: TableComponent;\n\n source: TableDataSource;\n state: TableState;\n currentPage = 1;\n pageSize = 50;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n\n ngOnInit(): void {\n this.state = this._getDefaultState();\n }\n\n pageChanged(currentPage: number): void {\n this.currentPage = currentPage;\n this.table.setCurrentPage(this.currentPage);\n }\n\n itemsPerPageChanged(itemsPerPage: number): void {\n this.pageSize = itemsPerPage;\n this.table.setPageSize(this.pageSize, true);\n }\n\n /**\n * Simulating scroll position update. Once table is initialized app can set back preserved scrolling table\n * position so table can scroll it its original state.\n *\n * Note: Bellow scrollTopPosition property is set based on the scrolling position that was read from\n * this table example. Just some number to showcase this.\n */\n _getDefaultState(): TableState {\n return {\n columnKeys: [],\n sortBy: [],\n filterBy: [],\n groupBy: [],\n columns: [],\n searchInput: {\n category: null,\n text: ''\n },\n freezeToColumn: null,\n freezeToEndColumn: null,\n page: {\n pageSize: this.pageSize,\n currentPage: this.currentPage\n },\n scrollTopPosition: 0\n };\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n children?: ExampleItem[];\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [...ITEMS];\n totalItems = ITEMS.length;\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n this.totalItems = this.items.length;\n\n const currentPage = tableState?.page.currentPage || 1;\n const size = tableState?.page.pageSize || 50;\n const skip = (currentPage - 1) * size;\n\n const paginatedItems = this.items.slice(skip, size * currentPage);\n\n return of(paginatedItems).pipe(delay(1000));\n }\n}\n\n// Example items\nconst ITEMS: ExampleItem[] = new Array(5000).fill(null).map((_, index) => ({\n name: 'Laptops ' + index,\n price: {\n value: Math.floor(Math.random() * 1000),\n currency: 'USD'\n }\n}));\n", "html": "
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n


    \n \n \n \n\n \n\n \n\n \n\n \n \n
    \n" }, - { - "name": "platform-table-editable-rows-example", - "description": "Platform Table Editable Rows", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", - "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" - }, - { - "name": "platform-table-initial-loading-example", - "description": "Platform Table Initial Loading", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", - "html": "\n \n\n \n\n \n\n \n\n" - }, { "name": "platform-table-preserved-state-example", "description": "Platform Table Preserved State", @@ -70114,6 +70180,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule } from '@fundamental-ngx/platform/table';\nimport {\n ChildTableDataSource,\n CollectionNumberFilter,\n CollectionStringFilter,\n FdpTableDataSource,\n FilterType,\n FilterableColumnDataType,\n SortDirection,\n TableChildrenDataProvider,\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableRow,\n TableState,\n TableVirtualScrollDirective,\n TreeTableItem\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, of } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-doc-advanced-scrolling-example',\n templateUrl: './advanced-scrolling-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule\n ]\n})\nexport class AdvancedScrollingExampleComponent {\n source: TableDataSource;\n childSource: ChildTableDataSource;\n readonly filterTypeEnum = FilterType;\n readonly dataTypeEnum = FilterableColumnDataType;\n readonly selectOptions = ['Laptops 1 (Level 1)', 'Laptops 12 (Level 1)'];\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n this.childSource = new ChildTableDataSource(new ChildTableProviderExample());\n }\n}\n\nexport interface ExampleItem extends TreeTableItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n hasChildren: boolean;\n children?: FdpTableDataSource;\n}\n\nclass ChildTableProviderExample extends TableChildrenDataProvider {\n items: Map, ExampleItem[]> = new Map();\n totalItems = 200;\n startIndex = 0;\n allItemsMap = new Map, ExampleItem[]>();\n\n rowChildrenCount(row: TableRow): Observable {\n return of(this.totalItems);\n }\n\n /**\n * Unlike default dataSource, childDataSource accepts array of table rows as a second argument.\n * This is done to load child rows in bulk for the cases when multiple rows being expanded at the same time.\n * @param tableState\n * @param tableRows\n */\n fetch(\n tableState?: TableState,\n tableRows?: TableRow[]\n ): Observable, ExampleItem[]>> {\n const itemsMap = new Map, ExampleItem[]>();\n\n /** Logic of retrieving the child rows for a particular row in tableRows array. */\n tableRows?.forEach((row) => {\n let allItems = this.allItemsMap.get(row);\n const currentPage = tableState?.page.currentPage;\n if (!allItems) {\n allItems = generateItems(this.totalItems, row.level + 1);\n this.allItemsMap.set(row, allItems);\n }\n\n // apply searching\n if (tableState?.searchInput) {\n allItems = this.search(allItems, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n allItems = this.sort(allItems, tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n allItems = this.filter(allItems, tableState);\n }\n\n // Apply paging\n if (currentPage && tableState?.page) {\n const startIndex = (currentPage - 1) * tableState.page.pageSize;\n allItems = allItems.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n itemsMap.set(row, allItems);\n });\n\n return of(itemsMap).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort(items: ExampleItem[], { sortBy }: TableState): ExampleItem[] {\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 5000;\n startIndex = 0;\n allItems: ExampleItem[];\n\n constructor(public level = 0) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.allItems = this.allItems || generateItems(this.totalItems, this.level);\n this.items = [...this.allItems];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(this.items, tableState);\n }\n\n // Apply paging\n if (tableState?.page?.currentPage) {\n const startIndex = (tableState.page.currentPage - 1) * tableState.page.pageSize;\n this.items = this.items.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n return of(this.items).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\nfunction generateItems(size = 5000, level = 0, startIndex = 0): ExampleItem[] {\n return new Array(size).fill(null).map(() => ({\n name: `Laptops ${startIndex++} (Level ${level + 1})`,\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true,\n hasChildren: level < 2 ? true : false\n }));\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => (a ? a[b] : null), object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n", "html": "\n \n\n \n \n\n \n\n \n \n\n \n \n\n\n\n\n" }, + { + "name": "platform-table-initial-loading-example", + "description": "Platform Table Initial Loading", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", + "html": "\n \n\n \n\n \n\n \n\n" + }, + { + "name": "platform-table-editable-rows-example", + "description": "Platform Table Editable Rows", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", + "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" + }, { "name": "table-custom-pagination-example", "description": "Table Custom Pagination", @@ -70126,18 +70204,6 @@ "typescript": "import { ChangeDetectionStrategy, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { PlatformTableModule, TableComponent } from '@fundamental-ngx/platform/table';\nimport {\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableState,\n TableVirtualScrollDirective\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, delay, of } from 'rxjs';\n\n@Component({\n selector: 'fdp-table-custom-pagination-outer-scroll-example',\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule,\n PaginationModule\n ],\n templateUrl: './table-custom-pagination-outer-scroll-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class TableCustomPaginationOuterScrollExampleComponent implements OnInit {\n @ViewChild(TableComponent)\n table: TableComponent;\n\n source: TableDataSource;\n state: TableState;\n currentPage = 1;\n pageSize = 50;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n\n ngOnInit(): void {\n this.state = this._getDefaultState();\n }\n\n pageChanged(currentPage: number): void {\n this.currentPage = currentPage;\n this.table.setCurrentPage(this.currentPage);\n }\n\n itemsPerPageChanged(itemsPerPage: number): void {\n this.pageSize = itemsPerPage;\n this.table.setPageSize(this.pageSize, true);\n }\n\n /**\n * Simulating scroll position update. Once table is initialized app can set back preserved scrolling table\n * position so table can scroll it its original state.\n *\n * Note: Bellow scrollTopPosition property is set based on the scrolling position that was read from\n * this table example. Just some number to showcase this.\n */\n _getDefaultState(): TableState {\n return {\n columnKeys: [],\n sortBy: [],\n filterBy: [],\n groupBy: [],\n columns: [],\n searchInput: {\n category: null,\n text: ''\n },\n freezeToColumn: null,\n freezeToEndColumn: null,\n page: {\n pageSize: this.pageSize,\n currentPage: this.currentPage\n },\n scrollTopPosition: 0\n };\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n children?: ExampleItem[];\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [...ITEMS];\n totalItems = ITEMS.length;\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n this.totalItems = this.items.length;\n\n const currentPage = tableState?.page.currentPage || 1;\n const size = tableState?.page.pageSize || 50;\n const skip = (currentPage - 1) * size;\n\n const paginatedItems = this.items.slice(skip, size * currentPage);\n\n return of(paginatedItems).pipe(delay(1000));\n }\n}\n\n// Example items\nconst ITEMS: ExampleItem[] = new Array(5000).fill(null).map((_, index) => ({\n name: 'Laptops ' + index,\n price: {\n value: Math.floor(Math.random() * 1000),\n currency: 'USD'\n }\n}));\n", "html": "
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n


    \n \n \n \n\n \n\n \n\n \n\n \n \n
    \n" }, - { - "name": "platform-table-editable-rows-example", - "description": "Platform Table Editable Rows", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", - "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" - }, - { - "name": "platform-table-initial-loading-example", - "description": "Platform Table Initial Loading", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", - "html": "\n \n\n \n\n \n\n \n\n" - }, { "name": "platform-table-preserved-state-example", "description": "Platform Table Preserved State", @@ -70371,6 +70437,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule } from '@fundamental-ngx/platform/table';\nimport {\n ChildTableDataSource,\n CollectionNumberFilter,\n CollectionStringFilter,\n FdpTableDataSource,\n FilterType,\n FilterableColumnDataType,\n SortDirection,\n TableChildrenDataProvider,\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableRow,\n TableState,\n TableVirtualScrollDirective,\n TreeTableItem\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, of } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-doc-advanced-scrolling-example',\n templateUrl: './advanced-scrolling-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule\n ]\n})\nexport class AdvancedScrollingExampleComponent {\n source: TableDataSource;\n childSource: ChildTableDataSource;\n readonly filterTypeEnum = FilterType;\n readonly dataTypeEnum = FilterableColumnDataType;\n readonly selectOptions = ['Laptops 1 (Level 1)', 'Laptops 12 (Level 1)'];\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n this.childSource = new ChildTableDataSource(new ChildTableProviderExample());\n }\n}\n\nexport interface ExampleItem extends TreeTableItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n hasChildren: boolean;\n children?: FdpTableDataSource;\n}\n\nclass ChildTableProviderExample extends TableChildrenDataProvider {\n items: Map, ExampleItem[]> = new Map();\n totalItems = 200;\n startIndex = 0;\n allItemsMap = new Map, ExampleItem[]>();\n\n rowChildrenCount(row: TableRow): Observable {\n return of(this.totalItems);\n }\n\n /**\n * Unlike default dataSource, childDataSource accepts array of table rows as a second argument.\n * This is done to load child rows in bulk for the cases when multiple rows being expanded at the same time.\n * @param tableState\n * @param tableRows\n */\n fetch(\n tableState?: TableState,\n tableRows?: TableRow[]\n ): Observable, ExampleItem[]>> {\n const itemsMap = new Map, ExampleItem[]>();\n\n /** Logic of retrieving the child rows for a particular row in tableRows array. */\n tableRows?.forEach((row) => {\n let allItems = this.allItemsMap.get(row);\n const currentPage = tableState?.page.currentPage;\n if (!allItems) {\n allItems = generateItems(this.totalItems, row.level + 1);\n this.allItemsMap.set(row, allItems);\n }\n\n // apply searching\n if (tableState?.searchInput) {\n allItems = this.search(allItems, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n allItems = this.sort(allItems, tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n allItems = this.filter(allItems, tableState);\n }\n\n // Apply paging\n if (currentPage && tableState?.page) {\n const startIndex = (currentPage - 1) * tableState.page.pageSize;\n allItems = allItems.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n itemsMap.set(row, allItems);\n });\n\n return of(itemsMap).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort(items: ExampleItem[], { sortBy }: TableState): ExampleItem[] {\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 5000;\n startIndex = 0;\n allItems: ExampleItem[];\n\n constructor(public level = 0) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.allItems = this.allItems || generateItems(this.totalItems, this.level);\n this.items = [...this.allItems];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(this.items, tableState);\n }\n\n // Apply paging\n if (tableState?.page?.currentPage) {\n const startIndex = (tableState.page.currentPage - 1) * tableState.page.pageSize;\n this.items = this.items.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n return of(this.items).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\nfunction generateItems(size = 5000, level = 0, startIndex = 0): ExampleItem[] {\n return new Array(size).fill(null).map(() => ({\n name: `Laptops ${startIndex++} (Level ${level + 1})`,\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true,\n hasChildren: level < 2 ? true : false\n }));\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => (a ? a[b] : null), object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n", "html": "\n \n\n \n \n\n \n\n \n \n\n \n \n\n\n\n\n" }, + { + "name": "platform-table-initial-loading-example", + "description": "Platform Table Initial Loading", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", + "html": "\n \n\n \n\n \n\n \n\n" + }, + { + "name": "platform-table-editable-rows-example", + "description": "Platform Table Editable Rows", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", + "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" + }, { "name": "table-custom-pagination-example", "description": "Table Custom Pagination", @@ -70383,18 +70461,6 @@ "typescript": "import { ChangeDetectionStrategy, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { PlatformTableModule, TableComponent } from '@fundamental-ngx/platform/table';\nimport {\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableState,\n TableVirtualScrollDirective\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, delay, of } from 'rxjs';\n\n@Component({\n selector: 'fdp-table-custom-pagination-outer-scroll-example',\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule,\n PaginationModule\n ],\n templateUrl: './table-custom-pagination-outer-scroll-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class TableCustomPaginationOuterScrollExampleComponent implements OnInit {\n @ViewChild(TableComponent)\n table: TableComponent;\n\n source: TableDataSource;\n state: TableState;\n currentPage = 1;\n pageSize = 50;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n\n ngOnInit(): void {\n this.state = this._getDefaultState();\n }\n\n pageChanged(currentPage: number): void {\n this.currentPage = currentPage;\n this.table.setCurrentPage(this.currentPage);\n }\n\n itemsPerPageChanged(itemsPerPage: number): void {\n this.pageSize = itemsPerPage;\n this.table.setPageSize(this.pageSize, true);\n }\n\n /**\n * Simulating scroll position update. Once table is initialized app can set back preserved scrolling table\n * position so table can scroll it its original state.\n *\n * Note: Bellow scrollTopPosition property is set based on the scrolling position that was read from\n * this table example. Just some number to showcase this.\n */\n _getDefaultState(): TableState {\n return {\n columnKeys: [],\n sortBy: [],\n filterBy: [],\n groupBy: [],\n columns: [],\n searchInput: {\n category: null,\n text: ''\n },\n freezeToColumn: null,\n freezeToEndColumn: null,\n page: {\n pageSize: this.pageSize,\n currentPage: this.currentPage\n },\n scrollTopPosition: 0\n };\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n children?: ExampleItem[];\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [...ITEMS];\n totalItems = ITEMS.length;\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n this.totalItems = this.items.length;\n\n const currentPage = tableState?.page.currentPage || 1;\n const size = tableState?.page.pageSize || 50;\n const skip = (currentPage - 1) * size;\n\n const paginatedItems = this.items.slice(skip, size * currentPage);\n\n return of(paginatedItems).pipe(delay(1000));\n }\n}\n\n// Example items\nconst ITEMS: ExampleItem[] = new Array(5000).fill(null).map((_, index) => ({\n name: 'Laptops ' + index,\n price: {\n value: Math.floor(Math.random() * 1000),\n currency: 'USD'\n }\n}));\n", "html": "
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n


    \n \n \n \n\n \n\n \n\n \n\n \n \n
    \n" }, - { - "name": "platform-table-editable-rows-example", - "description": "Platform Table Editable Rows", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", - "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" - }, - { - "name": "platform-table-initial-loading-example", - "description": "Platform Table Initial Loading", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", - "html": "\n \n\n \n\n \n\n \n\n" - }, { "name": "platform-table-preserved-state-example", "description": "Platform Table Preserved State", @@ -70745,6 +70811,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule } from '@fundamental-ngx/platform/table';\nimport {\n ChildTableDataSource,\n CollectionNumberFilter,\n CollectionStringFilter,\n FdpTableDataSource,\n FilterType,\n FilterableColumnDataType,\n SortDirection,\n TableChildrenDataProvider,\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableRow,\n TableState,\n TableVirtualScrollDirective,\n TreeTableItem\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, of } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-doc-advanced-scrolling-example',\n templateUrl: './advanced-scrolling-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule\n ]\n})\nexport class AdvancedScrollingExampleComponent {\n source: TableDataSource;\n childSource: ChildTableDataSource;\n readonly filterTypeEnum = FilterType;\n readonly dataTypeEnum = FilterableColumnDataType;\n readonly selectOptions = ['Laptops 1 (Level 1)', 'Laptops 12 (Level 1)'];\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n this.childSource = new ChildTableDataSource(new ChildTableProviderExample());\n }\n}\n\nexport interface ExampleItem extends TreeTableItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n hasChildren: boolean;\n children?: FdpTableDataSource;\n}\n\nclass ChildTableProviderExample extends TableChildrenDataProvider {\n items: Map, ExampleItem[]> = new Map();\n totalItems = 200;\n startIndex = 0;\n allItemsMap = new Map, ExampleItem[]>();\n\n rowChildrenCount(row: TableRow): Observable {\n return of(this.totalItems);\n }\n\n /**\n * Unlike default dataSource, childDataSource accepts array of table rows as a second argument.\n * This is done to load child rows in bulk for the cases when multiple rows being expanded at the same time.\n * @param tableState\n * @param tableRows\n */\n fetch(\n tableState?: TableState,\n tableRows?: TableRow[]\n ): Observable, ExampleItem[]>> {\n const itemsMap = new Map, ExampleItem[]>();\n\n /** Logic of retrieving the child rows for a particular row in tableRows array. */\n tableRows?.forEach((row) => {\n let allItems = this.allItemsMap.get(row);\n const currentPage = tableState?.page.currentPage;\n if (!allItems) {\n allItems = generateItems(this.totalItems, row.level + 1);\n this.allItemsMap.set(row, allItems);\n }\n\n // apply searching\n if (tableState?.searchInput) {\n allItems = this.search(allItems, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n allItems = this.sort(allItems, tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n allItems = this.filter(allItems, tableState);\n }\n\n // Apply paging\n if (currentPage && tableState?.page) {\n const startIndex = (currentPage - 1) * tableState.page.pageSize;\n allItems = allItems.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n itemsMap.set(row, allItems);\n });\n\n return of(itemsMap).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort(items: ExampleItem[], { sortBy }: TableState): ExampleItem[] {\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 5000;\n startIndex = 0;\n allItems: ExampleItem[];\n\n constructor(public level = 0) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.allItems = this.allItems || generateItems(this.totalItems, this.level);\n this.items = [...this.allItems];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(this.items, tableState);\n }\n\n // Apply paging\n if (tableState?.page?.currentPage) {\n const startIndex = (tableState.page.currentPage - 1) * tableState.page.pageSize;\n this.items = this.items.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n return of(this.items).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\nfunction generateItems(size = 5000, level = 0, startIndex = 0): ExampleItem[] {\n return new Array(size).fill(null).map(() => ({\n name: `Laptops ${startIndex++} (Level ${level + 1})`,\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true,\n hasChildren: level < 2 ? true : false\n }));\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => (a ? a[b] : null), object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n", "html": "\n \n\n \n \n\n \n\n \n \n\n \n \n\n\n\n\n" }, + { + "name": "platform-table-initial-loading-example", + "description": "Platform Table Initial Loading", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", + "html": "\n \n\n \n\n \n\n \n\n" + }, + { + "name": "platform-table-editable-rows-example", + "description": "Platform Table Editable Rows", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", + "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" + }, { "name": "table-custom-pagination-example", "description": "Table Custom Pagination", @@ -70757,18 +70835,6 @@ "typescript": "import { ChangeDetectionStrategy, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { PlatformTableModule, TableComponent } from '@fundamental-ngx/platform/table';\nimport {\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableState,\n TableVirtualScrollDirective\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, delay, of } from 'rxjs';\n\n@Component({\n selector: 'fdp-table-custom-pagination-outer-scroll-example',\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule,\n PaginationModule\n ],\n templateUrl: './table-custom-pagination-outer-scroll-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class TableCustomPaginationOuterScrollExampleComponent implements OnInit {\n @ViewChild(TableComponent)\n table: TableComponent;\n\n source: TableDataSource;\n state: TableState;\n currentPage = 1;\n pageSize = 50;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n\n ngOnInit(): void {\n this.state = this._getDefaultState();\n }\n\n pageChanged(currentPage: number): void {\n this.currentPage = currentPage;\n this.table.setCurrentPage(this.currentPage);\n }\n\n itemsPerPageChanged(itemsPerPage: number): void {\n this.pageSize = itemsPerPage;\n this.table.setPageSize(this.pageSize, true);\n }\n\n /**\n * Simulating scroll position update. Once table is initialized app can set back preserved scrolling table\n * position so table can scroll it its original state.\n *\n * Note: Bellow scrollTopPosition property is set based on the scrolling position that was read from\n * this table example. Just some number to showcase this.\n */\n _getDefaultState(): TableState {\n return {\n columnKeys: [],\n sortBy: [],\n filterBy: [],\n groupBy: [],\n columns: [],\n searchInput: {\n category: null,\n text: ''\n },\n freezeToColumn: null,\n freezeToEndColumn: null,\n page: {\n pageSize: this.pageSize,\n currentPage: this.currentPage\n },\n scrollTopPosition: 0\n };\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n children?: ExampleItem[];\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [...ITEMS];\n totalItems = ITEMS.length;\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n this.totalItems = this.items.length;\n\n const currentPage = tableState?.page.currentPage || 1;\n const size = tableState?.page.pageSize || 50;\n const skip = (currentPage - 1) * size;\n\n const paginatedItems = this.items.slice(skip, size * currentPage);\n\n return of(paginatedItems).pipe(delay(1000));\n }\n}\n\n// Example items\nconst ITEMS: ExampleItem[] = new Array(5000).fill(null).map((_, index) => ({\n name: 'Laptops ' + index,\n price: {\n value: Math.floor(Math.random() * 1000),\n currency: 'USD'\n }\n}));\n", "html": "
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n


    \n \n \n \n\n \n\n \n\n \n\n \n \n
    \n" }, - { - "name": "platform-table-editable-rows-example", - "description": "Platform Table Editable Rows", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", - "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" - }, - { - "name": "platform-table-initial-loading-example", - "description": "Platform Table Initial Loading", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", - "html": "\n \n\n \n\n \n\n \n\n" - }, { "name": "platform-table-preserved-state-example", "description": "Platform Table Preserved State", @@ -70995,6 +71061,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule } from '@fundamental-ngx/platform/table';\nimport {\n ChildTableDataSource,\n CollectionNumberFilter,\n CollectionStringFilter,\n FdpTableDataSource,\n FilterType,\n FilterableColumnDataType,\n SortDirection,\n TableChildrenDataProvider,\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableRow,\n TableState,\n TableVirtualScrollDirective,\n TreeTableItem\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, of } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-doc-advanced-scrolling-example',\n templateUrl: './advanced-scrolling-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule\n ]\n})\nexport class AdvancedScrollingExampleComponent {\n source: TableDataSource;\n childSource: ChildTableDataSource;\n readonly filterTypeEnum = FilterType;\n readonly dataTypeEnum = FilterableColumnDataType;\n readonly selectOptions = ['Laptops 1 (Level 1)', 'Laptops 12 (Level 1)'];\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n this.childSource = new ChildTableDataSource(new ChildTableProviderExample());\n }\n}\n\nexport interface ExampleItem extends TreeTableItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n hasChildren: boolean;\n children?: FdpTableDataSource;\n}\n\nclass ChildTableProviderExample extends TableChildrenDataProvider {\n items: Map, ExampleItem[]> = new Map();\n totalItems = 200;\n startIndex = 0;\n allItemsMap = new Map, ExampleItem[]>();\n\n rowChildrenCount(row: TableRow): Observable {\n return of(this.totalItems);\n }\n\n /**\n * Unlike default dataSource, childDataSource accepts array of table rows as a second argument.\n * This is done to load child rows in bulk for the cases when multiple rows being expanded at the same time.\n * @param tableState\n * @param tableRows\n */\n fetch(\n tableState?: TableState,\n tableRows?: TableRow[]\n ): Observable, ExampleItem[]>> {\n const itemsMap = new Map, ExampleItem[]>();\n\n /** Logic of retrieving the child rows for a particular row in tableRows array. */\n tableRows?.forEach((row) => {\n let allItems = this.allItemsMap.get(row);\n const currentPage = tableState?.page.currentPage;\n if (!allItems) {\n allItems = generateItems(this.totalItems, row.level + 1);\n this.allItemsMap.set(row, allItems);\n }\n\n // apply searching\n if (tableState?.searchInput) {\n allItems = this.search(allItems, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n allItems = this.sort(allItems, tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n allItems = this.filter(allItems, tableState);\n }\n\n // Apply paging\n if (currentPage && tableState?.page) {\n const startIndex = (currentPage - 1) * tableState.page.pageSize;\n allItems = allItems.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n itemsMap.set(row, allItems);\n });\n\n return of(itemsMap).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort(items: ExampleItem[], { sortBy }: TableState): ExampleItem[] {\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 5000;\n startIndex = 0;\n allItems: ExampleItem[];\n\n constructor(public level = 0) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.allItems = this.allItems || generateItems(this.totalItems, this.level);\n this.items = [...this.allItems];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(this.items, tableState);\n }\n\n // Apply paging\n if (tableState?.page?.currentPage) {\n const startIndex = (tableState.page.currentPage - 1) * tableState.page.pageSize;\n this.items = this.items.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n return of(this.items).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\nfunction generateItems(size = 5000, level = 0, startIndex = 0): ExampleItem[] {\n return new Array(size).fill(null).map(() => ({\n name: `Laptops ${startIndex++} (Level ${level + 1})`,\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true,\n hasChildren: level < 2 ? true : false\n }));\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => (a ? a[b] : null), object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n", "html": "\n \n\n \n \n\n \n\n \n \n\n \n \n\n\n\n\n" }, + { + "name": "platform-table-initial-loading-example", + "description": "Platform Table Initial Loading", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", + "html": "\n \n\n \n\n \n\n \n\n" + }, + { + "name": "platform-table-editable-rows-example", + "description": "Platform Table Editable Rows", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", + "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" + }, { "name": "table-custom-pagination-example", "description": "Table Custom Pagination", @@ -71007,18 +71085,6 @@ "typescript": "import { ChangeDetectionStrategy, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { PlatformTableModule, TableComponent } from '@fundamental-ngx/platform/table';\nimport {\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableState,\n TableVirtualScrollDirective\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, delay, of } from 'rxjs';\n\n@Component({\n selector: 'fdp-table-custom-pagination-outer-scroll-example',\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule,\n PaginationModule\n ],\n templateUrl: './table-custom-pagination-outer-scroll-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class TableCustomPaginationOuterScrollExampleComponent implements OnInit {\n @ViewChild(TableComponent)\n table: TableComponent;\n\n source: TableDataSource;\n state: TableState;\n currentPage = 1;\n pageSize = 50;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n\n ngOnInit(): void {\n this.state = this._getDefaultState();\n }\n\n pageChanged(currentPage: number): void {\n this.currentPage = currentPage;\n this.table.setCurrentPage(this.currentPage);\n }\n\n itemsPerPageChanged(itemsPerPage: number): void {\n this.pageSize = itemsPerPage;\n this.table.setPageSize(this.pageSize, true);\n }\n\n /**\n * Simulating scroll position update. Once table is initialized app can set back preserved scrolling table\n * position so table can scroll it its original state.\n *\n * Note: Bellow scrollTopPosition property is set based on the scrolling position that was read from\n * this table example. Just some number to showcase this.\n */\n _getDefaultState(): TableState {\n return {\n columnKeys: [],\n sortBy: [],\n filterBy: [],\n groupBy: [],\n columns: [],\n searchInput: {\n category: null,\n text: ''\n },\n freezeToColumn: null,\n freezeToEndColumn: null,\n page: {\n pageSize: this.pageSize,\n currentPage: this.currentPage\n },\n scrollTopPosition: 0\n };\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n children?: ExampleItem[];\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [...ITEMS];\n totalItems = ITEMS.length;\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n this.totalItems = this.items.length;\n\n const currentPage = tableState?.page.currentPage || 1;\n const size = tableState?.page.pageSize || 50;\n const skip = (currentPage - 1) * size;\n\n const paginatedItems = this.items.slice(skip, size * currentPage);\n\n return of(paginatedItems).pipe(delay(1000));\n }\n}\n\n// Example items\nconst ITEMS: ExampleItem[] = new Array(5000).fill(null).map((_, index) => ({\n name: 'Laptops ' + index,\n price: {\n value: Math.floor(Math.random() * 1000),\n currency: 'USD'\n }\n}));\n", "html": "
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n


    \n \n \n \n\n \n\n \n\n \n\n \n \n
    \n" }, - { - "name": "platform-table-editable-rows-example", - "description": "Platform Table Editable Rows", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", - "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" - }, - { - "name": "platform-table-initial-loading-example", - "description": "Platform Table Initial Loading", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", - "html": "\n \n\n \n\n \n\n \n\n" - }, { "name": "platform-table-preserved-state-example", "description": "Platform Table Preserved State", @@ -71245,6 +71311,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule } from '@fundamental-ngx/platform/table';\nimport {\n ChildTableDataSource,\n CollectionNumberFilter,\n CollectionStringFilter,\n FdpTableDataSource,\n FilterType,\n FilterableColumnDataType,\n SortDirection,\n TableChildrenDataProvider,\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableRow,\n TableState,\n TableVirtualScrollDirective,\n TreeTableItem\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, of } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-doc-advanced-scrolling-example',\n templateUrl: './advanced-scrolling-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule\n ]\n})\nexport class AdvancedScrollingExampleComponent {\n source: TableDataSource;\n childSource: ChildTableDataSource;\n readonly filterTypeEnum = FilterType;\n readonly dataTypeEnum = FilterableColumnDataType;\n readonly selectOptions = ['Laptops 1 (Level 1)', 'Laptops 12 (Level 1)'];\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n this.childSource = new ChildTableDataSource(new ChildTableProviderExample());\n }\n}\n\nexport interface ExampleItem extends TreeTableItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n hasChildren: boolean;\n children?: FdpTableDataSource;\n}\n\nclass ChildTableProviderExample extends TableChildrenDataProvider {\n items: Map, ExampleItem[]> = new Map();\n totalItems = 200;\n startIndex = 0;\n allItemsMap = new Map, ExampleItem[]>();\n\n rowChildrenCount(row: TableRow): Observable {\n return of(this.totalItems);\n }\n\n /**\n * Unlike default dataSource, childDataSource accepts array of table rows as a second argument.\n * This is done to load child rows in bulk for the cases when multiple rows being expanded at the same time.\n * @param tableState\n * @param tableRows\n */\n fetch(\n tableState?: TableState,\n tableRows?: TableRow[]\n ): Observable, ExampleItem[]>> {\n const itemsMap = new Map, ExampleItem[]>();\n\n /** Logic of retrieving the child rows for a particular row in tableRows array. */\n tableRows?.forEach((row) => {\n let allItems = this.allItemsMap.get(row);\n const currentPage = tableState?.page.currentPage;\n if (!allItems) {\n allItems = generateItems(this.totalItems, row.level + 1);\n this.allItemsMap.set(row, allItems);\n }\n\n // apply searching\n if (tableState?.searchInput) {\n allItems = this.search(allItems, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n allItems = this.sort(allItems, tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n allItems = this.filter(allItems, tableState);\n }\n\n // Apply paging\n if (currentPage && tableState?.page) {\n const startIndex = (currentPage - 1) * tableState.page.pageSize;\n allItems = allItems.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n itemsMap.set(row, allItems);\n });\n\n return of(itemsMap).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort(items: ExampleItem[], { sortBy }: TableState): ExampleItem[] {\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 5000;\n startIndex = 0;\n allItems: ExampleItem[];\n\n constructor(public level = 0) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.allItems = this.allItems || generateItems(this.totalItems, this.level);\n this.items = [...this.allItems];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(this.items, tableState);\n }\n\n // Apply paging\n if (tableState?.page?.currentPage) {\n const startIndex = (tableState.page.currentPage - 1) * tableState.page.pageSize;\n this.items = this.items.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n return of(this.items).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\nfunction generateItems(size = 5000, level = 0, startIndex = 0): ExampleItem[] {\n return new Array(size).fill(null).map(() => ({\n name: `Laptops ${startIndex++} (Level ${level + 1})`,\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true,\n hasChildren: level < 2 ? true : false\n }));\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => (a ? a[b] : null), object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n", "html": "\n \n\n \n \n\n \n\n \n \n\n \n \n\n\n\n\n" }, + { + "name": "platform-table-initial-loading-example", + "description": "Platform Table Initial Loading", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", + "html": "\n \n\n \n\n \n\n \n\n" + }, + { + "name": "platform-table-editable-rows-example", + "description": "Platform Table Editable Rows", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", + "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" + }, { "name": "table-custom-pagination-example", "description": "Table Custom Pagination", @@ -71257,18 +71335,6 @@ "typescript": "import { ChangeDetectionStrategy, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { PlatformTableModule, TableComponent } from '@fundamental-ngx/platform/table';\nimport {\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableState,\n TableVirtualScrollDirective\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, delay, of } from 'rxjs';\n\n@Component({\n selector: 'fdp-table-custom-pagination-outer-scroll-example',\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule,\n PaginationModule\n ],\n templateUrl: './table-custom-pagination-outer-scroll-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class TableCustomPaginationOuterScrollExampleComponent implements OnInit {\n @ViewChild(TableComponent)\n table: TableComponent;\n\n source: TableDataSource;\n state: TableState;\n currentPage = 1;\n pageSize = 50;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n\n ngOnInit(): void {\n this.state = this._getDefaultState();\n }\n\n pageChanged(currentPage: number): void {\n this.currentPage = currentPage;\n this.table.setCurrentPage(this.currentPage);\n }\n\n itemsPerPageChanged(itemsPerPage: number): void {\n this.pageSize = itemsPerPage;\n this.table.setPageSize(this.pageSize, true);\n }\n\n /**\n * Simulating scroll position update. Once table is initialized app can set back preserved scrolling table\n * position so table can scroll it its original state.\n *\n * Note: Bellow scrollTopPosition property is set based on the scrolling position that was read from\n * this table example. Just some number to showcase this.\n */\n _getDefaultState(): TableState {\n return {\n columnKeys: [],\n sortBy: [],\n filterBy: [],\n groupBy: [],\n columns: [],\n searchInput: {\n category: null,\n text: ''\n },\n freezeToColumn: null,\n freezeToEndColumn: null,\n page: {\n pageSize: this.pageSize,\n currentPage: this.currentPage\n },\n scrollTopPosition: 0\n };\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n children?: ExampleItem[];\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [...ITEMS];\n totalItems = ITEMS.length;\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n this.totalItems = this.items.length;\n\n const currentPage = tableState?.page.currentPage || 1;\n const size = tableState?.page.pageSize || 50;\n const skip = (currentPage - 1) * size;\n\n const paginatedItems = this.items.slice(skip, size * currentPage);\n\n return of(paginatedItems).pipe(delay(1000));\n }\n}\n\n// Example items\nconst ITEMS: ExampleItem[] = new Array(5000).fill(null).map((_, index) => ({\n name: 'Laptops ' + index,\n price: {\n value: Math.floor(Math.random() * 1000),\n currency: 'USD'\n }\n}));\n", "html": "
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n


    \n \n \n \n\n \n\n \n\n \n\n \n \n
    \n" }, - { - "name": "platform-table-editable-rows-example", - "description": "Platform Table Editable Rows", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", - "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" - }, - { - "name": "platform-table-initial-loading-example", - "description": "Platform Table Initial Loading", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", - "html": "\n \n\n \n\n \n\n \n\n" - }, { "name": "platform-table-preserved-state-example", "description": "Platform Table Preserved State", @@ -71524,6 +71590,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule } from '@fundamental-ngx/platform/table';\nimport {\n ChildTableDataSource,\n CollectionNumberFilter,\n CollectionStringFilter,\n FdpTableDataSource,\n FilterType,\n FilterableColumnDataType,\n SortDirection,\n TableChildrenDataProvider,\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableRow,\n TableState,\n TableVirtualScrollDirective,\n TreeTableItem\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, of } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-doc-advanced-scrolling-example',\n templateUrl: './advanced-scrolling-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule\n ]\n})\nexport class AdvancedScrollingExampleComponent {\n source: TableDataSource;\n childSource: ChildTableDataSource;\n readonly filterTypeEnum = FilterType;\n readonly dataTypeEnum = FilterableColumnDataType;\n readonly selectOptions = ['Laptops 1 (Level 1)', 'Laptops 12 (Level 1)'];\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n this.childSource = new ChildTableDataSource(new ChildTableProviderExample());\n }\n}\n\nexport interface ExampleItem extends TreeTableItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n hasChildren: boolean;\n children?: FdpTableDataSource;\n}\n\nclass ChildTableProviderExample extends TableChildrenDataProvider {\n items: Map, ExampleItem[]> = new Map();\n totalItems = 200;\n startIndex = 0;\n allItemsMap = new Map, ExampleItem[]>();\n\n rowChildrenCount(row: TableRow): Observable {\n return of(this.totalItems);\n }\n\n /**\n * Unlike default dataSource, childDataSource accepts array of table rows as a second argument.\n * This is done to load child rows in bulk for the cases when multiple rows being expanded at the same time.\n * @param tableState\n * @param tableRows\n */\n fetch(\n tableState?: TableState,\n tableRows?: TableRow[]\n ): Observable, ExampleItem[]>> {\n const itemsMap = new Map, ExampleItem[]>();\n\n /** Logic of retrieving the child rows for a particular row in tableRows array. */\n tableRows?.forEach((row) => {\n let allItems = this.allItemsMap.get(row);\n const currentPage = tableState?.page.currentPage;\n if (!allItems) {\n allItems = generateItems(this.totalItems, row.level + 1);\n this.allItemsMap.set(row, allItems);\n }\n\n // apply searching\n if (tableState?.searchInput) {\n allItems = this.search(allItems, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n allItems = this.sort(allItems, tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n allItems = this.filter(allItems, tableState);\n }\n\n // Apply paging\n if (currentPage && tableState?.page) {\n const startIndex = (currentPage - 1) * tableState.page.pageSize;\n allItems = allItems.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n itemsMap.set(row, allItems);\n });\n\n return of(itemsMap).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort(items: ExampleItem[], { sortBy }: TableState): ExampleItem[] {\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 5000;\n startIndex = 0;\n allItems: ExampleItem[];\n\n constructor(public level = 0) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.allItems = this.allItems || generateItems(this.totalItems, this.level);\n this.items = [...this.allItems];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(this.items, tableState);\n }\n\n // Apply paging\n if (tableState?.page?.currentPage) {\n const startIndex = (tableState.page.currentPage - 1) * tableState.page.pageSize;\n this.items = this.items.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n return of(this.items).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\nfunction generateItems(size = 5000, level = 0, startIndex = 0): ExampleItem[] {\n return new Array(size).fill(null).map(() => ({\n name: `Laptops ${startIndex++} (Level ${level + 1})`,\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true,\n hasChildren: level < 2 ? true : false\n }));\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => (a ? a[b] : null), object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n", "html": "\n \n\n \n \n\n \n\n \n \n\n \n \n\n\n\n\n" }, + { + "name": "platform-table-initial-loading-example", + "description": "Platform Table Initial Loading", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", + "html": "\n \n\n \n\n \n\n \n\n" + }, + { + "name": "platform-table-editable-rows-example", + "description": "Platform Table Editable Rows", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", + "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" + }, { "name": "table-custom-pagination-example", "description": "Table Custom Pagination", @@ -71536,18 +71614,6 @@ "typescript": "import { ChangeDetectionStrategy, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { PlatformTableModule, TableComponent } from '@fundamental-ngx/platform/table';\nimport {\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableState,\n TableVirtualScrollDirective\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, delay, of } from 'rxjs';\n\n@Component({\n selector: 'fdp-table-custom-pagination-outer-scroll-example',\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule,\n PaginationModule\n ],\n templateUrl: './table-custom-pagination-outer-scroll-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class TableCustomPaginationOuterScrollExampleComponent implements OnInit {\n @ViewChild(TableComponent)\n table: TableComponent;\n\n source: TableDataSource;\n state: TableState;\n currentPage = 1;\n pageSize = 50;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n\n ngOnInit(): void {\n this.state = this._getDefaultState();\n }\n\n pageChanged(currentPage: number): void {\n this.currentPage = currentPage;\n this.table.setCurrentPage(this.currentPage);\n }\n\n itemsPerPageChanged(itemsPerPage: number): void {\n this.pageSize = itemsPerPage;\n this.table.setPageSize(this.pageSize, true);\n }\n\n /**\n * Simulating scroll position update. Once table is initialized app can set back preserved scrolling table\n * position so table can scroll it its original state.\n *\n * Note: Bellow scrollTopPosition property is set based on the scrolling position that was read from\n * this table example. Just some number to showcase this.\n */\n _getDefaultState(): TableState {\n return {\n columnKeys: [],\n sortBy: [],\n filterBy: [],\n groupBy: [],\n columns: [],\n searchInput: {\n category: null,\n text: ''\n },\n freezeToColumn: null,\n freezeToEndColumn: null,\n page: {\n pageSize: this.pageSize,\n currentPage: this.currentPage\n },\n scrollTopPosition: 0\n };\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n children?: ExampleItem[];\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [...ITEMS];\n totalItems = ITEMS.length;\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n this.totalItems = this.items.length;\n\n const currentPage = tableState?.page.currentPage || 1;\n const size = tableState?.page.pageSize || 50;\n const skip = (currentPage - 1) * size;\n\n const paginatedItems = this.items.slice(skip, size * currentPage);\n\n return of(paginatedItems).pipe(delay(1000));\n }\n}\n\n// Example items\nconst ITEMS: ExampleItem[] = new Array(5000).fill(null).map((_, index) => ({\n name: 'Laptops ' + index,\n price: {\n value: Math.floor(Math.random() * 1000),\n currency: 'USD'\n }\n}));\n", "html": "
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n


    \n \n \n \n\n \n\n \n\n \n\n \n \n
    \n" }, - { - "name": "platform-table-editable-rows-example", - "description": "Platform Table Editable Rows", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", - "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" - }, - { - "name": "platform-table-initial-loading-example", - "description": "Platform Table Initial Loading", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", - "html": "\n \n\n \n\n \n\n \n\n" - }, { "name": "platform-table-preserved-state-example", "description": "Platform Table Preserved State", @@ -71799,6 +71865,18 @@ "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule } from '@fundamental-ngx/platform/table';\nimport {\n ChildTableDataSource,\n CollectionNumberFilter,\n CollectionStringFilter,\n FdpTableDataSource,\n FilterType,\n FilterableColumnDataType,\n SortDirection,\n TableChildrenDataProvider,\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableRow,\n TableState,\n TableVirtualScrollDirective,\n TreeTableItem\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, of } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\n@Component({\n selector: 'fdp-doc-advanced-scrolling-example',\n templateUrl: './advanced-scrolling-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule\n ]\n})\nexport class AdvancedScrollingExampleComponent {\n source: TableDataSource;\n childSource: ChildTableDataSource;\n readonly filterTypeEnum = FilterType;\n readonly dataTypeEnum = FilterableColumnDataType;\n readonly selectOptions = ['Laptops 1 (Level 1)', 'Laptops 12 (Level 1)'];\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n this.childSource = new ChildTableDataSource(new ChildTableProviderExample());\n }\n}\n\nexport interface ExampleItem extends TreeTableItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n hasChildren: boolean;\n children?: FdpTableDataSource;\n}\n\nclass ChildTableProviderExample extends TableChildrenDataProvider {\n items: Map, ExampleItem[]> = new Map();\n totalItems = 200;\n startIndex = 0;\n allItemsMap = new Map, ExampleItem[]>();\n\n rowChildrenCount(row: TableRow): Observable {\n return of(this.totalItems);\n }\n\n /**\n * Unlike default dataSource, childDataSource accepts array of table rows as a second argument.\n * This is done to load child rows in bulk for the cases when multiple rows being expanded at the same time.\n * @param tableState\n * @param tableRows\n */\n fetch(\n tableState?: TableState,\n tableRows?: TableRow[]\n ): Observable, ExampleItem[]>> {\n const itemsMap = new Map, ExampleItem[]>();\n\n /** Logic of retrieving the child rows for a particular row in tableRows array. */\n tableRows?.forEach((row) => {\n let allItems = this.allItemsMap.get(row);\n const currentPage = tableState?.page.currentPage;\n if (!allItems) {\n allItems = generateItems(this.totalItems, row.level + 1);\n this.allItemsMap.set(row, allItems);\n }\n\n // apply searching\n if (tableState?.searchInput) {\n allItems = this.search(allItems, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n allItems = this.sort(allItems, tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n allItems = this.filter(allItems, tableState);\n }\n\n // Apply paging\n if (currentPage && tableState?.page) {\n const startIndex = (currentPage - 1) * tableState.page.pageSize;\n allItems = allItems.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n itemsMap.set(row, allItems);\n });\n\n return of(itemsMap).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort(items: ExampleItem[], { sortBy }: TableState): ExampleItem[] {\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 5000;\n startIndex = 0;\n allItems: ExampleItem[];\n\n constructor(public level = 0) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.allItems = this.allItems || generateItems(this.totalItems, this.level);\n this.items = [...this.allItems];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(this.items, tableState);\n }\n\n // Apply paging\n if (tableState?.page?.currentPage) {\n const startIndex = (tableState.page.currentPage - 1) * tableState.page.pageSize;\n this.items = this.items.slice(startIndex, startIndex + tableState.page.pageSize);\n }\n\n return of(this.items).pipe(delay(1000));\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private filter(items: ExampleItem[], { filterBy }: TableState): ExampleItem[] {\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n case 'status':\n case 'statusColor':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return filterByNumber(item, rule as CollectionNumberFilter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n}\n\nfunction generateItems(size = 5000, level = 0, startIndex = 0): ExampleItem[] {\n return new Array(size).fill(null).map(() => ({\n name: `Laptops ${startIndex++} (Level ${level + 1})`,\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true,\n hasChildren: level < 2 ? true : false\n }));\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => (a ? a[b] : null), object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n", "html": "\n \n\n \n \n\n \n\n \n \n\n \n \n\n\n\n\n" }, + { + "name": "platform-table-initial-loading-example", + "description": "Platform Table Initial Loading", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", + "html": "\n \n\n \n\n \n\n \n\n" + }, + { + "name": "platform-table-editable-rows-example", + "description": "Platform Table Editable Rows", + "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", + "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" + }, { "name": "table-custom-pagination-example", "description": "Table Custom Pagination", @@ -71811,18 +71889,6 @@ "typescript": "import { ChangeDetectionStrategy, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FdDate, FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PaginationModule } from '@fundamental-ngx/core/pagination';\nimport { PlatformTableModule, TableComponent } from '@fundamental-ngx/platform/table';\nimport {\n TableDataProvider,\n TableDataSource,\n TableDataSourceDirective,\n TableDraggableDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective,\n TableState,\n TableVirtualScrollDirective\n} from '@fundamental-ngx/platform/table-helpers';\nimport { Observable, delay, of } from 'rxjs';\n\n@Component({\n selector: 'fdp-table-custom-pagination-outer-scroll-example',\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n TableDraggableDirective,\n TableVirtualScrollDirective,\n FdDatetimeModule,\n PaginationModule\n ],\n templateUrl: './table-custom-pagination-outer-scroll-example.component.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class TableCustomPaginationOuterScrollExampleComponent implements OnInit {\n @ViewChild(TableComponent)\n table: TableComponent;\n\n source: TableDataSource;\n state: TableState;\n currentPage = 1;\n pageSize = 50;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n\n ngOnInit(): void {\n this.state = this._getDefaultState();\n }\n\n pageChanged(currentPage: number): void {\n this.currentPage = currentPage;\n this.table.setCurrentPage(this.currentPage);\n }\n\n itemsPerPageChanged(itemsPerPage: number): void {\n this.pageSize = itemsPerPage;\n this.table.setPageSize(this.pageSize, true);\n }\n\n /**\n * Simulating scroll position update. Once table is initialized app can set back preserved scrolling table\n * position so table can scroll it its original state.\n *\n * Note: Bellow scrollTopPosition property is set based on the scrolling position that was read from\n * this table example. Just some number to showcase this.\n */\n _getDefaultState(): TableState {\n return {\n columnKeys: [],\n sortBy: [],\n filterBy: [],\n groupBy: [],\n columns: [],\n searchInput: {\n category: null,\n text: ''\n },\n freezeToColumn: null,\n freezeToEndColumn: null,\n page: {\n pageSize: this.pageSize,\n currentPage: this.currentPage\n },\n scrollTopPosition: 0\n };\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description?: string;\n price?: {\n value: number;\n currency: string;\n };\n status?: string;\n statusColor?: string;\n date?: FdDate;\n verified?: boolean;\n children?: ExampleItem[];\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [...ITEMS];\n totalItems = ITEMS.length;\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n this.totalItems = this.items.length;\n\n const currentPage = tableState?.page.currentPage || 1;\n const size = tableState?.page.pageSize || 50;\n const skip = (currentPage - 1) * size;\n\n const paginatedItems = this.items.slice(skip, size * currentPage);\n\n return of(paginatedItems).pipe(delay(1000));\n }\n}\n\n// Example items\nconst ITEMS: ExampleItem[] = new Array(5000).fill(null).map((_, index) => ({\n name: 'Laptops ' + index,\n price: {\n value: Math.floor(Math.random() * 1000),\n currency: 'USD'\n }\n}));\n", "html": "
    \n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab ducimus ratione, mollitia, possimus alias aperiam eaque,\n harum unde necessitatibus explicabo esse culpa accusantium blanditiis autem repellat maiores ipsum magni maxime.\n


    \n \n \n \n\n \n\n \n\n \n\n \n \n
    \n" }, - { - "name": "platform-table-editable-rows-example", - "description": "Platform Table Editable Rows", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\nimport { FormsModule } from '@angular/forms';\nimport { DatetimeAdapter, FdDate, FdDatetimeModule, provideDateTimeFormats } from '@fundamental-ngx/core/datetime';\nimport { SelectModule } from '@fundamental-ngx/core/select';\nimport { PlatformInputModule } from '@fundamental-ngx/platform/form';\nimport {\n CollectionBooleanFilter,\n CollectionDateFilter,\n CollectionFilter,\n CollectionNumberFilter,\n CollectionSelectFilter,\n CollectionSort,\n CollectionStringFilter,\n FilterableColumnDataType,\n PlatformTableModule,\n SaveRowsEvent,\n SortDirection,\n TableDataProvider,\n TableDataSource,\n TableState\n} from '@fundamental-ngx/platform/table';\nimport {\n FdpCellDef,\n FdpEditableCellDef,\n FdpEditableCellFormDirective,\n FdpTableCell,\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-editable-rows-example',\n templateUrl: './platform-table-editable-rows-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [provideDateTimeFormats()],\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdpEditableCellDef,\n FdpTableCell,\n FormsModule,\n FdpEditableCellFormDirective,\n PlatformInputModule,\n SelectModule,\n FdpCellDef,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableEditableRowsExampleComponent {\n readonly dataTypeEnum = FilterableColumnDataType;\n source: TableDataSource;\n loading = false;\n\n initialSort: CollectionSort[] = [\n {\n field: 'price.value',\n direction: SortDirection.ASC\n }\n ];\n\n editableRowSkeleton: Record = {\n name: null,\n description: null,\n price: {\n value: null,\n currency: null\n },\n status: null,\n statusColor: null,\n date: null,\n verified: false\n };\n\n statusOptions = ['No info', 'Out of stock', 'Stocked on demand', 'Available'];\n\n constructor(datetimeAdapter: DatetimeAdapter) {\n this.source = new TableDataSource(new TableDataProviderExample(datetimeAdapter));\n }\n\n addRows(event: SaveRowsEvent): void {\n // Simulate backend request\n this.loading = true;\n setTimeout(() => {\n ITEMS = [...ITEMS, ...event.items];\n this.source.dataProvider.items = ITEMS;\n event.done();\n this.loading = false;\n }, 2000);\n }\n}\n\nexport interface ExampleItem {\n name: string;\n description: string;\n price: {\n value: number;\n currency: string;\n };\n status: string;\n statusColor?: string;\n date: FdDate;\n verified: boolean;\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n items: ExampleItem[] = [];\n totalItems = 0;\n\n constructor(public dateTimeAdapter: DatetimeAdapter) {\n super();\n }\n\n fetch(tableState?: TableState): Observable {\n this.items = [...ITEMS];\n\n // apply searching\n if (tableState?.searchInput) {\n this.items = this.search(this.items, tableState);\n }\n // apply filtering\n if (tableState?.filterBy) {\n this.items = this.filter(tableState);\n }\n // apply sorting\n if (tableState?.sortBy) {\n this.items = this.sort(tableState);\n }\n\n this.totalItems = this.items.length;\n\n return of(this.items);\n }\n\n search(items: ExampleItem[], { searchInput, columnKeys }: TableState): ExampleItem[] {\n const searchText = searchInput?.text || '';\n const keysToSearchBy = columnKeys;\n\n if (searchText.trim() === '' || keysToSearchBy.length === 0) {\n return items;\n }\n\n return items.filter((item) => {\n const valuesForSearch = keysToSearchBy.map((key) => getNestedValue(key, item));\n return valuesForSearch\n .filter((value) => !!value)\n .map((value): string => value.toString())\n .some((value) => value.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()));\n });\n }\n\n private sort({ sortBy }: TableState): ExampleItem[] {\n const items = this.items.slice();\n\n sortBy = sortBy.filter(({ field }) => !!field);\n\n if (sortBy.length === 0) {\n return items;\n }\n\n return items.sort(\n (a, b) =>\n sortBy\n .map(({ field, direction }) => {\n const ascModifier = direction === SortDirection.ASC ? 1 : -1;\n return sort(a, b, field as string) * ascModifier;\n })\n .find((result, index, list) => result !== 0 || index === list.length - 1) ?? 0\n );\n }\n\n private filter({ filterBy }: TableState): ExampleItem[] {\n let items = this.items;\n\n filterBy\n .filter(({ field }) => !!field)\n .forEach((rule) => {\n items = items.filter((item) => {\n switch (rule.field) {\n case 'name':\n case 'description':\n return filterByString(item, rule as CollectionStringFilter);\n case 'price.value':\n return this.filterByPrice(item, rule);\n case 'status':\n return this.filterByStatus(item, rule);\n case 'statusColor':\n return this.filterByStatusColor(item, rule);\n case 'verified':\n return filterByBoolean(item, rule as CollectionBooleanFilter);\n case 'date':\n return filterByDate(item, rule as CollectionBooleanFilter, this.dateTimeAdapter);\n default:\n return false;\n }\n });\n });\n\n return items;\n }\n\n private filterByPrice(item: ExampleItem, rule: CollectionFilter): boolean {\n const filterValue = rule.value;\n if (filterValue && typeof filterValue === 'object' && ('min' in filterValue || 'max' in filterValue)) {\n const filterModel: { min: number; max: number } = rule.value;\n const price = item.price.value;\n const min = Number.parseFloat(filterModel?.min as any);\n const max = Number.parseFloat(filterModel?.max as any);\n return (Number.isNaN(min) || price >= min) && (Number.isNaN(max) || price <= max);\n }\n return filterByNumber(item, rule as CollectionNumberFilter);\n }\n\n private filterByStatus(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n\n private filterByStatusColor(item: ExampleItem, rule: CollectionFilter): boolean {\n if (Array.isArray(rule.value)) {\n return filterBySelect(item, rule as CollectionSelectFilter);\n }\n return filterByString(item, rule as CollectionStringFilter);\n }\n}\n\n/* UTILS */\n\nconst sort = >(a: T, b: T, key?: string): number => {\n if (key) {\n a = getNestedValue(key, a);\n b = getNestedValue(key, b);\n }\n return a > b ? 1 : a === b ? 0 : -1;\n};\n\nfunction getNestedValue>(key: string, object: T): any {\n return key.split('.').reduce((a, b) => a[b], object);\n}\n\nconst filterByString = (item: ExampleItem, filter: CollectionStringFilter): boolean => {\n const filterValue = filter.value && filter.value.toLocaleLowerCase();\n const filterValue2 = (filter.value2 && filter.value2.toLocaleLowerCase()) || '';\n const itemValue = getNestedValue(filter.field, item).toLocaleLowerCase();\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n result = itemValue === filterValue;\n break;\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'beginsWith':\n result = itemValue.startsWith(filterValue);\n break;\n case 'endsWith':\n result = itemValue.endsWith(filterValue);\n break;\n case 'contains':\n default:\n result = itemValue.includes(filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByNumber = (item: ExampleItem, filter: CollectionNumberFilter): boolean => {\n const filterValue = Number.parseFloat(filter.value as unknown as string);\n const filterValue2 = Number.parseFloat(filter.value2 as unknown as string) || 0;\n const itemValue = Number.parseFloat(getNestedValue(filter.field, item));\n let result = false;\n\n switch (filter.strategy) {\n case 'greaterThan':\n result = itemValue > filterValue;\n break;\n case 'greaterThanOrEqualTo':\n result = itemValue >= filterValue;\n break;\n case 'lessThan':\n result = itemValue < filterValue;\n break;\n case 'lessThanOrEqualTo':\n result = itemValue <= filterValue;\n break;\n case 'between':\n result = itemValue >= filterValue && itemValue <= filterValue2;\n break;\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByDate = (\n item: ExampleItem,\n filter: CollectionDateFilter,\n adapter: DatetimeAdapter\n): boolean => {\n const filterValue = filter.value;\n const filterValue2 = filter.value2;\n const itemValue = getNestedValue(filter.field, item);\n const diff = adapter.compareDate(itemValue, filterValue);\n let result = false;\n\n switch (filter.strategy) {\n case 'after':\n result = diff > 0;\n break;\n case 'onOrAfter':\n result = diff >= 0;\n break;\n case 'before':\n result = diff < 0;\n break;\n case 'beforeOrOn':\n result = diff <= 0;\n break;\n case 'between':\n result = adapter.isBetween(itemValue, filterValue, filterValue2);\n break;\n\n case 'equalTo':\n default:\n result = adapter.dateTimesEqual(itemValue, filterValue);\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterByBoolean = (item: ExampleItem, filter: CollectionBooleanFilter): boolean => {\n const filterValue = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = itemValue === filterValue;\n }\n\n return filter.exclude ? !result : result;\n};\n\nconst filterBySelect = (item: ExampleItem, filter: CollectionSelectFilter): boolean => {\n const filterValues = filter.value;\n const itemValue = getNestedValue(filter.field, item);\n let result = false;\n\n switch (filter.strategy) {\n case 'equalTo':\n default:\n result = filterValues.includes(itemValue);\n }\n\n return !filterValues.length || filter.exclude ? !result : result;\n};\n\n// Example items\nlet ITEMS: ExampleItem[] = [\n {\n name: '10 Portable DVD player',\n description: 'diam neque vestibulum eget vulputate',\n price: {\n value: 66.04,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 7),\n verified: true\n },\n {\n name: 'Astro Laptop 1516',\n description: 'pede malesuada',\n price: {\n value: 489.01,\n currency: 'EUR'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 2, 5),\n verified: true\n },\n {\n name: 'Astro Phone 6',\n description: 'penatibus et magnis',\n price: {\n value: 154.1,\n currency: 'IDR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 1, 12),\n verified: true\n },\n {\n name: 'Beam Breaker B-1',\n description: 'fermentum donec ut',\n price: {\n value: 36.56,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 11, 24),\n verified: false\n },\n {\n name: 'Beam Breaker B-2',\n description: 'sapien in sapien iaculis congue',\n price: {\n value: 332.57,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 10, 23),\n verified: true\n },\n {\n name: 'Benda Laptop 1408',\n description: 'suspendisse potenti cras in',\n price: {\n value: 243.49,\n currency: 'CNY'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 9, 22),\n verified: true\n },\n {\n name: 'Bending Screen 21HD',\n description: 'nunc nisl duis bibendum',\n price: {\n value: 66.46,\n currency: 'EUR'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 14),\n verified: false\n },\n {\n name: 'Blaster Extreme',\n description: 'quisque ut',\n price: {\n value: 436.88,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 8, 15),\n verified: true\n },\n {\n name: 'Broad Screen 22HD',\n description: 'ultrices posuere',\n price: {\n value: 458.18,\n currency: 'CNY'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 4),\n verified: true\n },\n {\n name: 'Camcorder View',\n description: 'integer ac leo pellentesque',\n price: {\n value: 300.52,\n currency: 'USD'\n },\n status: 'Available',\n statusColor: 'positive',\n date: new FdDate(2020, 5, 5),\n verified: true\n },\n {\n name: 'Cepat Tablet 10.5',\n description: 'rutrum rutrum neque aenean auctor',\n price: {\n value: 365.12,\n currency: 'NZD'\n },\n status: 'No info',\n date: new FdDate(2020, 5, 6),\n verified: true\n },\n {\n name: 'Ergo Mousepad',\n description: 'tortor duis mattis egestas',\n price: {\n value: 354.46,\n currency: 'EUR'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 5, 7),\n verified: true\n },\n {\n name: 'Ergo Screen E-I',\n description: 'massa quis augue luctus tincidunt',\n price: {\n value: 387.23,\n currency: 'NZD'\n },\n status: 'Stocked on demand',\n statusColor: 'informative',\n date: new FdDate(2020, 3, 23),\n verified: true\n },\n {\n name: 'Ergo Screen E-II',\n description: 'orci eget',\n price: {\n value: 75.86,\n currency: 'EUR'\n },\n status: 'No info',\n date: new FdDate(2020, 3, 20),\n verified: false\n },\n {\n name: 'Gaming Monster',\n description: 'cubilia curae',\n price: {\n value: 152.95,\n currency: 'EGP'\n },\n status: 'No info',\n date: new FdDate(2020, 9, 20),\n verified: false\n },\n {\n name: 'Gaming Monster Pro',\n description: 'pharetra magna vestibulum aliquet',\n price: {\n value: 213.47,\n currency: 'MZN'\n },\n status: 'Out of stock',\n statusColor: 'negative',\n date: new FdDate(2020, 4, 17),\n verified: false\n }\n];\n", - "html": "\n \n \n \n
    \n \n \n
    \n
    \n \n \n \n \n \n \n \n
    \n \n @for (option of statusOptions; track option) {\n
  • {{ option }}
  • \n }\n
    \n
    \n
    \n
    \n \n \n {{ item.date?.toDateString() }}\n \n \n\n" - }, - { - "name": "platform-table-initial-loading-example", - "description": "Platform Table Initial Loading", - "typescript": "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { FdDatetimeModule } from '@fundamental-ngx/core/datetime';\nimport { PlatformTableModule, TableDataProvider, TableDataSource, TableState } from '@fundamental-ngx/platform/table';\nimport {\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n TableInitialStateDirective\n} from '@fundamental-ngx/platform/table-helpers';\n\n@Component({\n selector: 'fdp-platform-table-initial-loading-example',\n templateUrl: './platform-table-initial-loading-example.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n TableDataSourceDirective,\n TableHeaderResizerDirective,\n PlatformTableModule,\n TableInitialStateDirective,\n FdDatetimeModule\n ]\n})\nexport class PlatformTableInitialLoadingExampleComponent {\n source: TableDataSource;\n\n constructor() {\n this.source = new TableDataSource(new TableDataProviderExample());\n }\n}\n\n/**\n * Table Data Provider Example\n *\n */\nexport class TableDataProviderExample extends TableDataProvider {\n fetch(tableState?: TableState): Observable {\n return new Observable();\n }\n}\n", - "html": "\n \n\n \n\n \n\n \n\n" - }, { "name": "platform-table-preserved-state-example", "description": "Platform Table Preserved State", @@ -74609,17 +74675,17 @@ "typescript": "import { UpperCasePipe } from '@angular/common';\nimport { Component, ViewChild } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { ButtonComponent } from '@fundamental-ngx/core/button';\nimport { DialogRef, DialogService } from '@fundamental-ngx/core/dialog';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { TableComponent, TableModule } from '@fundamental-ngx/core/table';\nimport { TableCustomDialogComponent } from './table-custom-dialog.component';\n\nexport interface DisplayedColumn {\n key: string;\n checked: boolean;\n}\n\nexport interface CellData {\n column1: string;\n column2: string;\n column3: string;\n date: string;\n type: string;\n}\n\nconst CELL_DATA: CellData[] = [\n { column1: 'Row 111', column2: 'Row 221', column3: 'Row 1', date: '09-07-18', type: 'search' },\n { column1: 'Row 112', column2: 'Row 222', column3: 'Row 2', date: '09-08-18', type: 'cart' },\n { column1: 'Row 113', column2: 'Row 223', column3: 'Row 3', date: '02-14-18', type: 'calendar' },\n { column1: 'Row 114', column2: 'Row 224', column3: 'Row 4', date: '12-30-17', type: 'search' },\n { column1: 'Row 115', column2: 'Row 225', column3: 'Row 5', date: '11-12-18', type: 'search' }\n];\n\n@Component({\n selector: 'fd-table-custom-columns-example',\n templateUrl: './table-custom-columns-example.component.html',\n imports: [FocusableGridDirective, TableModule, LinkComponent, IconComponent, ButtonComponent, UpperCasePipe]\n})\nexport class TableCustomColumnsExampleComponent {\n @ViewChild(TableComponent)\n tableComponent: TableComponent;\n\n displayedColumns: string[];\n originalDisplayedColumns: DisplayedColumn[];\n dataSource = CELL_DATA;\n dialogRef: DialogRef;\n\n constructor(private _dialogService: DialogService) {\n this.displayedColumns = Object.keys(this.dataSource[0]);\n this.originalDisplayedColumns = [];\n\n Object.keys(this.dataSource[0]).forEach((key) => {\n this.originalDisplayedColumns.push({ key, checked: true });\n });\n }\n\n openDialog(): void {\n const dialogRef = this._dialogService.open(TableCustomDialogComponent, {\n width: '350px',\n height: '370px',\n draggable: true,\n resizable: true,\n verticalPadding: false,\n data: {\n columns: this.originalDisplayedColumns\n }\n });\n\n dialogRef.afterClosed.subscribe(\n (columns) => {\n this.originalDisplayedColumns = [...columns];\n this._propagateChangeToDisplayedValue();\n },\n () => {\n console.log('closed without changes');\n }\n );\n }\n\n private _propagateChangeToDisplayedValue(): void {\n this.displayedColumns = [\n ...this.originalDisplayedColumns.filter((_col) => _col.checked).map((_col) => _col.key)\n ];\n this.tableComponent.reset(this.displayedColumns);\n }\n}\n", "html": "\n \n \n @for (column of displayedColumns; track column) {\n \n }\n \n \n \n @for (row of dataSource; track row) {\n \n \n \n \n \n \n \n }\n \n
    {{ column | uppercase }}
    \n {{ row.column1 }}\n {{ row.column2 }}{{ row.column3 }}{{ row.date }}
    \n
    \n
    \nChosen Columns: {{ displayedColumns }}\n
    \n
    \n\n" }, - { - "name": "table-focusable-example", - "description": "Table Focusable", - "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", - "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" - }, { "name": "table-popin-example", "description": "Table Popin", "typescript": "import { Component } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { CheckboxComponent } from '@fundamental-ngx/core/checkbox';\nimport { FormLabelComponent } from '@fundamental-ngx/core/form';\nimport { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-popin-example',\n templateUrl: './table-popin-example.component.html',\n styles: [\n `\n .table-example-popin-title {\n margin: 0 0 10px 0;\n }\n `\n ],\n imports: [\n FocusableGridDirective,\n TableModule,\n FormLabelComponent,\n ObjectStatusComponent,\n CheckboxComponent,\n FormsModule\n ]\n})\nexport class TablePopinExampleComponent {\n masterCheckbox: boolean | null = false;\n\n fruits: any[] = [\n {\n name: 'Banana',\n status: 'positive',\n statusName: 'Available',\n dateOfExpire: '12.06.2020',\n price: '5 EUR',\n country: 'India',\n description: `A banana is an elongated, edible fruit – botanically a berry – produced by several kinds of large herbaceous\n flowering plants in the genus Musa.`,\n checked: false\n },\n {\n name: 'Apple',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '10.06.2020',\n price: '5,5 EUR',\n country: 'USA',\n description: `An apple is an edible fruit produced by an apple tree (Malus domestica).\n Apple trees are cultivated worldwide and are the most widely grown species in the genus Malus.`,\n checked: false\n },\n {\n name: 'Pineapple',\n status: 'negative',\n statusName: 'Out of stock',\n dateOfExpire: '08.06.2020',\n price: '6 EUR',\n country: 'Mexico',\n description: `The pineapple (Ananas comosus) is a tropical plant with an edible fruit and the most\n economically significant plant in the family Bromeliaceae.`,\n checked: false\n },\n {\n name: 'Orange',\n status: 'informative',\n statusName: 'Temporary unavailable',\n dateOfExpire: '18.06.2020',\n price: '10 EUR',\n country: 'Spain',\n description: `The orange is the fruit of various citrus species in the family Rutaceae\n (see list of plants known as orange); it primarily refers to Citrus × sinensis.`,\n checked: false\n }\n ];\n\n constructor() {}\n\n select(index: number, checked: boolean): void {\n this.fruits[index].checked = checked;\n\n this._handleMasterCheckboxState();\n }\n\n selectMaster(checked: boolean): void {\n checked ? this._selectAll() : this._deselectAll();\n\n this._handleMasterCheckboxState();\n }\n\n private _handleMasterCheckboxState(): void {\n this.masterCheckbox = this._allSelected() ? true : this._anySelected() ? null : false;\n }\n\n private _selectAll(): void {\n this.fruits.forEach((row) => (row.checked = true));\n }\n\n private _deselectAll(): void {\n this.fruits.forEach((row) => (row.checked = false));\n }\n\n private _anySelected(): boolean {\n return this.fruits.some((_row) => _row.checked);\n }\n\n private _allSelected(): boolean {\n return this.fruits.every((_row) => _row.checked);\n }\n}\n", "html": "
    \n

    Mobile Mode

    \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Tablet Mode

    \n \n \n \n Fruit Description\n Price\n Status\n Date Of Expire\n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n {{ fruit.dateOfExpire }}\n \n \n \n \n \n \n \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n
    \n

    Desktop Mode

    \n \n \n \n \n \n \n \n \n \n \n \n \n \n @for (fruit of fruits; track fruit) {\n \n \n \n \n \n \n \n \n \n }\n \n
    NamePriceCountryStatusDate Of ExpireDescription
    \n {{ fruit.name }}\n \n {{ fruit.country }}\n \n {{ fruit.price }}\n \n \n \n {{ fruit.dateOfExpire }}\n \n {{ fruit.description }}\n \n \n
    \n
    \n
    \n

    Popin Mobile Mode with Checkboxes

    \n \n \n \n \n \n \n Fruit Description\n Price\n \n \n \n \n @for (fruit of fruits; track fruit; let ind = $index) {\n \n \n \n \n \n

    {{ fruit.name }}

    \n

    {{ fruit.country }}

    \n \n \n {{ fruit.price }}\n \n \n \n \n \n \n \n \n

    \n \n \n

    \n

    \n \n {{ fruit.dateOfExpire }}\n

    \n

    \n \n {{ fruit.description }}\n

    \n \n \n }\n \n \n
    \n" + }, + { + "name": "table-focusable-example", + "description": "Table Focusable", + "typescript": "import { Component } from '@angular/core';\nimport { FocusableGridDirective } from '@fundamental-ngx/cdk/utils';\nimport { IconComponent } from '@fundamental-ngx/core/icon';\nimport { LinkComponent } from '@fundamental-ngx/core/link';\nimport { MenuModule } from '@fundamental-ngx/core/menu';\nimport { SplitButtonModule } from '@fundamental-ngx/core/split-button';\nimport { StepInputModule } from '@fundamental-ngx/core/step-input';\nimport { TableModule } from '@fundamental-ngx/core/table';\n\n@Component({\n selector: 'fd-table-focusable-example',\n templateUrl: './table-focusable-example.component.html',\n imports: [\n FocusableGridDirective,\n TableModule,\n LinkComponent,\n StepInputModule,\n IconComponent,\n SplitButtonModule,\n MenuModule\n ]\n})\nexport class TableFocusableExampleComponent {\n tableRows = [\n {\n column1: 'user.name@email.com',\n column2:\n 'LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText LongText',\n column3: 'Row 2',\n date: '09-07-18',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 2',\n column3:\n 'Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long Text Wrapped Long',\n date: '09-08-18',\n type: 'cart'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 3',\n column3: 'Row 3',\n date: '02-14-18',\n type: 'calendar'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 4',\n column3: 'Row 4',\n date: '12-30-17',\n type: 'search'\n },\n {\n column1: 'user.name@email.com',\n column2: 'Row 5',\n column3: 'Row 5',\n date: '11-12-18',\n type: 'search'\n }\n ];\n}\n", + "html": "\n \n \n \n \n \n \n \n \n \n \n @for (item of [0, 1, 2, 3, 4, 5]; track item) {\n \n \n \n \n \n \n \n }\n \n
    EverySingleCellCan beFocused
    WholeRowCan alsoBeFocused
    \n
    \nIt's also possible to set [allCellsFocusable]=\"true\" in order to not apply the input to each cell\n seperately\n\n\n \n \n \n \n \n \n \n \n \n \n \n @for (row of tableRows; track row) {\n \n \n \n \n \n \n \n \n }\n \n
    Column HeaderColumn HeaderColumn HeaderColumn HeaderColumn HeaderColumn Header
    \n {{ row.column1 }}\n \n

    \n \n

    \n
    \n

    \n {{ row.column3 }}\n

    \n
    {{ row.date }}\n \n \n
  • \n
    \n Option 1\n
    \n
  • \n
  • \n
    \n Option 2\n
    \n
  • \n
    \n
    \n
    \n" } ] }, @@ -74669,10 +74735,10 @@ "html": "\n \n\n \n\n \n\n" }, { - "name": "feed-input-grow-example", - "description": "Feed Input Grow", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { FeedInputModule } from '@fundamental-ngx/core/feed-input';\nimport { FormControlComponent } from '@fundamental-ngx/core/form';\n\n@Component({\n selector: 'fd-feed-input-grow-example',\n templateUrl: './feed-input-grow-example.component.html',\n imports: [FeedInputModule, AvatarComponent, FormControlComponent]\n})\nexport class FeedInputGrowExampleComponent {}\n", - "html": "\n \n\n \n\n \n\n" + "name": "feed-input-placeholder-example", + "description": "Feed Input Placeholder", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { FeedInputModule } from '@fundamental-ngx/core/feed-input';\nimport { FormControlComponent } from '@fundamental-ngx/core/form';\n\n@Component({\n selector: 'fd-feed-input-placeholder-example',\n templateUrl: './feed-input-placeholder-example.component.html',\n imports: [FeedInputModule, AvatarComponent, FormControlComponent]\n})\nexport class FeedInputPlaceholderExampleComponent {}\n", + "html": "\n \n\n \n\n \n\n" }, { "name": "feed-input-no-avatar-example", @@ -74681,10 +74747,10 @@ "html": "\n \n\n \n\n" }, { - "name": "feed-input-placeholder-example", - "description": "Feed Input Placeholder", - "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { FeedInputModule } from '@fundamental-ngx/core/feed-input';\nimport { FormControlComponent } from '@fundamental-ngx/core/form';\n\n@Component({\n selector: 'fd-feed-input-placeholder-example',\n templateUrl: './feed-input-placeholder-example.component.html',\n imports: [FeedInputModule, AvatarComponent, FormControlComponent]\n})\nexport class FeedInputPlaceholderExampleComponent {}\n", - "html": "\n \n\n \n\n \n\n" + "name": "feed-input-grow-example", + "description": "Feed Input Grow", + "typescript": "import { Component } from '@angular/core';\nimport { AvatarComponent } from '@fundamental-ngx/core/avatar';\nimport { FeedInputModule } from '@fundamental-ngx/core/feed-input';\nimport { FormControlComponent } from '@fundamental-ngx/core/form';\n\n@Component({\n selector: 'fd-feed-input-grow-example',\n templateUrl: './feed-input-grow-example.component.html',\n imports: [FeedInputModule, AvatarComponent, FormControlComponent]\n})\nexport class FeedInputGrowExampleComponent {}\n", + "html": "\n \n\n \n\n \n\n" } ] },