Angular将一个组件作为另一个组件的ng-template传递

时间:2018-07-04 10:20:47

标签: angular typescript angular-components ng-template

在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的父级中>不是(出于某些原因,我无法将其向上移动一级)。

我该如何解决这个问题?

2 个答案:

答案 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。