chave de access e valor do object usando * ngFor

Bit confuso sobre como obter Key and Value of object em angular2 enquanto usng * ngFor para iteração sobre object. Eu sei em 1.x angular há syntax como

 ng-repeat="(key, value) in demo" 

mas em angular2 eu não sei, eu me cansei da mesma, mas não tive sucesso. Eu tentei o código abaixo, mas não corri por favor me diga onde eu estou fazendo errado.

 
  • {{key}}
demo = { 'key1': [{'key11':'value11'}, {'key12':'value12'}], 'key2': [{'key21':'value21'}, {'key22':'value22'}], }

aqui é plnkr onde eu tentei o mesmo: http://plnkr.co/edit/mIj619FncOpfdwrR0KeG?p=preview

Eu quero obter key1 e key2 dinamicamente usando * ngFor. Como conseguir isso? Eu procurei muito achei idéia de usar pipe, mas como usar eu não sei. Existe algum tubo embutido para fazer o mesmo em angular2?

Tenha o Object.keys acessível no template e use-o em *ngFor .

 @Component({ selector: 'app-myview', template: `
{{key + ' : ' + items[key]}}
` }) export class MyComponent { objectKeys = Object.keys; items = { keyOne: 'value 1', keyTwo: 'value 2', keyThree: 'value 3' }; constructor(){} }

Você pode criar um pipe personalizado para retornar a lista de chaves para cada elemento. Algo parecido:

 import { PipeTransform, Pipe } from '@angular/core'; @Pipe({name: 'keys'}) export class KeysPipe implements PipeTransform { transform(value, args:string[]) : any { let keys = []; for (let key in value) { keys.push(key); } return keys; } } 

e usá-lo assim:

  {{key}}: {{c[key]}}  

Editar

Você também pode retornar uma input contendo chave e valor:

 @Pipe({name: 'keys'}) export class KeysPipe implements PipeTransform { transform(value, args:string[]) : any { let keys = []; for (let key in value) { keys.push({key: key, value: value[key]}); } return keys; } } 

e usá-lo assim:

  Key: {{entry.key}}, value: {{entry.value}}  

Elaboração da resposta de @ Thierry com exemplo.

Não existe um pipe ou método embutido para obter key and value do loop * ngFor. então temos que criar um pipe personalizado para o mesmo. como thierry disse aqui é a resposta com o código.

** A class pipe implementa o método de transformação da interface PipeTransform, que recebe um valor de input e uma matriz opcional de cadeias de parâmetros e retorna o valor transformado.

** O método transform é essencial para um pipe. A interface PipeTransform define esse método e orienta o ferramental e o compilador. É opcional; Angular procura e executa o método de transformação independentemente. para mais informações sobre o tubo consulte aqui

 import {Component, Pipe, PipeTransform} from 'angular2/core'; import {CORE_DIRECTIVES, NgClass, FORM_DIRECTIVES, Control, ControlGroup, FormBuilder, Validators} from 'angular2/common'; @Component({ selector: 'my-app', templateUrl: 'mytemplate.html', directives: [CORE_DIRECTIVES, FORM_DIRECTIVES], pipes: [KeysPipe] }) export class AppComponent { demo = { 'key1': 'ANGULAR 2', 'key2': 'Pardeep', 'key3': 'Jain', } } @Pipe({name: 'keys'}) export class KeysPipe implements PipeTransform { transform(value, args:string[]) : any { let keys = []; for (let key in value) { keys.push({key: key, value: value[key]}); } return keys; } } 

e parte HTML é:

 
  • Key: {{key.key}}, value: {{key.value}}

Trabalhando Plnkr http://plnkr.co/edit/50LlK0k6OnMnkc2kNHM2?p=preview

atualizar para RC

como sugerido por user6123723 (obrigado) no comentário aqui é atualização.

 
  • Key: {{key.key}}, value: {{key.value}}

@Marton teve uma objeção importante à resposta aceita, alegando que o pipe cria uma nova coleção em cada detecção de mudança. Em vez disso, criaria um HtmlService que fornece um intervalo de funções de utilitário que a exibição pode usar da seguinte maneira:

 @Component({ selector: 'app-myview', template: `
{{i + ' : ' + items[i]}}
` }) export class MyComponent { items = {keyOne: 'value 1', keyTwo: 'value 2', keyThree: 'value 3'}; constructor(private html: HtmlService){} } @Injectable() export class HtmlService { keys(object: {}) { return Object.keys(object); } // ... other useful methods not available inside html, like isObject(), isArray(), findInArray(), and others... }

Outra abordagem é criar a diretiva NgForIn que será usada como:

 
{{ key }}: {{ obj[key] }}

Exemplo de Plunker

ngforin.directive.ts

 @Directive({ selector: '[ngFor][ngForIn]' }) export class NgForIn extends NgForOf implements OnChanges { @Input() ngForIn: any; ngOnChanges(changes: NgForInChanges): void { if (changes.ngForIn) { this.ngForOf = Object.keys(this.ngForIn) as Array; const change = changes.ngForIn; const currentValue = Object.keys(change.currentValue); const previousValue = change.previousValue ? Object.keys(change.previousValue) : undefined; changes.ngForOf = new SimpleChange(previousValue, currentValue, change.firstChange); super.ngOnChanges(changes); } } } 

Atualizar

No 6.1.0-beta.1 KeyValuePipe foi introduzido https://github.com/angular/angular/pull/24319

 
{{ item.key }} - {{ item.value }}

Exemplo de Plunker

Se você já estiver usando o Lodash, você pode fazer essa abordagem simples que inclui tanto a chave quanto o valor:

 
  • {{key}}: {{demo[key]}}

No arquivo de typescript, inclua:

 import * as _ from 'lodash'; 

e no componente exportado, inclua:

 _: any = _; 

Como na versão mais recente do Angular (v6.1.0), o Angular Team adicionou novo pipe keyvalue para o mesmo nome do pipe de valor-chave para ajudá-lo a percorrer objects, mapas e matrizes, no módulo common do pacote angular. Por exemplo –

 
Key: {{item.key}} and Value: {{item.value}}

Exemplo de trabalho bifurcado

confira aqui para mais informações úteis –

Se você estiver usando Angular v5 ou abaixo, ou se quiser usar pipe, siga esta resposta

  • chave de access e valor do object usando ngfor

Obrigado pelo cano, mas eu tive que fazer algumas mudanças antes que eu pudesse usá-lo em angular 2 RC5. Alterou a linha de importação de tubos e também adicionou um tipo de qualquer à boot da matriz de chaves.

  import {Pipe, PipeTransform} from '@angular/core'; @Pipe({name: 'keys'}) export class KeysPipe implements PipeTransform { transform(value) { let keys:any = []; for (let key in value) { keys.push( {key: key, value: value[key]} ); } return keys; } } 

Nenhuma das respostas aqui funcionou para mim fora da checkbox, aqui está o que funcionou para mim:

Crie pipes/keys.ts com o conteúdo:

 import { Pipe, PipeTransform } from '@angular/core'; @Pipe({name: 'keys'}) export class KeysPipe implements PipeTransform { transform(value:any, args:string[]): any { let keys:any[] = []; for (let key in value) { keys.push({key: key, value: value[key]}); } return keys; } } 

Adicione ao app.module.ts (seu módulo principal):

 import { KeysPipe } from './pipes/keys'; 

e, em seguida, adicione ao seu array de declarações de módulo algo como isto:

 @NgModule({ declarations: [ KeysPipe ] }) export class AppModule {} 

Em seguida, no seu modelo de visualização, você pode usar algo assim:

  

Aqui está uma boa referência que encontrei se você quiser ler mais.

Há uma biblioteca muito legal que faz isso entre outras coisas legais. É chamado ngx-pipes .

Por exemplo, o pipe keys retorna chaves para um object e valores pipe retorna valores para um object:

tubo de chaves

 
{{key}}

tubo de valores

 
{{value}}

Não há necessidade de criar seu próprio cachimbo personalizado 🙂

Aqui está a solução simples

Você pode usar iteradores datilografados para isso

 import {Component} from 'angular2/core'; declare var Symbol; @Component({ selector: 'my-app', template:`

Iterating an Object using Typescript Symbol


Object is :

{{obj | json}}

============================
Iterated object params are:
{{o}}
` }) export class AppComponent { public obj: any = { "type1": ["A1", "A2", "A3","A4"], "type2": ["B1"], "type3": ["C1"], "type4": ["D1","D2"] }; constructor() { this.obj[Symbol.iterator] = () => { let i =0; return { next: () => { i++; return { done: i > 4?true:false, value: this.obj['type'+i] } } } }; } }

http://plnkr.co/edit/GpmX8g?p=info

De Angular 6.1 você pode usar o tubo de valor de chave:

 
Key: {{item.key}} and Value: {{item.value}}

Mas tem o inconveniente que classifica a lista resultante pelo valor da chave. Se você precisa de algo neutro:

 @Pipe({ name: 'keyValueUnsorted' }) export class KeyValuePipe implements PipeTransform { transform(value: any, args: string[]): any { let keys = []; for (let key in value) { keys.push({ key: key, value: value[key]}); } return keys; } } 

Eu acho que Object.keys é a melhor solução para este problema. Para qualquer um que se deparar com esta resposta e está tentando descobrir porque Object.keys está dando a eles [‘0’, ‘1’] em vez de [‘key1’, ‘key2’], um conto preventivo – cuidado com a diferença entre ” de “e” em “:

Eu já estava usando Object.keys, algo semelhante a isto:

 interface demo { key: string; value: string; } createDemo(mydemo: any): Array { const tempdemo: Array = []; // Caution: use "of" and not "in" for (const key of Object.keys(mydemo)) { tempdemo.push( { key: key, value: mydemo[key]} ); } return tempdemo; } 

No entanto, em vez de

 for (const key OF Object.keys(mydemo)) { 

Eu inadvertidamente escrevi

 for (const key IN Object.keys(mydemo)) { 

que “funcionou” perfeitamente bem sem qualquer erro e retornou

 [{key: '0', value: undefined}, {key: '1', value: undefined}] 

Isso me custou cerca de 2 horas googling e xingando ..

(bate na testa)

Você tem que fazer assim por enquanto, eu não sei muito eficiente como você não quer converter o object que você recebe do firebase.

  this.af.database.list('/data/' + this.base64Email).subscribe(years => { years.forEach(year => { var localYears = []; Object.keys(year).forEach(month => { localYears.push(year[month]) }); year.months = localYears; }) this.years = years; }); 

alterar o tipo de demonstração para matriz ou iterar sobre o seu object e empurrar para outra matriz

 public details =[]; Object.keys(demo).forEach(key => { this.details.push({"key":key,"value":demo[key]); }); 

e do html:

 

{{obj.key}}

{{obj.value}}