如何强制 Mat Tab 主体渲染/绑定非活动选项卡的 html 元素

nic*_*ker 5 angular-material angular

我正在使用 Angular mat-tab-group 我如何强制 Angular 绑定非活动选项卡的 html 元素,下面是 html 实现

<mat-tab label="Test">
    <app-test></app-test>
</mat-tab>
Run Code Online (Sandbox Code Playgroud)

test.component.ts 文件确实初始化并运行,但 html 元素未绑定,请查看下面的附图。有没有办法强制角度绑定它?我正在集成一些第 3 方库,该库要求在 component.ts 文件开始执行时绑定 html 元素,否则它将中断。

在此输入图像描述

Eli*_*seo 4

恐怕你不能,你可以使用事件(selectedTabChange)或(selectedIndexChange)。注意:如果您在@Output中看到有关TabMatGroup的API,则您拥有可以“到达”的所有“事件”,您总是使用例如,(selectedTabChange)="yourFunction($event)"并且该函数的参数是API中“EmitterEvent”下的指示 - 在这种情况下属于类型MatTabChangeEvent-

存在另一个选项,即创建一个没有内容的选项卡组,并使用可变索引

//in your .ts
index=0
Run Code Online (Sandbox Code Playgroud)

然后你创建一个 .html 像

//in your .ts
index=0
Run Code Online (Sandbox Code Playgroud)

但您需要手动创建“动画”。为此,您可以将动画添加到组件中

  animations: [
    trigger('flyInOut', [
      transition(':decrement', [
        style({ transform: 'translateX(100%)' }),
        animate(200)
      ]),
      transition(':increment', [
        style({ transform: 'translateX(100%)' }),
        animate(200)
      ])
    ])
  ]
Run Code Online (Sandbox Code Playgroud)

并使用辅助变量“indexOld”。然后在html中使用动画

<mat-tab-group style="margin-bottom:5px;" animationDuration="0" 
     mat-align-tabs="start" (selectedIndexChange)="index=$event">
  <mat-tab label="First"></mat-tab>
  <mat-tab label="Second"></mat-tab>
  <mat-tab label="Third"></mat-tab>
</mat-tab-group>

<!--see that now I use "indexOld", not "index"
    when the animation is done, you equal indexOld to index-->

<div [style.display]="indexOld!=0?'none':null" [@flyInOut]="index" (@flyInOut.done)="indexOld=index">
  Content 1
</div>
<div [style.display]="indexOld!=1?'none':null" [@flyInOut]="index" (@flyInOut.done)="indexOld=index">
Content 2
</div>
<div [style.display]="indexOld!=2?'none':null" [@flyInOut]="index" (@flyInOut.done)="indexOld=index">
Content 3
</div>
Run Code Online (Sandbox Code Playgroud)

查看堆栈闪电战

注意:实际上,它与 mat-tab 中的动画并不“精确”,可以随意更改动画以使其更接近

更新“模拟”mat-tab 动画的动画

我们需要一次看到两个“选项卡”,因此我们需要将选项卡“包装”在 div 中,使其位置相对,并使位置绝对。这使得我们需要知道选项卡的“高度”。所以我们将使用“可见性”而不是“显示”,但首先我们将定义四个动画

  animations: [
    trigger('flyInOut', [
      transition('*=>inmore', [
        style({ transform: 'translateX(100%)' }), //start in
        animate(200)
      ]),
      transition('*=>inless', [
        style({ transform: 'translateX(-100%)' }), //start in
        animate(200)
      ]),
      transition('*=>outless', [
        animate(200, style({ transform: 'translateX(100%)' })) //end in
      ]),
      transition('*=>outmore', [
        animate(200, style({ transform: 'translateX(-100%)' })) //end in
      ])
    ])
  ]
Run Code Online (Sandbox Code Playgroud)

我们将查看选项卡,如果“i”是索引或索引旧,并获取“动画”,我们将使用一个函数

  getAnimation(i:number,indexOld:number,index:number)
  {
    const from=(i==index)?'in':(i==indexOld)?'out':null
    if (from && indexOld!=index)
        return from+(indexOld>index?'less':'more')
    return null
  }
Run Code Online (Sandbox Code Playgroud)

和 .html 一样

<div class="wrapper" [style.height]="maxHeigth">
  <div #tab [style.visibility]="index!=0 && indexOld!=0?'hidden':null" [@flyInOut]="getAnimation(0,indexOld,index)"
    (@flyInOut.done)="indexOld=index">
    Content 1
  </div>
  <div #tab [style.visibility]="index!=1 && indexOld!=1?'hidden':null" [@flyInOut]="getAnimation(1,indexOld,index)"
    (@flyInOut.done)="indexOld=index">
    Content 2
  </div>
  <div #tab [style.visibility]="index!=2 && indexOld!=2?'hidden':null" [@flyInOut]="getAnimation(2,indexOld,index)"
    (@flyInOut.done)="indexOld=index">
    Content 3
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

查看包装类指示

.wrapper
{
  position:relative;
  width:100%;
}
.wrapper>div
{
  position:absolute;
  width:100%;
}
Run Code Online (Sandbox Code Playgroud)

最后一步是知道“maxHeigth”,因此,我们将使用 viewChildren 获取“选项卡”,并在 setTimeout 中包含的 ngAfterViewInit 中获取 maxHeigth

  maxHeigth:string;
  @ViewChildren('tab') tabs:QueryList<ElementRef>

  ngAfterViewInit()
  {
    setTimeout(()=>{
    this.maxHeigth=this.tabs.map(x=>x.nativeElement.getBoundingClientRect().height)
                 .reduce((a,b)=>a>b?a:b,0)+'px'
    })
  }
Run Code Online (Sandbox Code Playgroud)

你可以看到最后的stackblitz