在Angular 6应用中,我需要将一个组件作为其ng-template传递给另一个组件。
原因是我有一个 A组件,需要多次复制,但是每次必须包含不同的组件(我们称它们为 B组件, 组件C ),其具有相同的输入。
组件A 模板:
import { Component, OnInit } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import * as Leaflet from 'leaflet';
import { VehicleService } from '../vehicle.services';
import { VehicleDetail } from '../models/vehicle-detail';
.........
vehicleDetail: VehicleDetail;
private unsubscribe$ = new Subject();
.........
getVehicleDetail(): Observable<VehicleDetail> {
const details = this.vehicleService
.getVehicleDetail(this.vehicleService.vehicleId);
details.takeUntil(this.unsubscribe$).subscribe(data => {
this.vehicleDetail = data;
});
return details;
}
updateInfo(item): void {
this.unsubscribe$.next();
this.unsubscribe$.complete();
this.vehicleService.vehicleId = item;
console.log(this.vehicleService.vehicleId);
this.getVehicleDetail().takeUntil(this.unsubscribe$).subscribe(() => {
if (this.vehicleDetail.position) {
this.setMap();
return;
}
this.map.flyTo(new Leaflet.LatLng(50.7089, 10.9746), 4, {
animate: true,
duration: 4
});
});
}
然后我使用以下方法创建一个 Component 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>
因此,我考虑使用<app-component-a
[entity]="row"
[entityName]="entityName"
></app-component-a>
,因此按如下所示更改 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>
因此,我可以轻松地将组件C 而不是组件B 注入为组件A 的ng-template:
<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>
问题:
我需要注入到组件B 或组件C 的变量<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>
仅存在于组件A 和组件A的父级中>不是(出于某些原因,我无法将其向上移动一级)。
我该如何解决这个问题?
答案 0 :(得分:4)
您是否只是通过以下方式尝试过:
<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
成员应该是公共的,最好是readonly
。
答案 1 :(得分:1)
您可以执行以下操作:
调用组件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>
现在在您的app-component-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条件发生变化时,实例化组件C不会破坏您的组件B。
编辑:
我能想到的另一件事是,如果在实例化A时不立即调用组件B或C,则还可以从A向A的父oninit发出(@Output)形式。或C被调用,则A的父级将有权访问表格并将其传递给B或C。