多行垫选项卡组 [英] Multiline mat tab group

查看:27
本文介绍了多行垫选项卡组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我有一个 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆