From a129f5ecd5891f33706f7b9bdd93c6236e13b881 Mon Sep 17 00:00:00 2001 From: N1XUS Date: Thu, 19 Oct 2023 18:16:47 +0300 Subject: [PATCH] fix(core): async scenario handler (#10761) --- .../src/lib/scroll-spy/scroll-spy.directive.ts | 11 ++++++----- libs/core/src/lib/tabs/tab-list.component.html | 1 + libs/core/src/lib/tabs/tab-list.component.ts | 18 ++++++++++++++---- .../tab-stacked-content-example.component.html | 2 +- .../tab-stacked-content-example.component.ts | 6 ++++++ 5 files changed, 28 insertions(+), 10 deletions(-) diff --git a/libs/core/src/lib/scroll-spy/scroll-spy.directive.ts b/libs/core/src/lib/scroll-spy/scroll-spy.directive.ts index d1dc799c80f..18330b4d9eb 100644 --- a/libs/core/src/lib/scroll-spy/scroll-spy.directive.ts +++ b/libs/core/src/lib/scroll-spy/scroll-spy.directive.ts @@ -18,7 +18,8 @@ import { debounceTime } from 'rxjs'; */ @Directive({ selector: '[fdScrollSpy]', - standalone: true + standalone: true, + exportAs: 'fdScrollSpy' }) export class ScrollSpyDirective implements OnInit { /** @@ -72,13 +73,13 @@ export class ScrollSpyDirective implements OnInit { /** @hidden */ @HostListener('scroll', ['$event']) - onScroll(event: Event): void { + onScroll(event?: Event, forced = false): void { if (this.scrollSpyDisabled) { return; } let spiedTag: HTMLElement | undefined; - const target = event.target as HTMLElement; + const target = (event?.target || this._elRef.nativeElement) as HTMLElement; const children: HTMLElement[] = this._elRef.nativeElement.children; const [firstChild] = children; const childrenLength = children.length; @@ -94,7 +95,7 @@ export class ScrollSpyDirective implements OnInit { } } - if ((spiedTag || this.fireEmpty) && spiedTag !== this._currentActive) { + if (forced || ((spiedTag || this.fireEmpty) && spiedTag !== this._currentActive)) { this._currentActive = spiedTag; this.spyChange.emit(this._currentActive); } @@ -106,7 +107,7 @@ export class ScrollSpyDirective implements OnInit { resizeObservable(this._elRef.nativeElement) .pipe(debounceTime(30), takeUntilDestroyed(this._destroyRef)) .subscribe(() => { - this.onScroll({ target: this._elRef.nativeElement } as Event); + this.onScroll(undefined, true); }); } } diff --git a/libs/core/src/lib/tabs/tab-list.component.html b/libs/core/src/lib/tabs/tab-list.component.html index e9613fb05ee..df1be8e0eec 100644 --- a/libs/core/src/lib/tabs/tab-list.component.html +++ b/libs/core/src/lib/tabs/tab-list.component.html @@ -103,6 +103,7 @@ class="fd-tabs__content" [style.max-height]="maxContentHeight" fdScrollSpy + #scrollSpy="fdScrollSpy" fd-scrollbar [overrideTabindex]="false" [trackedTags]="['fd-tab']" diff --git a/libs/core/src/lib/tabs/tab-list.component.ts b/libs/core/src/lib/tabs/tab-list.component.ts index fff7aba36a0..f0ebf181cf1 100644 --- a/libs/core/src/lib/tabs/tab-list.component.ts +++ b/libs/core/src/lib/tabs/tab-list.component.ts @@ -12,13 +12,15 @@ import { ElementRef, EventEmitter, Input, + NgZone, OnDestroy, Output, QueryList, ViewChild, ViewChildren, ViewEncapsulation, - forwardRef + forwardRef, + inject } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { KeyUtil, Nullable, scrollTop } from '@fundamental-ngx/cdk/utils'; @@ -40,7 +42,7 @@ import { import { ScrollSpyDirective } from '@fundamental-ngx/core/scroll-spy'; import { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar'; import { Observable, Subject, Subscription, fromEvent, merge } from 'rxjs'; -import { debounceTime, delay, filter, first, map, startWith, switchMap } from 'rxjs/operators'; +import { debounceTime, delay, filter, first, map, startWith, switchMap, tap } from 'rxjs/operators'; import { TabItemExpandComponent } from './tab-item-expand/tab-item-expand.component'; import { TabItemDirective } from './tab-item/tab-item.directive'; import { TabLinkDirective } from './tab-link/tab-link.directive'; @@ -211,6 +213,10 @@ export class TabListComponent implements TabListComponentInterface, AfterContent @ViewChild(OverflowLayoutComponent) private _overflowLayout: OverflowLayoutComponent; + /** @hidden */ + @ViewChild('scrollSpy', { read: ScrollSpyDirective }) + private readonly _scrollSpy: Nullable; + /** @hidden */ get contentContainer(): ElementRef { return this._scrollbar?.elementRef; @@ -234,10 +240,12 @@ export class TabListComponent implements TabListComponentInterface, AfterContent /** @hidden */ private _subscriptions = new Subscription(); + /** @hidden */ + private readonly _zone = inject(NgZone); + /** @hidden */ constructor( private readonly _changeDetectorRef: ChangeDetectorRef, - private _elRef: ElementRef, readonly _contentDensityObserver: ContentDensityObserver, private readonly _destroyRef: DestroyRef ) {} @@ -349,10 +357,12 @@ export class TabListComponent implements TabListComponentInterface, AfterContent map((tabPanels) => tabPanels.map((el) => this._tabArray?.find((tabInfo) => tabInfo.panel === el) || new TabInfo(el)) ), + tap((tabs) => (this._tabArray = tabs)), + switchMap(() => this._zone.onStable.pipe(startWith(this._zone.isStable))), takeUntilDestroyed(this._destroyRef) ) .subscribe((tabs) => { - this._tabArray = tabs; + this.stackContent && this._scrollSpy?.onScroll(undefined, true); }); } diff --git a/libs/docs/core/tabs/examples/tab-stacked-content-example/tab-stacked-content-example.component.html b/libs/docs/core/tabs/examples/tab-stacked-content-example/tab-stacked-content-example.component.html index d4d1af71f94..50e4ac7a073 100644 --- a/libs/docs/core/tabs/examples/tab-stacked-content-example/tab-stacked-content-example.component.html +++ b/libs/docs/core/tabs/examples/tab-stacked-content-example/tab-stacked-content-example.component.html @@ -1,4 +1,4 @@ - +

 

diff --git a/libs/docs/core/tabs/examples/tab-stacked-content-example/tab-stacked-content-example.component.ts b/libs/docs/core/tabs/examples/tab-stacked-content-example/tab-stacked-content-example.component.ts index e3576d8c0a0..5a518acc50d 100644 --- a/libs/docs/core/tabs/examples/tab-stacked-content-example/tab-stacked-content-example.component.ts +++ b/libs/docs/core/tabs/examples/tab-stacked-content-example/tab-stacked-content-example.component.ts @@ -20,4 +20,10 @@ export class TabStackedContentExampleComponent { this.tabs.push({ title: `Tab ${i}`, content: `Content ${i}` }); } } + + showZeroTabLater(): void { + setTimeout(() => { + this.showZeroTab = true; + }, 2000); + } }