如何将一个组件选择器传递给另一个组件?
How to pass one component selector to another component?
我正在尝试创建全局组件,以便其他开发人员可以将此组件用于他们的项目。
这里的目标是,我有一个名为 app.component.ts 的本地组件,它有一个 child 组件。我已经捆绑了全局组件并保存在 node_modules 文件夹中。
app.component.html
<p-table #dt [value]='genes' [columns]="tableHeader" dataKey="geneName">
<ng-template pTemplate="header">
<th></th>
<th>Gene</th>
<th>Position</th>
<th>Value</th>
</ng-template>
<ng-template pTemplate="body" let-columns="columns" let-expanded="expanded" let-gene>
<tr [pSelectableRow]="gene">
...
</tr>
</ng-template>
<ng-template pTemplate="rowexpansion" let-rowData let-columns="columns">
<tr>
<gene-child [geneData]="rowData" (geneSelection)="selection()"> </gene-child>
</tr>
</ng-template>
</p-table>
child.component.ts
import { ConfirmationService } from 'primeng/api';
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'gene-child',
templateUrl: './gene.html',
})
export class GeneChildComponent implements OnInit {
@Input() geneName: any;
@Output() geneSelection = new EventEmitter();
以上代码运行良好,没有任何问题。
现在我正在创建全局组件来处理来自 parent 组件的 priemng table,我只需要传递 headers 和数据。
更新代码
app.component.html
<bio-tables [tableData]="genes" [header]="tableHeader"></bio-tables>
以上代码也可以正常工作。
但这里 我的问题是我需要将“选择器”gene-child
传递给全局组件 所以我做了以下操作,但它给出了错误,
<bio-tables [tableData]="genes" [header]="tableHeader" [rowExpansionSelector]="gene-child"></bio-tables>
我尝试将 gene-child 组件存储到一个变量中并尝试传递它,如下面的代码
app.component.ts
import { GeneChildComponent } from './gene-child.component.ts';
...
export class ....{
geneChlid = GeneChildComponent;
app.component.html
<bio-tables [tableData]="genes" [header]="tableHeader" [rowExpansionSelector]="geneChild"></bio-tables>
以上代码也不起作用。我不确定如何将选择器传递给 child 组件。
您可以传递模板,然后根据需要进行渲染
app.component.html
<bio-tables ... [rowExpansionTpl]="geneTpl">
</bio-tables>
<ng-template #geneTpl let-params="params">
<gene-child [geneName]="params.gene" (geneSelection)="selection(params)"> </gene-child>
</ng-template>
bio-tables.component.html
<div>
<ng-container *ngTemplateOutlet="rowExpansionTpl; context: {params: {gene: 'anything'}}"></ng-container>
</div>
据我了解,您想将动态组件传递给 bio-tables
组件,如果是这样,您可以尝试执行以下操作:
创建和抽象 class 我们称之为 GenericChild
在这里定义您对组件的期望。
export abstract class GenericChild {
abstract geneName: any;
abstract geneSelection: EventEmitter<any>;
}
制作 GeneChildComponent
或任何你想要的组件,从这个抽象 class.
扩展
export class GeneChildComponent extends GenericChild {
@Input() geneName: any;
@Output() geneSelection = new EventEmitter<any>();
}
我们将创建一个包装器组件,以便我们可以访问 let-rowData
,该包装器将创建一个子组件(GeneChildComponent
,即动态组件)。为此,我们需要一个 ng-contaier
作为 ViewContainerRef
并且我们将从 GenericChild.
扩展
要创建组件,我们将使用 ComponentFactoryResolver
。
模板:
<ng-container #child></ng-container>
组件:
export class ChildWrapper extends GenericChild {
@Input()
genericChild: Type<GenericChild>;
@Input()
geneData: any;
@Output()
geneSelection: EventEmitter<any> = new EventEmitter<any>();
@ViewChild("child", { read: ViewContainerRef })
childsContainer: ViewContainerRef;
constructor(
private factory: ComponentFactoryResolver,
private cdr: ChangeDetectorRef
) {
super();
}
//create the component in the container, and set the values of the instance.
ngAfterViewInit(): void {
const componentFactory = this.factory.resolveComponentFactory(
this.genericChild
);
const ref = this.childsContainer.createComponent(componentFactory);
ref.instance.geneData = this.geneData;
ref.instance.geneSelection.subscribe(event => {
this.geneSelection.emit(event);
});
this.cdr.detectChanges();
}
}
用类似下面的内容替换主组件中的模板,并创建一个@Input 来传递动态组件 (genericChild)。
<ng-template pTemplate="rowexpansion" let-rowData>
<tr>
<child-wrapper
[genericChild]="genericChild"
[geneData]="rowData"
(geneSelection)="selection($event)"
></child-wrapper>
</tr>
</ng-template>
那么您需要做的就是:
//app.component.html
<bio-tables [genericChild]="geneChildComponent"></bio-tables>
//app.component.ts
geneChildComponent: Type<GeneChildComponent> = GeneChildComponent;
我正在尝试创建全局组件,以便其他开发人员可以将此组件用于他们的项目。
这里的目标是,我有一个名为 app.component.ts 的本地组件,它有一个 child 组件。我已经捆绑了全局组件并保存在 node_modules 文件夹中。
app.component.html
<p-table #dt [value]='genes' [columns]="tableHeader" dataKey="geneName">
<ng-template pTemplate="header">
<th></th>
<th>Gene</th>
<th>Position</th>
<th>Value</th>
</ng-template>
<ng-template pTemplate="body" let-columns="columns" let-expanded="expanded" let-gene>
<tr [pSelectableRow]="gene">
...
</tr>
</ng-template>
<ng-template pTemplate="rowexpansion" let-rowData let-columns="columns">
<tr>
<gene-child [geneData]="rowData" (geneSelection)="selection()"> </gene-child>
</tr>
</ng-template>
</p-table>
child.component.ts
import { ConfirmationService } from 'primeng/api';
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'gene-child',
templateUrl: './gene.html',
})
export class GeneChildComponent implements OnInit {
@Input() geneName: any;
@Output() geneSelection = new EventEmitter();
以上代码运行良好,没有任何问题。
现在我正在创建全局组件来处理来自 parent 组件的 priemng table,我只需要传递 headers 和数据。
更新代码
app.component.html
<bio-tables [tableData]="genes" [header]="tableHeader"></bio-tables>
以上代码也可以正常工作。
但这里 我的问题是我需要将“选择器”gene-child
传递给全局组件 所以我做了以下操作,但它给出了错误,
<bio-tables [tableData]="genes" [header]="tableHeader" [rowExpansionSelector]="gene-child"></bio-tables>
我尝试将 gene-child 组件存储到一个变量中并尝试传递它,如下面的代码
app.component.ts
import { GeneChildComponent } from './gene-child.component.ts';
...
export class ....{
geneChlid = GeneChildComponent;
app.component.html
<bio-tables [tableData]="genes" [header]="tableHeader" [rowExpansionSelector]="geneChild"></bio-tables>
以上代码也不起作用。我不确定如何将选择器传递给 child 组件。
您可以传递模板,然后根据需要进行渲染
app.component.html
<bio-tables ... [rowExpansionTpl]="geneTpl">
</bio-tables>
<ng-template #geneTpl let-params="params">
<gene-child [geneName]="params.gene" (geneSelection)="selection(params)"> </gene-child>
</ng-template>
bio-tables.component.html
<div>
<ng-container *ngTemplateOutlet="rowExpansionTpl; context: {params: {gene: 'anything'}}"></ng-container>
</div>
据我了解,您想将动态组件传递给 bio-tables
组件,如果是这样,您可以尝试执行以下操作:
创建和抽象 class 我们称之为 GenericChild
在这里定义您对组件的期望。
export abstract class GenericChild {
abstract geneName: any;
abstract geneSelection: EventEmitter<any>;
}
制作 GeneChildComponent
或任何你想要的组件,从这个抽象 class.
export class GeneChildComponent extends GenericChild {
@Input() geneName: any;
@Output() geneSelection = new EventEmitter<any>();
}
我们将创建一个包装器组件,以便我们可以访问 let-rowData
,该包装器将创建一个子组件(GeneChildComponent
,即动态组件)。为此,我们需要一个 ng-contaier
作为 ViewContainerRef
并且我们将从 GenericChild.
要创建组件,我们将使用 ComponentFactoryResolver
。
模板:
<ng-container #child></ng-container>
组件:
export class ChildWrapper extends GenericChild {
@Input()
genericChild: Type<GenericChild>;
@Input()
geneData: any;
@Output()
geneSelection: EventEmitter<any> = new EventEmitter<any>();
@ViewChild("child", { read: ViewContainerRef })
childsContainer: ViewContainerRef;
constructor(
private factory: ComponentFactoryResolver,
private cdr: ChangeDetectorRef
) {
super();
}
//create the component in the container, and set the values of the instance.
ngAfterViewInit(): void {
const componentFactory = this.factory.resolveComponentFactory(
this.genericChild
);
const ref = this.childsContainer.createComponent(componentFactory);
ref.instance.geneData = this.geneData;
ref.instance.geneSelection.subscribe(event => {
this.geneSelection.emit(event);
});
this.cdr.detectChanges();
}
}
用类似下面的内容替换主组件中的模板,并创建一个@Input 来传递动态组件 (genericChild)。
<ng-template pTemplate="rowexpansion" let-rowData>
<tr>
<child-wrapper
[genericChild]="genericChild"
[geneData]="rowData"
(geneSelection)="selection($event)"
></child-wrapper>
</tr>
</ng-template>
那么您需要做的就是:
//app.component.html
<bio-tables [genericChild]="geneChildComponent"></bio-tables>
//app.component.ts
geneChildComponent: Type<GeneChildComponent> = GeneChildComponent;