Tudo o que você precisa saber sobre ng-template, ng-content, ng-container e *ngTemplateOutlet em Angular
Tudo o que você precisa saber sobre ng-template, ng-content, ng-container e *ngTemplateOutlet em Angular
Jul 1, 2021
admin
Foi um daqueles dias em que eu estava ocupado trabalhando em novas funcionalidades para o meu projeto de escritório. De repente, algo chamou minha atenção:
Apesar de inspecionar o DOM eu vi o ngcontent sendo aplicado em elementos pela Angular. Hmm… se eles contêm os elementos no DOM final, então qual é o uso de <ng-container>? Naquela época fiquei confuso entre <ng-container> e <ng-content>.
Na busca para saber as respostas às minhas perguntas descobri o conceito de <ng-template>. Para minha surpresa, havia também *ngTemplateOutlet. Comecei minha jornada buscando clareza sobre dois conceitos, mas agora eu tinha quatro deles, soando quase o mesmo!
Você já esteve nessa situação? Se sim, então você está no lugar certo. Então sem mais delongas vamos levá-los um a um.
><ng-template>
Como o nome sugere o <ng-template> é um elemento template que Angular usa com diretivas estruturais (*ngIf, *ngFor, e diretivas personalizadas).
Estes elementos template só funcionam na presença de diretivas estruturais. Angular envolve o elemento hospedeiro (ao qual a diretriz é aplicada) dentro de <ng-template> e consome o <ng-template> no DOM acabado, substituindo-o por comentários de diagnóstico.
Considerar um exemplo simples de *ngIf:
Mostrada acima é a interpretação angular de *ngIf. Angular coloca o elemento hospedeiro ao qual a diretiva é aplicada dentro de <ng-template> e mantém o hospedeiro como ele é. O DOM final é semelhante ao que vimos no início deste artigo:
Usagem:
Vimos como Angular usa <ng-template> mas e se quisermos usá-lo? Como estes elementos funcionam apenas com uma directiva estrutural, podemos escrever como:
Aqui home é uma boolean propriedade do componente definida para true valor. A saída do código acima em DOM:
Nada foi renderizada! 🙁
>
Mas porque não podemos ver a nossa mensagem mesmo depois de usar <ng-template> correctamente com uma directiva estrutural?
Este foi o resultado esperado. Como já discutimos, Angular substitui o <ng-template> por comentários de diagnóstico. Sem dúvida o código acima não geraria nenhum erro, pois Angular está perfeitamente bem com o seu caso de uso. Você nunca saberia o que exatamente aconteceu nos bastidores.
Vamos comparar os dois DOMs acima que foram renderizados pela Angular:
Se você observar de perto, há uma tag de comentário extra no DOM final do Exemplo 2. O código que Angular interpretou foi:
Angular embrulhou seu host <ng-template> dentro de outro <ng-template> e converteu não só o externo <ng-template> em comentários de diagnóstico, mas também o interno! É por isso que você não pôde ver nenhuma de suas mensagens.
Para se livrar disso, há duas maneiras de obter o resultado desejado:
Método 1:
Neste método, você está fornecendo o Angular com o formato dessugared, que não precisa de mais processamento. Desta vez a Angular apenas converteria <ng-template> para comentários mas deixaria o conteúdo dentro dela intocado (eles não estão mais dentro de nenhum <ng-template> como estavam no caso anterior). Assim, ele renderizará o conteúdo corretamente.
Para saber mais sobre como usar este formato com outras diretrizes estruturais, consulte este artigo.
Método 2:
Este é um formato bastante invisível e raramente é usado (usando dois irmãos <ng-template>). Aqui estamos dando uma referência ao modelo *ngIf em seu then para dizer-lhe qual modelo deve ser usado se a condição for verdadeira.
Usar múltiplos <ng-template> como este não é aconselhado (você poderia usar <ng-container> em seu lugar), pois não é para isto que eles são destinados. Eles são usados como um recipiente para templates que podem ser reutilizados em vários lugares. Cobriremos mais sobre isto numa secção posterior deste artigo.
>
<ng-container>
>
Deixe que alguma vez tenha escrito ou visto um código semelhante a este:
A razão pela qual muitos de nós escrevemos este código é a incapacidade de usar múltiplas directivas estruturais num único elemento hospedeiro em Angular. Agora este código funciona bem mas introduz vários vazios extra <div> no DOM se item.id é um valor falso que pode não ser necessário.
Um pode não estar preocupado com um exemplo simples como este, mas para uma aplicação enorme que tem um DOM complexo (para exibir dezenas de milhares de dados) isto pode tornar-se problemático pois os elementos podem ter ouvintes ligados a eles que ainda estarão lá no DOM ouvindo eventos.
O que é ainda pior é o nível de aninhamento que você tem que fazer para aplicar o seu estilo (CSS)!
Não se preocupe, nós temos <ng-container> para o resgate!
O Angular <ng-container> é um elemento de agrupamento que não interfere com estilos ou layout porque o Angular não o coloca no DOM.
Então se escrevermos o nosso Exemplo 1 com <ng-container>: