diff --git a/libs/core/src/lib/dynamic-page/directives/dynamic-page-header-subtitle.directive.ts b/libs/core/src/lib/dynamic-page/directives/dynamic-page-header-subtitle.directive.ts new file mode 100644 index 00000000000..24b88d137cc --- /dev/null +++ b/libs/core/src/lib/dynamic-page/directives/dynamic-page-header-subtitle.directive.ts @@ -0,0 +1,19 @@ +import { Directive, TemplateRef, inject } from '@angular/core'; +import { DynamicPageTitleDirectiveContext } from '../models/title-directive-context'; + +@Directive({ + selector: '[fdDynamicPageHeaderSubtitle]', + standalone: true +}) +export class DynamicPageHeaderSubtitleDirective { + /** Template reference. */ + templateRef = inject>(TemplateRef); + + /** @hidden */ + static ngTemplateContextGuard( + dir: DynamicPageHeaderSubtitleDirective, + ctx: DynamicPageTitleDirectiveContext + ): ctx is DynamicPageTitleDirectiveContext { + return true; + } +} diff --git a/libs/core/src/lib/dynamic-page/directives/dynamic-page-header-title.directive.ts b/libs/core/src/lib/dynamic-page/directives/dynamic-page-header-title.directive.ts new file mode 100644 index 00000000000..ef4e6e76944 --- /dev/null +++ b/libs/core/src/lib/dynamic-page/directives/dynamic-page-header-title.directive.ts @@ -0,0 +1,19 @@ +import { Directive, TemplateRef, inject } from '@angular/core'; +import { DynamicPageTitleDirectiveContext } from '../models/title-directive-context'; + +@Directive({ + selector: '[fdDynamicPageHeaderTitle]', + standalone: true +}) +export class DynamicPageHeaderTitleDirective { + /** Template reference. */ + templateRef = inject>(TemplateRef); + + /** @hidden */ + static ngTemplateContextGuard( + dir: DynamicPageHeaderTitleDirective, + ctx: DynamicPageTitleDirectiveContext + ): ctx is DynamicPageTitleDirectiveContext { + return true; + } +} diff --git a/libs/core/src/lib/dynamic-page/dynamic-page-header/header/dynamic-page-header.component.html b/libs/core/src/lib/dynamic-page/dynamic-page-header/header/dynamic-page-header.component.html index 3099bca38cf..564e95dd1d9 100644 --- a/libs/core/src/lib/dynamic-page/dynamic-page-header/header/dynamic-page-header.component.html +++ b/libs/core/src/lib/dynamic-page/dynamic-page-header/header/dynamic-page-header.component.html @@ -18,9 +18,9 @@ - {{ title }} +
@@ -31,24 +31,24 @@
- {{ subtitle }} +
- {{ subtitle }} +
@@ -57,3 +57,32 @@ + + + + + + + + + + + {{ subtitle }} + + + + + + + + {{ title }} + diff --git a/libs/core/src/lib/dynamic-page/dynamic-page-header/header/dynamic-page-header.component.spec.ts b/libs/core/src/lib/dynamic-page/dynamic-page-header/header/dynamic-page-header.component.spec.ts index 264499bc4ab..5625cadc95b 100644 --- a/libs/core/src/lib/dynamic-page/dynamic-page-header/header/dynamic-page-header.component.spec.ts +++ b/libs/core/src/lib/dynamic-page/dynamic-page-header/header/dynamic-page-header.component.spec.ts @@ -1,5 +1,5 @@ import { CommonModule } from '@angular/common'; -import { Component, ViewChild } from '@angular/core'; +import { ChangeDetectionStrategy, Component, ViewChild } from '@angular/core'; import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; import { BreadcrumbModule } from '@fundamental-ngx/core/breadcrumb'; @@ -35,6 +35,38 @@ class TestComponent { constructor(public dynamicPageService: DynamicPageService) {} } +@Component({ + template: ` + + + Title {{ collapsed ? 'collapsed' : 'expanded' }} + + + Subtitle {{ collapsed ? 'collapsed' : 'expanded' }} + + + + Men + + + Shoes + + + + + + + `, + changeDetection: ChangeDetectionStrategy.OnPush, + providers: [DynamicPageService] +}) +class TestWithSubtitleTemplateComponent { + @ViewChild(DynamicPageHeaderComponent) + header: DynamicPageHeaderComponent; + + constructor(public dynamicPageService: DynamicPageService) {} +} + describe('DynamicPageTitleComponent', () => { let fixture: ComponentFixture; let header: DynamicPageHeaderComponent; @@ -86,3 +118,63 @@ describe('DynamicPageTitleComponent', () => { expect((header)._actionsSquashed).toBe(false); }); }); + +describe('DynamicPageTitleComponent with custom subtitle', () => { + let fixture: ComponentFixture; + let header: DynamicPageHeaderComponent; + let component: TestWithSubtitleTemplateComponent; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [CommonModule, DynamicPageModule, BreadcrumbModule, ToolbarModule, ButtonModule], + declarations: [TestWithSubtitleTemplateComponent], + providers: [DynamicPageService] + }).compileComponents(); + }); + + beforeEach(async () => { + fixture = TestBed.createComponent(TestWithSubtitleTemplateComponent); + component = fixture.componentInstance; + await fixture.whenRenderingDone(); + fixture.detectChanges(); + header = component.header; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(fixture).toBeTruthy(); + }); + + it('should set title template correctly', fakeAsync(() => { + expect(header._titleTemplate).toBeDefined(); + expect(header.title).toBeUndefined(); + })); + + it('should set subtitle template correctly', fakeAsync(() => { + expect(header._subtitleTemplate).toBeDefined(); + expect(header.subtitle).toBeUndefined(); + })); + + it('should set subtitle template properties correctly', async () => { + fixture.componentInstance.dynamicPageService.collapsed.next(false); + fixture.detectChanges(); + await fixture.whenStable(); + + let subtitle = (header as any)._elementRef.nativeElement.querySelector('.my-custom-subtitle'); + let title = (header as any)._elementRef.nativeElement.querySelector('.my-custom-title'); + + expect(subtitle).toBeDefined(); + expect(subtitle.textContent).toEqual(`Subtitle expanded`); + expect(title.textContent).toEqual('Title expanded'); + + fixture.componentInstance.dynamicPageService.collapsed.next(true); + fixture.detectChanges(); + await fixture.whenStable(); + + subtitle = (header as any)._elementRef.nativeElement.querySelector('.my-custom-subtitle'); + title = (header as any)._elementRef.nativeElement.querySelector('.my-custom-title'); + + expect(subtitle.textContent).toEqual(`Subtitle collapsed`); + expect(title.textContent).toEqual('Title collapsed'); + }); +}); diff --git a/libs/core/src/lib/dynamic-page/dynamic-page-header/header/dynamic-page-header.component.ts b/libs/core/src/lib/dynamic-page/dynamic-page-header/header/dynamic-page-header.component.ts index f69c8530d59..ba191426969 100644 --- a/libs/core/src/lib/dynamic-page/dynamic-page-header/header/dynamic-page-header.component.ts +++ b/libs/core/src/lib/dynamic-page/dynamic-page-header/header/dynamic-page-header.component.ts @@ -6,7 +6,6 @@ import { ContentChild, ElementRef, Input, - NgZone, OnDestroy, OnInit, Renderer2, @@ -25,6 +24,9 @@ import { addClassNameToElement } from '../../utils'; import { DynamicPageLayoutActionsComponent } from '../actions/dynamic-page-layout-actions.component'; import { DynamicPageGlobalActionsComponent } from '../actions/dynamic-page-global-actions.component'; import { DynamicPageTitleContentComponent } from '../actions/dynamic-page-title-content.component'; +import { DynamicPageHeaderSubtitleDirective } from '../../directives/dynamic-page-header-subtitle.directive'; +import { Nullable } from '@fundamental-ngx/cdk/utils'; +import { DynamicPageHeaderTitleDirective } from '../../directives/dynamic-page-header-title.directive'; export const ActionSquashBreakpointPx = 1280; @@ -64,6 +66,20 @@ export class DynamicPageHeaderComponent implements OnInit, AfterViewInit, OnDest @Input() subtitleWrap = false; + /** + * @hidden + * Template used to provide a custom content for the subtitle page header area. + */ + @ContentChild(DynamicPageHeaderSubtitleDirective) + _subtitleTemplate: Nullable; + + /** + * @hidden + * Template used to provide a custom content for the title page header area. + */ + @ContentChild(DynamicPageHeaderTitleDirective) + _titleTemplate: Nullable; + /** @hidden */ @ContentChild(FD_BREADCRUMB_COMPONENT) _breadcrumbComponent: BreadcrumbComponent; @@ -94,7 +110,6 @@ export class DynamicPageHeaderComponent implements OnInit, AfterViewInit, OnDest private _elementRef: ElementRef, private _renderer: Renderer2, private _dynamicPageService: DynamicPageService, - private _ngZone: NgZone, private _changeDetRef: ChangeDetectorRef ) {} diff --git a/libs/core/src/lib/dynamic-page/dynamic-page.module.ts b/libs/core/src/lib/dynamic-page/dynamic-page.module.ts index 3ddf4302b2a..4c4324e805a 100644 --- a/libs/core/src/lib/dynamic-page/dynamic-page.module.ts +++ b/libs/core/src/lib/dynamic-page/dynamic-page.module.ts @@ -17,6 +17,8 @@ import { IgnoreClickOnSelectionModule } from '@fundamental-ngx/cdk/utils'; import { DeprecatedDynamicPageCompactDirective } from './deprecated-dynamic-page-compact.directive'; import { ContentDensityModule } from '@fundamental-ngx/core/content-density'; import { ScrollbarModule } from '@fundamental-ngx/core/scrollbar'; +import { DynamicPageHeaderSubtitleDirective } from './directives/dynamic-page-header-subtitle.directive'; +import { DynamicPageHeaderTitleDirective } from './directives/dynamic-page-header-title.directive'; @NgModule({ declarations: [ @@ -38,7 +40,9 @@ import { ScrollbarModule } from '@fundamental-ngx/core/scrollbar'; PopoverModule, IgnoreClickOnSelectionModule, ContentDensityModule, - ScrollbarModule + ScrollbarModule, + DynamicPageHeaderSubtitleDirective, + DynamicPageHeaderTitleDirective ], exports: [ DynamicPageComponent, @@ -50,7 +54,9 @@ import { ScrollbarModule } from '@fundamental-ngx/core/scrollbar'; DynamicPageFooterComponent, DynamicPageTitleContentComponent, DynamicPageWrapperDirective, - DeprecatedDynamicPageCompactDirective + DeprecatedDynamicPageCompactDirective, + DynamicPageHeaderSubtitleDirective, + DynamicPageHeaderTitleDirective ] }) export class DynamicPageModule {} diff --git a/libs/core/src/lib/dynamic-page/index.ts b/libs/core/src/lib/dynamic-page/index.ts index 57bd4f54864..374838daa8e 100644 --- a/libs/core/src/lib/dynamic-page/index.ts +++ b/libs/core/src/lib/dynamic-page/index.ts @@ -14,3 +14,6 @@ export * from './dynamic-page.module'; export * from './dynamic-page.service'; export * from './utils'; export * from './deprecated-dynamic-page-compact.directive'; +export * from './models/title-directive-context'; +export * from './directives/dynamic-page-header-subtitle.directive'; +export * from './directives/dynamic-page-header-title.directive'; diff --git a/libs/core/src/lib/dynamic-page/models/title-directive-context.ts b/libs/core/src/lib/dynamic-page/models/title-directive-context.ts new file mode 100644 index 00000000000..589a021c4c2 --- /dev/null +++ b/libs/core/src/lib/dynamic-page/models/title-directive-context.ts @@ -0,0 +1,4 @@ +export interface DynamicPageTitleDirectiveContext { + /** Whether the header is collapsed */ + $implicit: boolean; +} diff --git a/libs/docs/core/dynamic-page/dynamic-page-docs.component.html b/libs/docs/core/dynamic-page/dynamic-page-docs.component.html index b2597e4f4c6..78dbc2413b4 100644 --- a/libs/docs/core/dynamic-page/dynamic-page-docs.component.html +++ b/libs/docs/core/dynamic-page/dynamic-page-docs.component.html @@ -50,8 +50,9 @@ The Dynamic Page header can consist of various facet types, such as Form facet, Key-value facet, Image facet, and Rating Indicator facet. When an Image facet is used in the header content, collapsing the header will bring the - image facet next to the title. Expanding the header will place it back to its original place. + image facet next to the title. Expanding the header will place it back to its original place. This Dynamic Page + header also features custom subtitleTemplate for custom html content. + diff --git a/libs/docs/core/dynamic-page/examples/dynamic-page-facets-example/dynamic-page-facets-example.component.html b/libs/docs/core/dynamic-page/examples/dynamic-page-facets-example/dynamic-page-facets-example.component.html index aa2ccb68876..9664badd4d1 100644 --- a/libs/docs/core/dynamic-page/examples/dynamic-page-facets-example/dynamic-page-facets-example.component.html +++ b/libs/docs/core/dynamic-page/examples/dynamic-page-facets-example/dynamic-page-facets-example.component.html @@ -1,10 +1,17 @@
- + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit ({{ + collapsed ? 'collapsed' : 'not collapsed' + }}) + + + Different parts | of the | + subtitle | with + {{ collapsed ? 'collapsed' : 'not collapsed' }} header + Men diff --git a/libs/docs/core/dynamic-page/examples/dynamic-page-facets-example/dynamic-page-facets-example.component.ts b/libs/docs/core/dynamic-page/examples/dynamic-page-facets-example/dynamic-page-facets-example.component.ts index fa7c7883b70..7e95871c7e2 100644 --- a/libs/docs/core/dynamic-page/examples/dynamic-page-facets-example/dynamic-page-facets-example.component.ts +++ b/libs/docs/core/dynamic-page/examples/dynamic-page-facets-example/dynamic-page-facets-example.component.ts @@ -17,6 +17,15 @@ import { Component } from '@angular/core'; .fd-dynamic-page-section-example { min-height: 20vh; } + .red-subtitle { + color: red; + } + .blue-subtitle { + color: blue; + } + .green-subtitle { + color: green; + } ` ] }) diff --git a/libs/docs/platform/dynamic-page/examples/platform-dynamic-page-facets-example/platform-dynamic-page-facets-example.component.html b/libs/docs/platform/dynamic-page/examples/platform-dynamic-page-facets-example/platform-dynamic-page-facets-example.component.html index ca39462a4a5..248510758a9 100644 --- a/libs/docs/platform/dynamic-page/examples/platform-dynamic-page-facets-example/platform-dynamic-page-facets-example.component.html +++ b/libs/docs/platform/dynamic-page/examples/platform-dynamic-page-facets-example/platform-dynamic-page-facets-example.component.html @@ -2,7 +2,15 @@
- + + + {{ pageTitle }} ({{ collapsed ? 'collapsed' : 'not collapsed' }}) + + + Different platform parts | + of the | subtitle | with + {{ collapsed ? 'collapsed' : 'not collapsed' }} header + diff --git a/libs/docs/platform/dynamic-page/examples/platform-dynamic-page-facets-example/platform-dynamic-page-facets-example.component.scss b/libs/docs/platform/dynamic-page/examples/platform-dynamic-page-facets-example/platform-dynamic-page-facets-example.component.scss index 5fb70d9a0b5..d15ec5bfa7f 100644 --- a/libs/docs/platform/dynamic-page/examples/platform-dynamic-page-facets-example/platform-dynamic-page-facets-example.component.scss +++ b/libs/docs/platform/dynamic-page/examples/platform-dynamic-page-facets-example/platform-dynamic-page-facets-example.component.scss @@ -8,3 +8,13 @@ background-color: rgb(255, 255, 255); overflow-x: hidden; } + +.red-subtitle { + color: red; +} +.blue-subtitle { + color: blue; +} +.green-subtitle { + color: green; +} diff --git a/libs/platform/src/lib/dynamic-page/directives/dynamic-page-header-subtitle.directive.ts b/libs/platform/src/lib/dynamic-page/directives/dynamic-page-header-subtitle.directive.ts new file mode 100644 index 00000000000..ad8b2b2cb1c --- /dev/null +++ b/libs/platform/src/lib/dynamic-page/directives/dynamic-page-header-subtitle.directive.ts @@ -0,0 +1,19 @@ +import { Directive, TemplateRef, inject } from '@angular/core'; +import { DynamicPageTitleDirectiveContext } from '@fundamental-ngx/core/dynamic-page'; + +@Directive({ + selector: '[fdpDynamicPageHeaderSubtitle]', + standalone: true +}) +export class DynamicPageHeaderSubtitleDirective { + /** Template reference. */ + templateRef = inject>(TemplateRef); + + /** @hidden */ + static ngTemplateContextGuard( + dir: DynamicPageHeaderSubtitleDirective, + ctx: DynamicPageTitleDirectiveContext + ): ctx is DynamicPageTitleDirectiveContext { + return true; + } +} diff --git a/libs/platform/src/lib/dynamic-page/directives/dynamic-page-header-title.directive.ts b/libs/platform/src/lib/dynamic-page/directives/dynamic-page-header-title.directive.ts new file mode 100644 index 00000000000..f0664b44840 --- /dev/null +++ b/libs/platform/src/lib/dynamic-page/directives/dynamic-page-header-title.directive.ts @@ -0,0 +1,19 @@ +import { Directive, TemplateRef, inject } from '@angular/core'; +import { DynamicPageTitleDirectiveContext } from '@fundamental-ngx/core/dynamic-page'; + +@Directive({ + selector: '[fdpDynamicPageHeaderTitle]', + standalone: true +}) +export class DynamicPageHeaderTitleDirective { + /** Template reference. */ + templateRef = inject>(TemplateRef); + + /** @hidden */ + static ngTemplateContextGuard( + dir: DynamicPageHeaderTitleDirective, + ctx: DynamicPageTitleDirectiveContext + ): ctx is DynamicPageTitleDirectiveContext { + return true; + } +} diff --git a/libs/platform/src/lib/dynamic-page/dynamic-page-header/title/dynamic-page-title.component.ts b/libs/platform/src/lib/dynamic-page/dynamic-page-header/title/dynamic-page-title.component.ts index 2eb3a5eae70..494d5abbd18 100644 --- a/libs/platform/src/lib/dynamic-page/dynamic-page-header/title/dynamic-page-title.component.ts +++ b/libs/platform/src/lib/dynamic-page/dynamic-page-header/title/dynamic-page-title.component.ts @@ -14,6 +14,8 @@ import { DynamicPageGlobalActionsComponent } from '../actions/global-actions/dyn import { DynamicPageLayoutActionsComponent } from '../actions/layout-actions/dynamic-page-layout-actions.component'; import { DynamicPageKeyInfoComponent } from '../key-info/dynamic-page-key-info.component'; import { DynamicPageTitleImageComponent } from './dynamic-page-title-image.component'; +import { DynamicPageHeaderTitleDirective } from '../../directives/dynamic-page-header-title.directive'; +import { DynamicPageHeaderSubtitleDirective } from '../../directives/dynamic-page-header-subtitle.directive'; /** * Dynamic Page Title Component. @@ -86,6 +88,14 @@ export class DynamicPageTitleComponent implements DynamicPageHeader { @ContentChild(DynamicPageTitleImageComponent) imageComponent: DynamicPageTitleImageComponent; + /** @hidden */ + @ContentChild(DynamicPageHeaderTitleDirective) + _titleDirective: DynamicPageHeaderTitleDirective; + + /** @hidden */ + @ContentChild(DynamicPageHeaderSubtitleDirective) + _subtitleDirective: DynamicPageHeaderSubtitleDirective; + /** * @hidden * The component view is wrapped in ng-template so diff --git a/libs/platform/src/lib/dynamic-page/dynamic-page.component.html b/libs/platform/src/lib/dynamic-page/dynamic-page.component.html index df3ee68e85e..bedc1c36922 100644 --- a/libs/platform/src/lib/dynamic-page/dynamic-page.component.html +++ b/libs/platform/src/lib/dynamic-page/dynamic-page.component.html @@ -17,6 +17,24 @@ + + + + + + + + + + diff --git a/libs/platform/src/lib/dynamic-page/dynamic-page.module.ts b/libs/platform/src/lib/dynamic-page/dynamic-page.module.ts index 723102492e0..7da15371349 100644 --- a/libs/platform/src/lib/dynamic-page/dynamic-page.module.ts +++ b/libs/platform/src/lib/dynamic-page/dynamic-page.module.ts @@ -18,6 +18,8 @@ import { DynamicPageTitleImageComponent } from './dynamic-page-header/title/dyna import { DynamicPageComponent } from './dynamic-page.component'; import { ScrollingModule } from '@angular/cdk/scrolling'; import { FacetModule } from '@fundamental-ngx/core/facets'; +import { DynamicPageHeaderSubtitleDirective } from './directives/dynamic-page-header-subtitle.directive'; +import { DynamicPageHeaderTitleDirective } from './directives/dynamic-page-header-title.directive'; @NgModule({ declarations: [ @@ -39,7 +41,9 @@ import { FacetModule } from '@fundamental-ngx/core/facets'; PlatformButtonModule, BreadcrumbModule, ScrollingModule, - FacetModule + FacetModule, + DynamicPageHeaderSubtitleDirective, + DynamicPageHeaderTitleDirective ], exports: [ DynamicPageComponent, @@ -50,7 +54,9 @@ import { FacetModule } from '@fundamental-ngx/core/facets'; DynamicPageHeaderComponent, DynamicPageContentComponent, DynamicPageFooterComponent, - DynamicPageTitleImageComponent + DynamicPageTitleImageComponent, + DynamicPageHeaderSubtitleDirective, + DynamicPageHeaderTitleDirective ] }) export class PlatformDynamicPageModule {} diff --git a/libs/platform/src/lib/dynamic-page/index.ts b/libs/platform/src/lib/dynamic-page/index.ts index 726b445feb0..caa7bac03b9 100644 --- a/libs/platform/src/lib/dynamic-page/index.ts +++ b/libs/platform/src/lib/dynamic-page/index.ts @@ -16,3 +16,5 @@ export * from './dynamic-page-header/header/dynamic-page-header.component'; export * from './dynamic-page-header/key-info/dynamic-page-key-info.component'; export * from './dynamic-page-header/title/dynamic-page-title.component'; export * from './dynamic-page-header/title/dynamic-page-title-image.component'; +export * from './directives/dynamic-page-header-subtitle.directive'; +export * from './directives/dynamic-page-header-title.directive';