javascript - projeto - w3schools angular directive




Angular2: renderiza um componente sem sua marca de quebra automática (2)

Estou lutando para encontrar uma maneira de fazer isso. Em um componente pai, o modelo descreve uma table e seu elemento thead , mas delega a renderização do tbody para outro componente, como este:

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

Cada componente myResult renderiza sua própria tag tr , basicamente assim:

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

O motivo de eu não colocar isso diretamente no componente pai (evitando a necessidade de um componente myResult) é que o componente myResult é realmente mais complicado do que o mostrado aqui, portanto, quero colocar seu comportamento em um componente e arquivo separados.

O DOM resultante parece ruim. Eu acredito que isso ocorre porque é inválido, pois tbody pode conter apenas elementos tr (consulte MDN) , mas meu DOM gerado (simplificado) é:

<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 alguma maneira de obtermos a mesma coisa renderizada, mas sem a tag wrapping <my-result> e ainda usando um componente como o único responsável por renderizar uma linha da tabela?

Eu olhei para o ng-content , DynamicComponentLoader , o ViewContainerRef , mas eles não parecem fornecer uma solução para isso, tanto quanto eu posso ver.


Use esta diretiva em seu elemento

@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);
   }
}

Exemplo de uso:

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

e no html pai você chama o elemento do cartão como de costume, por exemplo:

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

A saída será:

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

Você pode usar seletores de atributos

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

e depois usá-lo como

<td myTd></td>




angular