Criando um componente Angular com conteúdo dinâmico utilizando ng-content

ng-content é um ótimo recurso para criar componentes Angular que aceitem conteúdo dinâmico em determinados locais da template.

Tiago Boeing
Senior Sistemas
Published in
4 min readJul 22, 2019

--

Frameworks/libs para JavaScript como Angular, ReactJS, Vue.js e outros oferecem inúmeras praticidades durante o processo de desenvolvimento frontend, não há como negar.

Todo desenvolvedor deve ter em mente boas práticas e o reaproveitamento de código sempre que possível, uma técnica (de muitas) para concretizar este conceito é conhecida como arquitetura ou desenvolvimento voltado a uma estrutura master-detail.

Trazendo para o contexto do framework deste post (Angular 😉), master-detail ajuda a…

“Manter todos os recursos em um componente à medida que o aplicativo cresce não será passível de manutenção. Você vai querer dividir grandes componentes em subcomponentes menores, cada um focado em uma tarefa ou fluxo de trabalho específico. — Documentação do Angular

Partindo do princípio que você já conhece o decorator @Input() (uma forma de injeção de dados em um componente), vamos falar do ng-content. (Input fica para uma outra postagem, caso ainda não conheça 😎)

ng-content

Utilizado para projeção de conteúdo, permite passar qualquer conteúdo entre as tags de abertura e fechamento do componente criado. Não entendeu? Vamos lá…

Digamos que você possua um componente item (item.component.ts) com a seguinte declaração:

Template neste caso substitui o arquivo .html que você teria… Apenas para ficar mais fácil de exemplificar.

Ok. Vamos imaginar que você deseja adicionar um checkbox, radio button ou qualquer outro elemento que necessite de uma lógica acoplada ao componente pai (master). Leve em consideração que item é o componente filho (detail).

É comum seguir com a ideia de adicionar o checkbox dentro do item (detail), já que visualmente ele não se encontraria no pai (master). Dependendo da ocasião utilizar emissão de eventos ou @ContentChild() tornaria a situação ainda complexa, muitas vezes sem necessidade.

É possível adicionar o checkbox via ng-content e manipular toda sua lógica no componente pai, ele estará em um laço de repetição (*ngFor).

Utilizando ng-content

A posição em que encontra-se <ng-content></ng-content> será onde o elemento que você passar vai aparecer. Com elemento quero dizer, qualquer conteúdo HTML.

Adicionando checkbox

Apenas abstraindo como é possível passar qualquer conteúdo para o local em que você definiu o <ng-content> no item. Passando um input do tipo checkbox…

<item>
<input type="checkbox"/>
</item>

Pratique no Stackblitz

app.component.ts

O app.component.ts cria uma variável chamada items que é um array de objetos, neste exemplo contém title, description e checked (identifica se o checkbox está marcado ou não).

Temos um método toggle() com um forEach, ele basicamente percorre o array de objetos trocando o valor da propriedade checked, quer dizer que, se checked = true passará a ser false e vice-versa.

É no app.component que realizamos a iteração dos objetos com *ngFor e passamos o objeto para o decorator @Input() presente no item.

<item *ngFor="let item of items" [item]="item">
<input type="checkbox" [(ngModel)]="item.checked"/>
</item>

De forma rápida, ngModel realiza o bind do valor item.checked com o checkbox, isto é, muda a maneira com que ele aparece para o usuário, marcado ou não.

A maneira com que ngModel aparece, entre colchetes e parênteses [(ngModel)] é chamada de two way data binding no Angular.

item.component.ts

Perceba que item.component.ts recebe do app.component.ts um array de objetos via @Input() e instancia uma variável item.

Você não só pode como deve criar uma interface para identificar o tipo que está trabalhando.

Interface para item

Se preferir criar uma interface para Item, ficaria assim:

Chame a interface com o nome que quiser.

Para utilizar a interface é simples, basta na declaração das variáveis trocar any para Item (e importar a interface).

items: Item[];

Múltiplos ng-content

Quando for utilizar mais de um ng-content em um componente você precisará informar uma propriedade select.

Veja que utilizamos <ng-content select=”[title]”></ng-content> para indicar qual será o seletor a ser utilizado quando os dados forem injetados.

Para injetar o conteúdo em cada um dos ng-content:

Utilizamos title diretiva para informar que o conteúdo Título é referente ao ng-content com select=”[title]” e Description ao ng-content com select description.

Os exemplos do artigo encontram-se no Stackblitz.

Referências

Conheça o blog Dev Senior: fórum, guias para integrações, documentações de APIs e atualizações sobre os produtos da Senior. — https://dev.senior.com.br/

Tiago Boeing

Dev frontend na equipe de Arquitetura, time de Tecnologia, estudante de Ciência da Computação, nos tempos vagos jornalista e joga CS GO.

--

--

Tiago Boeing
Senior Sistemas

🇧🇷 Software engineering specialist | AWS Community Builder | ⌨ Works at Grupo Casas Bahia | @tiagoboeing