web-dev-qa-db-ja.com

Angularコンポーネントを別のコンポーネントのng-templateとして渡す

私のAngular 6アプリでは、コンポーネントを ng-template として別のコンポーネントに渡す必要があります。

理由は、何度も複製する必要があるComponent Aがありますが、そのたびに異なるコンポーネントを含める必要があるためです(それらをComponent 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 Bの代わりにComponent CComponent Aのng-templateとして簡単に注入できます。

<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は、コンポーネントAおよびnotinComponent Aのparent(何らかの理由で1レベル上に移動できません)。

この問題を解決するにはどうすればよいですか?

9
Francesco Borzi

あなたは単純にやってみましたか:

<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である必要があります。

5
Jota.Toledo

あなたができることはこれです:

コンポーネントAを呼び出すとき、ngテンプレートを次のように渡します。

<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コンテナは、条件に基づいてコンポーネントBまたはCを取得します。

フォームに関する限り、考えられる唯一のことは、サービスを作成してコンポーネントAで提供し、A、B、Cに注入して、そのサービスでフォームを共有することだけだと思います。

ただし、上記の方法でコンポーネントBとCを含めると、Angularは、BおよびCコンポーネントの作成と破棄を単独で処理します。

そうしないと、ng-templateの条件が変更されても、コンポーネントCがインスタンス化されたときにコンポーネントBは破棄されません。

編集:

私が考えることができるもう1つのことは、Aがインスタンス化された直後にコンポーネントBまたはCを呼び出さない場合、AからAの親oninitに(@Output)フォームを発行することもできるということです。この方法はBまたはCが呼び出されると、Aの親はフォームにアクセスでき、BまたはCに渡すことができます。

5
Vinod Bhavnani