Angular 将组件作为另一个组件的 ng-template 传递
Angular pass a Component as ng-template of another Component
在我的 Angular 6 应用程序中,我需要将一个组件作为其 ng-template 传递给另一个组件。
原因是我有一个 Component A 我需要复制很多次,但每次它都必须包含不同的组件(让我们称它们为 组件 B 和 组件 C) 具有相同的输入。
组件 A 模板:
<div class="row-detail-panel">
<h4 class="row-detail-panel-title">{{ newEntity ? 'Add new' : 'Edit this'}} {{ entityName }}</h4>
<!--THIS IS THE COMPONENT I WANT TO INJECT-->
<app-component-b
[inline]="true"
[form]="form"
></app-component-b>
<!--END-->
<!--some more html code here-->
</div>
然后我创建一个 Component A 实例使用:
<app-component-a
[entity]="row"
[entityName]="entityName"
></app-component-a>
所以我想到了使用ng-template
,于是将Component A模板改成如下:
<div class="row-detail-panel">
<h4 class="row-detail-panel-title">{{ newEntity ? 'Add new' : 'Edit this'}} {{ entityName }}</h4>
<ng-template></ng-template>
<!--some more html code here-->
</div>
并创建一个 Component A 实例使用:
<app-component-a
[entity]="row"
[entityName]="entityName"
>
<app-component-b
[inline]="true"
[form]="form" <!--PROBLEM: "form" does not exist here-->
></app-component-b>
</app-component-a>
所以我可以轻松地注入 Component C 而不是 Component B 作为 Component A' s ng-模板:
<app-component-a
[entity]="row"
[entityName]="entityName"
>
<app-component-c
[inline]="true"
[form]="form" <!--PROBLEM: "form" does not exist here-->
></app-component-c>
</app-component-a>
问题:
我需要注入到组件B或组件C的变量form
只存在于中]Component A and not in Component A's parent(出于某些原因,我无法将其向上移动一级)。
我该如何解决这个问题?
你能做的是:
当您调用组件 A 时,您将一个 ng-template 传递给它,如下所示:
<app-component-a>
<ng-template *ngIf=”condition; else elseBlock”>
<app-component-b></app-component-b>
</ng-template>
<ng-template #elseBlock>
<app-component-c></app-component-c>
</ng-template>
</app-component-a>
现在在您的应用程序组件中-a.ts您这样做:
@ContentChild(TemplateRef) template: TemplateRef;
所以基本上模板会根据您的条件获取组件 b 或 c。
然后在组件 A 模板中,您这样做:
<ng-container [ngTemplateOutlet]="template"></ng-container>
所以现在你的 ng-container 将根据你的情况获得组件 B 或 C。
就你的表单而言,恐怕我唯一能想到的就是创建一个服务并在组件A中提供它,将其注入A,B和C并在其中共享表单服务。
但是如果您按照我上面显示的方式包含组件 B 和 C,Angular 将自行处理 B 和 C 组件的创建和销毁。
否则当你的ng-template条件改变时,你的组件B不会在实例化组件C时销毁。
编辑:
我能想到的另一件事是,如果您不在 A 实例化后立即调用组件 B 或 C,您也可以在 A 的 A 的父级 oninit 上发出 (@Output) 表单。这样当调用 B 或 C 时,A 的父级将有权访问表单并将其传递给 B 或 C。
你试过吗:
<app-component-a #compA
[entity]="row"
[entityName]="entityName">
<app-component-b
[inline]="true"
[form]="compA.form"
></app-component-b>
</app-component-a>
// component-a.html
<div class="row-detail-panel">
<h4 class="row-detail-panel-title">{{ newEntity ? 'Add new' : 'Edit this'}} {{ entityName }}</h4>
<ng-content></ng-content>
</div>
为了使其工作,A组件中定义的form
成员应该是public,最好是readonly
.
在我的 Angular 6 应用程序中,我需要将一个组件作为其 ng-template 传递给另一个组件。
原因是我有一个 Component A 我需要复制很多次,但每次它都必须包含不同的组件(让我们称它们为 组件 B 和 组件 C) 具有相同的输入。
组件 A 模板:
<div class="row-detail-panel">
<h4 class="row-detail-panel-title">{{ newEntity ? 'Add new' : 'Edit this'}} {{ entityName }}</h4>
<!--THIS IS THE COMPONENT I WANT TO INJECT-->
<app-component-b
[inline]="true"
[form]="form"
></app-component-b>
<!--END-->
<!--some more html code here-->
</div>
然后我创建一个 Component A 实例使用:
<app-component-a
[entity]="row"
[entityName]="entityName"
></app-component-a>
所以我想到了使用ng-template
,于是将Component A模板改成如下:
<div class="row-detail-panel">
<h4 class="row-detail-panel-title">{{ newEntity ? 'Add new' : 'Edit this'}} {{ entityName }}</h4>
<ng-template></ng-template>
<!--some more html code here-->
</div>
并创建一个 Component A 实例使用:
<app-component-a
[entity]="row"
[entityName]="entityName"
>
<app-component-b
[inline]="true"
[form]="form" <!--PROBLEM: "form" does not exist here-->
></app-component-b>
</app-component-a>
所以我可以轻松地注入 Component C 而不是 Component B 作为 Component A' s ng-模板:
<app-component-a
[entity]="row"
[entityName]="entityName"
>
<app-component-c
[inline]="true"
[form]="form" <!--PROBLEM: "form" does not exist here-->
></app-component-c>
</app-component-a>
问题:
我需要注入到组件B或组件C的变量form
只存在于中]Component A and not in Component A's parent(出于某些原因,我无法将其向上移动一级)。
我该如何解决这个问题?
你能做的是:
当您调用组件 A 时,您将一个 ng-template 传递给它,如下所示:
<app-component-a>
<ng-template *ngIf=”condition; else elseBlock”>
<app-component-b></app-component-b>
</ng-template>
<ng-template #elseBlock>
<app-component-c></app-component-c>
</ng-template>
</app-component-a>
现在在您的应用程序组件中-a.ts您这样做:
@ContentChild(TemplateRef) template: TemplateRef;
所以基本上模板会根据您的条件获取组件 b 或 c。
然后在组件 A 模板中,您这样做:
<ng-container [ngTemplateOutlet]="template"></ng-container>
所以现在你的 ng-container 将根据你的情况获得组件 B 或 C。
就你的表单而言,恐怕我唯一能想到的就是创建一个服务并在组件A中提供它,将其注入A,B和C并在其中共享表单服务。
但是如果您按照我上面显示的方式包含组件 B 和 C,Angular 将自行处理 B 和 C 组件的创建和销毁。
否则当你的ng-template条件改变时,你的组件B不会在实例化组件C时销毁。
编辑:
我能想到的另一件事是,如果您不在 A 实例化后立即调用组件 B 或 C,您也可以在 A 的 A 的父级 oninit 上发出 (@Output) 表单。这样当调用 B 或 C 时,A 的父级将有权访问表单并将其传递给 B 或 C。
你试过吗:
<app-component-a #compA
[entity]="row"
[entityName]="entityName">
<app-component-b
[inline]="true"
[form]="compA.form"
></app-component-b>
</app-component-a>
// component-a.html
<div class="row-detail-panel">
<h4 class="row-detail-panel-title">{{ newEntity ? 'Add new' : 'Edit this'}} {{ entityName }}</h4>
<ng-content></ng-content>
</div>
为了使其工作,A组件中定义的form
成员应该是public,最好是readonly
.