*ngFor para objetos: como obter chaves e valores sem perda de desempenho

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Problema que todo desenvolvedor Angular conhece

\n\n

Você 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.

\n\n

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

Neste 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\n

Por que *ngFor não funciona com objetos "de fábrica"?

\n\n

A diretiva *ngFor no Angular é projetada para estruturas iteráveis (Iterable). Um array é uma estrutura iterável. Um objeto não é. Quando você escreve:

\n\n
<div *ngFor="let item of myObject">{{ item }}</div>
\n\n

O Angular exibirá um erro: "Cannot find a differ supporting object '...'". O Angular simplesmente não sabe como iterar sobre um objeto.

\n\n

Mas 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' }).

\n\n

A maneira mais simples: Object.keys() e Object.entries()

\n\n

A resposta mais popular e óbvia no Stack Overflow é converter o objeto em um array diretamente no template ou no componente.

\n\n

Opçã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\n

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

\n\n
// 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\n

Isso 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\n

Opçã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\n

Ou com desestruturação (mais legível):

\n\n
<div *ngFor="let [key, value] of entries">\n  Chave: {{ key }}, Valor: {{ value }}\n</div>
\n\n

Vantagens: 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.

\n\n

Desempenho: por que isso é importante?

\n\n

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

\n\n

Portanto, para projetos sérios, é necessário usar otimização.

Blogs

Book Recommendations