web-dev-qa-db-fra.com

Angular passer un composant comme ng-template d'un autre composant

Dans mon Angular 6, je dois passer un composant à un autre composant en tant que ng-template .

La raison en est que j'ai un composant A que je dois répliquer plusieurs fois, mais à chaque fois il doit inclure différents composants (appelons-les Composant B et Composant C ) qui ont les mêmes entrées .

Modèle du composant 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>

Et je crée une instance du composant A en utilisant:

<app-component-a
  [entity]="row"
  [entityName]="entityName"
></app-component-a>

J'ai donc pensé à utiliser ng-template, modifiant ainsi le modèle du composant A comme suit:

<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>

Et en créant une instance A du composant A en utilisant:

<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>

Je peux donc facilement injecter Composant C au lieu de Composant B comme ng-template du composant A :

<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>

Problème [~ # ~] [~ # ~] :

la variable form que je dois injecter dans Composant B ou Composant C n'existe qu'à l'intérieur du composant A et pas dans Parent du composant A (pour certaines raisons, je ne peux pas le déplacer d'un niveau vers le haut).

Comment puis-je résoudre ce problème?

9
Francesco Borzi

Avez-vous essayé en faisant simplement:

<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>

Pour que cela fonctionne, le membre form défini dans le composant A doit être public, et de préférence readonly.

5
Jota.Toledo

Voici ce que vous pouvez faire:

Lorsque vous appelez le composant A, vous passez un modèle ng à celui-ci comme suit:

<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> 

Maintenant, dans votre app-component-a.ts, vous procédez comme suit:

@ContentChild(TemplateRef) template: TemplateRef;

Donc, fondamentalement, le modèle obtiendra le composant b ou c en fonction de votre état.

Et puis dans le modèle de composant A, vous procédez comme suit:

<ng-container [ngTemplateOutlet]="template"></ng-container>

Alors maintenant, votre conteneur ng recevra le composant B ou C en fonction de votre état.

En ce qui concerne votre formulaire, je crains que la seule chose à laquelle je puisse penser est de créer un service et de le fournir dans le composant A, de l'injecter dans A, B et C et de partager le formulaire dans ce service.

Mais si vous incluez les composants B et C comme je l'ai montré ci-dessus, Angular gérera seul la création et la destruction de vos composants B et C.

Sinon, lorsque votre condition ng-template change, votre composant B ne sera pas détruit lorsque le composant C est instancié.

Modifier:

Une autre chose à laquelle je peux penser est que si vous n'appelez pas le composant B ou C dès que A est instancié, vous pouvez également émettre la forme (@Output) de A vers le parent de A sur Ainit de A. De cette façon, lorsque B ou C est appelé, le parent de A aura accès au formulaire et il pourra le transmettre à B ou C.

5
Vinod Bhavnani