带有自定义组件的角包裹角材料标签组件
Posted
技术标签:
【中文标题】带有自定义组件的角包裹角材料标签组件【英文标题】:Angular wrapping angular material tabs component with in custom components 【发布时间】:2021-09-05 20:24:54 【问题描述】:我想在这里实现的是我想在我的共享组件中包装 angular material tabs 组件。
所以,这是我要包装的组件:
PS:我可以在每个标签中显示组件:
<mat-tab-group>
<mat-tab label="First"> Content 1 </mat-tab>
<mat-tab label="Second"> Content 2 </mat-tab>
<mat-tab label="Third"> Content 3 </mat-tab>
</mat-tab-group>
所以,我想使用包装器来使用它:
<app-wrapper>
<app-item>
<app-item-header title="first"></app-item-header>
<app-item-content>
<app-needs-to-be-displayed></app-needs-to-be-displayed>
</app-item-content>
</app-item>
</app-wrapper>
app-wrapper.html
<mat-tab-group>
<ng-content></ng-content>
</mat-tab-group>
TS 类没有变化
app-item.html
<mat-tab>
<ng-content></ng-content>
</mat-tab>
TS 类没有变化
app-item-header.html
<ng-template mat-tab-label>
title
</ng-template>
app-item-header.ts 类
@Input() title:string = ''
app-item-content.html
<div>
<ng-content></ng-content>
</div>
TS 类没有变化,这可以容纳一个实际的组件
这在控制台中没有错误,但页面上也没有出现任何内容。
这里是 stackblitz 版本
https://stackblitz.com/edit/angular-wrapping-component-with-ng-content
PS:如果这是实现这一目标的最佳解决方案,请建议大家 还是有其他解决方案?
【问题讨论】:
stackblitz 的层次结构比问题更复杂。它还使用content projection,其中相同的选择 .app-item 似乎在层次结构中发生冲突。 主要思想是我需要将在示例中由角度材料提供的ui组件包装到本地组件中,组件中的包装器和组件中的内容等等 【参考方案1】:您看不到任何内容,因为mat-tab
组件必须是mat-tab-group
组件的直接子级,否则它不知道存在任何选项卡。因此,您需要以不同的方式处理事情。您需要从自定义组件中获取内容,然后在包装器组件中呈现所有内容。我认为最简单的方法是将内容作为模板获取,它也非常接近您创建的内容。我将从最低的组件开始,然后向上移动。
app-item-content
组件可以是您创建的那样。 app-item-header
需要更改。与选项卡一样,mat-tab-label
指令也需要直接在mat-tab-group
内应用。这就是我将其从模板中删除的原因。
<ng-template>
title
</ng-template>
主要变化是我使用ViewChild 装饰器将组件内部的ng-template
也作为代码中的属性公开。这使得模板也可以从组件外部访问。
@Component(
selector: 'app-item-header',
templateUrl: './item-header.component.html',
styleUrls: ['./item-header.component.css']
)
export class ItemHeaderComponent implements OnInit
@ViewChild(TemplateRef) public headerTemplate: TemplateRef<any>;
@Input() title:string = ''
之后您可以移动到app-item
组件。这里也只是模板的一个小改动。使用与标题组件中相同的方法,您可以获得项目内容的模板。
<ng-template>
<ng-content select="app-item-content"t></ng-content>
<ng-template>
在代码中,您可以像以前一样再次使用ViewChild 装饰器来获取内容模板。 header 是 item 的子组件,要获取它,您需要使用不同但相似的 ContentChild 装饰器来访问提供 header 模板的 header 组件。
@Component(
selector: 'app-item',
templateUrl: './item.component.html',
styleUrls: ['./item.component.css']
)
export class ItemComponent implements OnInit
@ViewChild(TemplateRef) public contentTemplate: TemplateRef<any>;
@ContentChild(ItemHeaderComponent) public itemHeader: ItemHeaderComponent;
此时,您可以访问在mat-tab
组件中呈现内容所需的一切。在模板中,您需要渲染与每个app-item
组件对应的mat-tab-group
和mat-tab
,以及之前公开的模板中的内容。
<mat-tab-group>
<mat-tab *ngFor="let item of appItems">
<ng-template mat-tab-label>
<ng-container *ngTemplateOutlet="item.itemHeader.headerTemplate"></ng-container>
</ng-template>
<ng-container *ngTemplateOutlet="item.contentTemplate"></ng-container>
</mat-tab>
</mat-tab-group>
正如您所看到的,您为每个项目创建一个选项卡并在项目的内容中呈现非常简单。有点棘手的是您需要在另一个 ng-template
中呈现模板的标题,以便能够添加被识别为标题内容的 mat-tab-label
指令。
要在包装器组件中获取所有 app-item
组件,请使用 ContentChildren 装饰器,它提供内容内的组件列表。就像前面的例子一样,我们只是在代码中添加一个属性,其余的由 Angular 处理。
@Component(
selector: 'app-wrapper',
templateUrl: './wrapper.component.html',
styleUrls: ['./wrapper.component.css']
)
export class WrapperComponent implements OnInit
@ContentChildren(ItemComponent) public appItems: QueryList<ItemComponent>;
我还创建了一个fork of you StackBlitz,您可以在其中看到它的工作原理。
【讨论】:
以上是关于带有自定义组件的角包裹角材料标签组件的主要内容,如果未能解决你的问题,请参考以下文章