web-dev-qa-db-fra.com

Angular2: rendre un composant sans sa balise wrapping

Je me bats pour trouver un moyen de le faire. Dans un composant parent, le modèle décrit une variable table et son élément thead, mais les délégués restituent la variable tbody à un autre composant, comme suit:

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Time</th>
    </tr>
  </thead>
  <tbody *ngFor="let entry of getEntries()">
    <my-result [entry]="entry"></my-result>
  </tbody>
</table>

Chaque composant myResult génère sa propre balise tr, comme ci-dessous:

<tr>
  <td>{{ entry.name }}</td>
  <td>{{ entry.time }}</td>
</tr>

La raison pour laquelle je ne mets pas cela directement dans le composant parent (pour éviter le recours à un composant myResult) est que le composant myResult est en réalité plus compliqué que ce qui est montré ici. Je souhaite donc placer son comportement dans un composant et un fichier distincts.

Le DOM résultant semble mauvais. Je pense que c'est parce qu'il est invalide, car tbody ne peut contenir que tr éléments (voir MDN) , mais mon DOM généré (simplifié) est:

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Time</th>
    </tr>
  </thead>
  <tbody>
    <my-result>
      <tr>
        <td>Bob</td>
        <td>128</td>
      </tr>
    </my-result>
  </tbody>
  <tbody>
    <my-result>
      <tr>
        <td>Lisa</td>
        <td>333</td>
      </tr>
    </my-result>
  </tbody>
</table>

Existe-t-il un moyen d'obtenir le même rendu, mais sans la balise wrapper <my-result>, tout en utilisant un composant pour être seul responsable du rendu d'une ligne de tableau?

J'ai regardé ng-content, DynamicComponentLoader, le ViewContainerRef, mais ils ne semblent pas apporter de solution à cela à ma connaissance.

44
Greg

Vous pouvez utiliser des sélecteurs d'attributs 

@Component({
  selector: '[myTd]'
  ...
})

et ensuite l'utiliser comme

<td myTd></td>
43
Günter Zöchbauer

Vous avez besoin de "ViewContainerRef" et dans le composant my-result, procédez comme suit:

html:

<ng-template #template>
    <tr>
       <td>Lisa</td>
       <td>333</td>
    </tr>
 </ng-template>

ts:

@ViewChild('template') template;


  constructor(
    private viewContainerRef: ViewContainerRef
  ) { }

  ngOnInit() {
    this.viewContainerRef.createEmbeddedView(this.template);
  }
2
Slim

Utilisez cette directive sur votre élément

@Directive({
   selector: '[remove-wrapper]'
})
export class RemoveWrapperDirective {
   constructor(private el: ElementRef) {
       const parentElement = el.nativeElement.parentElement;
       const element = el.nativeElement;
       parentElement.removeChild(element);
       parentElement.parentNode.insertBefore(element, parentElement.nextSibling);
       parentElement.parentNode.removeChild(parentElement);
   }
}

Exemple d'utilisation:

<div class="card" remove-wrapper>
   This is my card component
</div>

et dans le code HTML parent, vous appelez l’élément de carte comme d’habitude, par exemple:

<div class="cards-container">
   <card></card>
</div>

La sortie sera:

<div class="cards-container">
   <div class="card" remove-wrapper>
      This is my card component
   </div>
</div>
2
Shlomi Aharoni

Aucune des réponses proposées ne fonctionne ou ne sont complètes .. La bonne réponse est décrite ici avec un échantillon de plunker Retirer la balise du composant hôte de html dans l’angle 4

0
sancelot