Problema que todo desenvolvedor Angular conhece
\n\nVocê já tentou exibir no template Angular o conteúdo de um objeto JavaScript comum usando *ngFor e de repente percebeu: "Como faço para obter a chave e o valor?" Afinal, *ngFor por padrão funciona apenas com arrays. E um objeto não é um array.
Esta pergunta é uma das mais populares no Stack Overflow (milhares de visualizações e dezenas de respostas). Desenvolvedores não buscam apenas uma solução, mas a solução correta — aquela que não prejudique o desempenho da aplicação, especialmente quando o objeto é grande ou atualizado com frequência.
\n\nNeste artigo, não vamos apenas dar a resposta. Vamos analisar todas as abordagens principais, das simples às avançadas, e mostrar como escrever código que seja rápido e estável. Vamos lá!
\n\nPor que *ngFor não funciona com objetos "de fábrica"?
\n\nA diretiva *ngFor no Angular é projetada para estruturas iteráveis (Iterable). Um array é uma estrutura iterável. Um objeto não é. Quando você escreve:
<div *ngFor="let item of myObject">{{ item }}</div>\n\nO Angular exibirá um erro: "Cannot find a differ supporting object '...'". O Angular simplesmente não sabe como iterar sobre um objeto.
\n\nMas na prática, muitas vezes precisamos exibir dados de um objeto: configurações, dicionários, respostas de API, onde as chaves têm significado (por exemplo, { name: 'Ana', age: 25, city: 'Moscou' }).
A maneira mais simples: Object.keys() e Object.entries()
\n\nA resposta mais popular e óbvia no Stack Overflow é converter o objeto em um array diretamente no template ou no componente.
\n\nOpção 1: Object.keys() — obtendo apenas as chaves
\n\n// No componente (TypeScript)\nexport class MyComponent {\n myObject = { name: 'Ana', age: 25, city: 'Moscou' };\n}\n\n<!-- No template -->\n<div *ngFor="let key of objectKeys(myObject)">\n Chave: {{ key }}, Valor: {{ myObject[key] }}\n</div>\n\nMas há um detalhe: objectKeys precisa estar disponível no template. Ou a tornamos um método do componente, ou a colocamos em uma propriedade separada:
// Componente\nexport class MyComponent {\n myObject = { name: 'Ana', age: 25, city: 'Moscou' };\n objectKeys = Object.keys; // apenas uma referência à função nativa\n}\n\nIsso funciona, mas chama a função a cada verificação de mudanças (change detection). Se o objeto for grande — isso impacta o desempenho.
\n\nOpção 2: Object.entries() — chaves e valores de uma vez
\n\n// Componente\nexport class MyComponent {\n myObject = { name: 'Ana', age: 25, city: 'Moscou' };\n get entries() {\n return Object.entries(this.myObject);\n }\n}\n\n<!-- Template -->\n<div *ngFor="let entry of entries">\n Chave: {{ entry[0] }}, Valor: {{ entry[1] }}\n</div>\n\nOu com desestruturação (mais legível):
\n\n<div *ngFor="let [key, value] of entries">\n Chave: {{ key }}, Valor: {{ value }}\n</div>\n\nVantagens: simples, claro, intuitivo.
\nDesvantagens: o método entries será chamado a cada ciclo de detecção de mudanças. Para objetos estáticos — ok, para dinâmicos — pode se tornar um problema.
Desempenho: por que isso é importante?
\n\nImagine que seu objeto contenha 10.000 registros. Ou que ele seja atualizado a cada 100 ms (por exemplo, dados do servidor em tempo real). Cada chamada de Object.entries() cria um novo array. O Angular, a cada ciclo de detecção de mudanças, verá um array "novo" e redesenhará toda a lista. Isso causa travamentos na interface, perda de foco em inputs e lentidão.
Portanto, para projetos sérios, é necessário usar otimização.