从 Angular Material 选项卡内容中获取滚动位置
Get the scroll position from an Angular Material Tab content
我使用带有自定义组件的 Angular Material 选项卡组件作为选项卡的内容。
选项卡列表来自 API.
我需要获取 mat-tab-body-content
的滚动索引,因为带有此 class 的元素具有我需要的 scrollTop
值。
我可以使用以下 JS 表达式获取 scrollTop
值:
document.getElementsByClassName('mat-tab-body-content')[index];
其中 index
是选定的选项卡,mat-tab-body-content
中有滚动位置。
问题是我找不到触发的事件 在 更改 Tab 之前,加上这种方法是不完整的,因为不考虑对当前 Tab 所做的所有更改以及更改 Route 时。
这是我的根容器组件模板:
<section class="page">
<ng-container *ngIf="adressenTabsList$ | async as tabsContainer">
<form [formGroup]="adressenForm" *ngIf="tabsContainer.tabsList.length > 0 && !isLoading; else noResults">
<mat-tab-group animationDuration="0ms" selectedTabChange)="onTabSelected($event)">
<mat-tab *ngFor="let tab of tabsContainer.tabsList; trackBy: trackById; index as idx"
[label]="tab.label">
<span [ngSwitch]="tab.tabLabelKey">
<ng-container *ngSwitchCase="tabsType.kunde">
<kunde-tab [kundeForm]="kundeForm"></kunde-tab>
</ng-container>
</ng-container>
<ng-container *ngSwitchCase="tabsType.personen">
...
</ng-container>
</span>
</mat-tab>
</mat-tab-group>
</section>
在组件中,我只是从后端获取选项卡对象:
this.adressenTabsList$ = this.adressenService.getTabs()
.pipe(
map((list: TabList) => list)
);
我希望能够为每个 Tab 内容获取具有 class mat-tab-body-content
的元素的 scrollTop
值(如下图所示)。
我尝试使用以下代码与可滚动选项卡内容进行交互,但我注意到没有注册的可滚动元素(即使 mat 选项卡内容应用了 cdkscrollable
指令(见上图) ,因此永远不会触发以下代码:
this.scrollDispatcher.scrolled()
.pipe(
)
.subscribe((cdk: CdkScrollable) => {
this.zone.run(() => {
const scrollPosition = cdk.getElementRef().nativeElement.scrollTop;
console.log(scrollPosition);
});
});
我可以使用 _MatTabGroupBase
摘要 class 中的私有事件处理程序 _handleClick
来拦截 Tab 单击,然后相应地应用我们的逻辑来解决我的问题。
如果您有兴趣,我在 Dev.to article 中描述了该过程。
相关代码如下:
模板
<mat-tab-group mat-align-tabs="start">
<mat-tab label="First">Content first tab</mat-tab>
<mat-tab label="Second">Content second tab</mat-tab>
<mat-tab label="Third">Content third tab</mat-tab>
</mat-tab-group>
组件class
import {
AfterViewInit,
ChangeDetectionStrategy,
Component,
ViewChild,
} from '@angular/core';
import { MatTabChangeEvent, MatTabGroup } from '@angular/material/tabs';
@Component({
selector: 'app-component,
templateUrl: './app-component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent implements AfterViewInit {
// Get a reference of the MatTabGroup form the template
@ViewChild(MatTabGroup)
tabs?: MatTabGroup;
private currentTabIndex = 0;
ngAfterViewInit() {
this.registerTabClick();
}
registerTabClick(): void {
// Get the handler reference
const handleTabClick = this.tabs._handleClick;
this.tabs._handleClick = (tab, header, index) => {
// Get tab content reference for the current Tab -> currentTabIndex
// since index here is already the "new" tab index
const tabContent = this.getTabContentElement(this.currentTabIndex);
const scrollPosition = Math.round(tabContent.scrollTop) || 0;
this.store.dispatch(
setTabScrollPosition({
scrollPosition: scrollPosition,
// ... other props
})
);
// If you want to prevent the user to navigate to the new tab,
// you can avoid invoking the 'apply' method below
handleTabClick.apply(this.tabs, [tab, header, index]);
// We update the currentIndex, as we need it again when
// another tab is clicked
this.currentTabIndex = index;
};
}
// Returns the <mat-tab-body-content> with the tab content scroll
position given the target tab index
private getTabContentElement(tabIndex: number) {
return document.getElementsByClassName('mat-tab-body-content')[tabIndex];
}
}
我使用带有自定义组件的 Angular Material 选项卡组件作为选项卡的内容。 选项卡列表来自 API.
我需要获取 mat-tab-body-content
的滚动索引,因为带有此 class 的元素具有我需要的 scrollTop
值。
我可以使用以下 JS 表达式获取 scrollTop
值:
document.getElementsByClassName('mat-tab-body-content')[index];
其中 index
是选定的选项卡,mat-tab-body-content
中有滚动位置。
问题是我找不到触发的事件 在 更改 Tab 之前,加上这种方法是不完整的,因为不考虑对当前 Tab 所做的所有更改以及更改 Route 时。
这是我的根容器组件模板:
<section class="page">
<ng-container *ngIf="adressenTabsList$ | async as tabsContainer">
<form [formGroup]="adressenForm" *ngIf="tabsContainer.tabsList.length > 0 && !isLoading; else noResults">
<mat-tab-group animationDuration="0ms" selectedTabChange)="onTabSelected($event)">
<mat-tab *ngFor="let tab of tabsContainer.tabsList; trackBy: trackById; index as idx"
[label]="tab.label">
<span [ngSwitch]="tab.tabLabelKey">
<ng-container *ngSwitchCase="tabsType.kunde">
<kunde-tab [kundeForm]="kundeForm"></kunde-tab>
</ng-container>
</ng-container>
<ng-container *ngSwitchCase="tabsType.personen">
...
</ng-container>
</span>
</mat-tab>
</mat-tab-group>
</section>
在组件中,我只是从后端获取选项卡对象:
this.adressenTabsList$ = this.adressenService.getTabs()
.pipe(
map((list: TabList) => list)
);
我希望能够为每个 Tab 内容获取具有 class mat-tab-body-content
的元素的 scrollTop
值(如下图所示)。
我尝试使用以下代码与可滚动选项卡内容进行交互,但我注意到没有注册的可滚动元素(即使 mat 选项卡内容应用了 cdkscrollable
指令(见上图) ,因此永远不会触发以下代码:
this.scrollDispatcher.scrolled()
.pipe(
)
.subscribe((cdk: CdkScrollable) => {
this.zone.run(() => {
const scrollPosition = cdk.getElementRef().nativeElement.scrollTop;
console.log(scrollPosition);
});
});
我可以使用 _MatTabGroupBase
摘要 class 中的私有事件处理程序 _handleClick
来拦截 Tab 单击,然后相应地应用我们的逻辑来解决我的问题。
如果您有兴趣,我在 Dev.to article 中描述了该过程。
相关代码如下:
模板
<mat-tab-group mat-align-tabs="start">
<mat-tab label="First">Content first tab</mat-tab>
<mat-tab label="Second">Content second tab</mat-tab>
<mat-tab label="Third">Content third tab</mat-tab>
</mat-tab-group>
组件class
import {
AfterViewInit,
ChangeDetectionStrategy,
Component,
ViewChild,
} from '@angular/core';
import { MatTabChangeEvent, MatTabGroup } from '@angular/material/tabs';
@Component({
selector: 'app-component,
templateUrl: './app-component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent implements AfterViewInit {
// Get a reference of the MatTabGroup form the template
@ViewChild(MatTabGroup)
tabs?: MatTabGroup;
private currentTabIndex = 0;
ngAfterViewInit() {
this.registerTabClick();
}
registerTabClick(): void {
// Get the handler reference
const handleTabClick = this.tabs._handleClick;
this.tabs._handleClick = (tab, header, index) => {
// Get tab content reference for the current Tab -> currentTabIndex
// since index here is already the "new" tab index
const tabContent = this.getTabContentElement(this.currentTabIndex);
const scrollPosition = Math.round(tabContent.scrollTop) || 0;
this.store.dispatch(
setTabScrollPosition({
scrollPosition: scrollPosition,
// ... other props
})
);
// If you want to prevent the user to navigate to the new tab,
// you can avoid invoking the 'apply' method below
handleTabClick.apply(this.tabs, [tab, header, index]);
// We update the currentIndex, as we need it again when
// another tab is clicked
this.currentTabIndex = index;
};
}
// Returns the <mat-tab-body-content> with the tab content scroll
position given the target tab index
private getTabContentElement(tabIndex: number) {
return document.getElementsByClassName('mat-tab-body-content')[tabIndex];
}
}