如何将 Mat Tab 正文强制为非活动选项卡的 render/bind html 元素
How to force Mat Tab body to render/bind html element for inactive tab
我正在使用 angular mat-tab-group
我如何强制 angular 绑定非活动选项卡的 html 元素,下面是 html 实现
<mat-tab label="Test">
<app-test></app-test>
</mat-tab>
test.component.ts 文件已初始化并且 运行,但 html 元素未绑定,请查看下面的附图。有没有办法强制 angular 绑定它?我正在集成一些第 3 方库,该库要求在 component.ts 文件开始执行时绑定 html 元素,否则它将中断。
恐怕你做不到,你可以使用事件(selectedTabChange)或(selectedIndexChange)。注意:如果您在@Output 中看到关于 TabMatGroup 的 API,您将拥有所有可以“到达”的“事件”,您总是使用,例如(selectedTabChange)="yourFunction($event)"
并且函数的参数是“EmitterEvent”下 API 中的指示 - 在这种情况下是类型 MatTabChangeEvent
-
存在另一个选项,即创建一个没有内容的标签组,并使用变量索引
//in your .ts
index=0
然后你创建一个 .html like
<!-- see that you use margin-bottom and animationDuration -->
<mat-tab-group style="margin-bottom:5px;" animationDuration="0"
mat-align-tabs="start" (selectedIndexChange)="index=$event">
<!-- you makes the mat-tabs "empty" -->
<mat-tab label="First"></mat-tab>
<mat-tab label="Second"></mat-tab>
<mat-tab label="Third"></mat-tab>
</mat-tab-group>
<!--here you put your content using [style.display]="none" when
the index is not equal to hte value (remember index begings by 0-->
<div [style.display]="index!=0?'none':null">
Content 1
</div>
<div [style.display]="index!=1?'none':null">
Content 2
</div>
<div [style.display]="index!=2?'none':null">
Content 3
</div>
但是您需要手动创建“动画”。为此,您可以将动画添加到组件中
animations: [
trigger('flyInOut', [
transition(':decrement', [
style({ transform: 'translateX(100%)' }),
animate(200)
]),
transition(':increment', [
style({ transform: 'translateX(100%)' }),
animate(200)
])
])
]
并使用辅助变量“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>
注意:实际上它与 mat-tab 中的动画并不“完全一样”,请随意更改动画以使其更接近
更新一个“模拟”mat-tab动画的动画
我们需要一次看到两个“选项卡”,因此我们需要“包装”div 中的选项卡,并使位置相对并使其成为绝对位置。这使我们需要知道选项卡的“高度”。所以我们将使用“visibility”而不是“display”,但首先我们要定义四个动画
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
])
])
]
如果“i”是 index 或 indexOld,我们将看到选项卡,并且要获得“动画”,我们将使用一个函数
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
}
还有.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>
看到包装器class表明
.wrapper
{
position:relative;
width:100%;
}
.wrapper>div
{
position:absolute;
width:100%;
}
最后一步是知道“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'
})
}
你可以看到 final stackblitz
我正在使用 angular mat-tab-group 我如何强制 angular 绑定非活动选项卡的 html 元素,下面是 html 实现
<mat-tab label="Test">
<app-test></app-test>
</mat-tab>
test.component.ts 文件已初始化并且 运行,但 html 元素未绑定,请查看下面的附图。有没有办法强制 angular 绑定它?我正在集成一些第 3 方库,该库要求在 component.ts 文件开始执行时绑定 html 元素,否则它将中断。
恐怕你做不到,你可以使用事件(selectedTabChange)或(selectedIndexChange)。注意:如果您在@Output 中看到关于 TabMatGroup 的 API,您将拥有所有可以“到达”的“事件”,您总是使用,例如(selectedTabChange)="yourFunction($event)"
并且函数的参数是“EmitterEvent”下 API 中的指示 - 在这种情况下是类型 MatTabChangeEvent
-
存在另一个选项,即创建一个没有内容的标签组,并使用变量索引
//in your .ts
index=0
然后你创建一个 .html like
<!-- see that you use margin-bottom and animationDuration -->
<mat-tab-group style="margin-bottom:5px;" animationDuration="0"
mat-align-tabs="start" (selectedIndexChange)="index=$event">
<!-- you makes the mat-tabs "empty" -->
<mat-tab label="First"></mat-tab>
<mat-tab label="Second"></mat-tab>
<mat-tab label="Third"></mat-tab>
</mat-tab-group>
<!--here you put your content using [style.display]="none" when
the index is not equal to hte value (remember index begings by 0-->
<div [style.display]="index!=0?'none':null">
Content 1
</div>
<div [style.display]="index!=1?'none':null">
Content 2
</div>
<div [style.display]="index!=2?'none':null">
Content 3
</div>
但是您需要手动创建“动画”。为此,您可以将动画添加到组件中
animations: [
trigger('flyInOut', [
transition(':decrement', [
style({ transform: 'translateX(100%)' }),
animate(200)
]),
transition(':increment', [
style({ transform: 'translateX(100%)' }),
animate(200)
])
])
]
并使用辅助变量“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>
注意:实际上它与 mat-tab 中的动画并不“完全一样”,请随意更改动画以使其更接近
更新一个“模拟”mat-tab动画的动画
我们需要一次看到两个“选项卡”,因此我们需要“包装”div 中的选项卡,并使位置相对并使其成为绝对位置。这使我们需要知道选项卡的“高度”。所以我们将使用“visibility”而不是“display”,但首先我们要定义四个动画
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
])
])
]
如果“i”是 index 或 indexOld,我们将看到选项卡,并且要获得“动画”,我们将使用一个函数
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
}
还有.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>
看到包装器class表明
.wrapper
{
position:relative;
width:100%;
}
.wrapper>div
{
position:absolute;
width:100%;
}
最后一步是知道“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'
})
}
你可以看到 final stackblitz