多行垫选项卡组 [英] Multiline mat tab group
问题描述
所以,我有一个 mat 标签组,用户可以在其中动态添加标签.
<mat-tab *ngFor="let tab of tabs;让 tabIndex = index"><ng-template mat-tab-label>{{ tab.title }}<i class="material-icons";(click)=removeTab(tabIndex)">close</i></ng-模板><div><app-tab-content [tab]=tab"></app-tab-content>
</mat-tab><mat-tab 禁用><ng-template mat-tab-label><button mat-stroked-button (click)="addNewTab()">添加新标签</button></ng-模板></mat-tab></mat-tab-group>
代码工作正常,但我需要知道是否有办法在发生这种情况时将新标签放在第二行:
with TotallyNewb 解决方案存在一个问题,即inkBar 不会垂直跟随选定的选项卡,并且在某些情况下也会水平跟随(例如,如果内容被调整大小 - 而不是窗口).
我的方法类似,但有一些改进:
使用
...
实施
1.全局定义新样式
我可以使用组件样式,但这会有其他缺点.
我没有使用disablePagination,只是因为我的版本是8.2.3我隐藏了控件.
.mat-tab-group.mat-tab-multiline {.mat-tab-header:first-child {.mat-tab-header-分页{显示:无;}.mat-tab-labels {flex-wrap: 包裹;}}}
2.定义指令
@Directive({选择器:'[matMultilineTab]',})导出类 MatMultilineTabDirective 实现 OnInit、OnDestroy {@HostBinding('class.mat-tab-multiline') class = true;私有只读 onDestroy = new Subject();私有只读 resizeObserver: ResizeObserver;私人调整大小超时:数字;构造函数(私有元素引用:元素引用,私人 matTabGroup:MatTabGroup){this.matTabGroup.selectedTabChange.pipe(takeUntil(this.onDestroy)).subscribe(() => this.updateInkBarPosition());this.resizeObserver = new ResizeObserver(() => {如果(this.resizeTimeout)clearTimeout(this.resizeTimeout);this.resizeTimeout = setTimeout(() => this.updateInkBarPosition(), 100);});}ngOnInit() {this.resizeObserver.observe(this.elementRef.nativeElement.querySelector('.mat-tab-header:first-child'));}ngOnDestroy() {this.resizeObserver &&this.resizeObserver.disconnect();this.onDestroy.next();this.onDestroy.complete();}私人 updateInkBarPosition() {const headerElement: HTMLElement = this.elementRef.nativeElement.querySelector('.mat-tab-header:first-child');const activeTabElement: HTMLElement = headerElement.querySelector('.mat-tab-label-active');constinkBarElement: HTMLElement = headerElement.querySelector('.mat-ink-bar');const listElement: HTMLElement = headerElement.querySelector('.mat-tab-list');const 底部 = listElement.offsetHeight -(activeTabElement.offsetTop + activeTabElement.offsetHeight);inkBarElement.style.bottom = 底部 + 'px';inkBarElement.style.left = activeTabElement.offsetLeft + 'px';}}
So, i have a mat tab group where the tabs can be added dinamically by the user.
<mat-tab-group class="main-tab-group mt-2" [selectedIndex]="selectedTab" (selectedTabChange)="tabChanged($event)">
<mat-tab *ngFor="let tab of tabs; let tabIndex = index">
<ng-template mat-tab-label>{{ tab.title }}
<i class="material-icons" (click)="removeTab(tabIndex)">close</i>
</ng-template>
<div>
<app-tab-content [tab]="tab"></app-tab-content>
</div>
</mat-tab>
<mat-tab disabled>
<ng-template mat-tab-label>
<button mat-stroked-button (click)="addNewTab()">Add new tab</button>
</ng-template>
</mat-tab>
</mat-tab-group>
the code is working fine but i need to know if there is a way to put the new tabs on a second line when this happens:
with TotallyNewb solution there is a problem that inkBar does not follow selected tab vertically, and in some cases also horizontally (e.g. if the content is resized - not the window).
My approach was similar but with some improvements:
Usage
<mat-tab-group matMultilineTab>...</mat-tab-group>
Implementation
1. Define new style globally
I could use component style, however that would have other drawbacks.
I did not use disablePagination, simply because my version was 8.2.3 thus I'm hiding the controls instead.
.mat-tab-group.mat-tab-multiline { .mat-tab-header:first-child { .mat-tab-header-pagination { display: none; } .mat-tab-labels { flex-wrap: wrap; } } }
2. Define directive
@Directive({
selector: '[matMultilineTab]',
})
export class MatMultilineTabDirective implements OnInit, OnDestroy {
@HostBinding('class.mat-tab-multiline') class = true;
private readonly onDestroy = new Subject();
private readonly resizeObserver: ResizeObserver;
private resizeTimeout: number;
constructor(
private elementRef: ElementRef,
private matTabGroup: MatTabGroup
) {
this.matTabGroup.selectedTabChange.pipe(
takeUntil(this.onDestroy)
).subscribe(() => this.updateInkBarPosition());
this.resizeObserver = new ResizeObserver(() => {
if (this.resizeTimeout)
clearTimeout(this.resizeTimeout);
this.resizeTimeout = setTimeout(() => this.updateInkBarPosition(), 100);
});
}
ngOnInit() {
this.resizeObserver.observe(
this.elementRef.nativeElement.querySelector('.mat-tab-header:first-child')
);
}
ngOnDestroy() {
this.resizeObserver && this.resizeObserver.disconnect();
this.onDestroy.next();
this.onDestroy.complete();
}
private updateInkBarPosition() {
const headerElement: HTMLElement = this.elementRef.nativeElement.querySelector(
'.mat-tab-header:first-child'
);
const activeTabElement: HTMLElement = headerElement.querySelector(
'.mat-tab-label-active'
);
const inkBarElement: HTMLElement = headerElement.querySelector('.mat-ink-bar');
const listElement: HTMLElement = headerElement.querySelector('.mat-tab-list');
const bottom = listElement.offsetHeight -
(activeTabElement.offsetTop + activeTabElement.offsetHeight);
inkBarElement.style.bottom = bottom + 'px';
inkBarElement.style.left = activeTabElement.offsetLeft + 'px';
}
}
这篇关于多行垫选项卡组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!