supports such only objects iterables example array angular typescript object

angular - such - clave de acceso y valor del objeto usando*ngFor



ngfor only supports binding to iterables such as arrays (17)

Actualizar

En 6.1.0- beta.1 se introdujo KeyValuePipe https://github.com/angular/angular/pull/24319

<div *ngFor="let item of {''b'': 1, ''a'': 1} | keyvalue"> {{ item.key }} - {{ item.value }} </div>

Ejemplo de Plunker

Versión previa

Otro enfoque es crear la directiva NgForIn que se utilizará como:

<div *ngFor="let key in obj"> <b>{{ key }}</b>: {{ obj[key] }} </div>

Ejemplo de Plunker

ngforin.directive.ts

@Directive({ selector: ''[ngFor][ngForIn]'' }) export class NgForIn<T> extends NgForOf<T> implements OnChanges { @Input() ngForIn: any; ngOnChanges(changes: NgForInChanges): void { if (changes.ngForIn) { this.ngForOf = Object.keys(this.ngForIn) as Array<any>; 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); } } }

Estoy un poco confundido acerca de cómo obtener la key y el value de un objeto en angular2 mientras uso *ngFor para iterar sobre el objeto. Sé que en angular 1.x hay una sintaxis como

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

pero no sé cómo hacer lo mismo en angular2. He intentado algo similar, sin éxito:

<ul> <li *ngFor=''#key of demo''>{{key}}</li> </ul> demo = { ''key1'': [{''key11'':''value11''}, {''key12'':''value12''}], ''key2'': [{''key21'':''value21''}, {''key22'':''value22''}], }

Aquí hay un plnkr con mi intento: http://plnkr.co/edit/mIj619FncOpfdwrR0KeG?p=preview

¿Cómo puedo obtener key2 y key2 dinámicamente usando *ngFor ? Después de buscar mucho, encontré la idea de usar tuberías, pero no sé cómo hacerlo. ¿Hay alguna tubería incorporada para hacer lo mismo en angular2?


Índice de uso:

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

Uso:

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


@ Martin tuvo una importante objeción a la respuesta aceptada debido a que la tubería crea una nueva colección en cada detección de cambio. En su lugar, crearía un HtmlService que proporciona una gama de funciones de utilidad que la vista puede usar de la siguiente manera:

@Component({ selector: ''app-myview'', template: `<div *ngFor="let i of html.keys(items)">{{i + '' : '' + items[i]}}</div>` }) 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... }


Al igual que en la última versión de Angular (v6.1.0) , Angular Team ha agregado una nueva tubería incorporada para el mismo nombre que la tubería de valor keyvalue para ayudarlo a iterar a través de objetos, mapas y matrices, en el módulo common del paquete angular. Por ejemplo -

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; } }

Ejemplo de trabajo bifurcado

échale un vistazo aquí para obtener más información útil:

Si está utilizando Angular v5 o inferior o desea lograr el uso de tubería, siga esta respuesta

  • clave de acceso y valor del objeto usando ngfor

Aquí está la solución simple

Puede usar iteradores de mecanografía para esto

import {Component} from ''angular2/core''; declare var Symbol; @Component({ selector: ''my-app'', template:`<div> <h4>Iterating an Object using Typescript Symbol</h4><br> Object is : <p>{{obj | json}}</p> </div> ============================<br> Iterated object params are: <div *ngFor="#o of obj"> {{o}} </div> ` }) 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


Creo que Object.keys es la mejor solución para este problema. Para cualquiera que encuentre esta respuesta y esté tratando de descubrir por qué Object.keys les está dando [''0'', ''1''] en lugar de [''clave1'', ''clave2''], una historia de advertencia: tenga cuidado con la diferencia entre " de "y" en ":

Ya estaba usando Object.keys, algo similar a esto:

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

Sin embargo, en lugar de

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

Inadvertidamente escribí

myObj[''key'']

que "funcionó" perfectamente bien sin ningún error y regresó

<div *ngFor="let value of Objects; index as key">

Eso me costó unas 2 horas buscando en Google y maldiciendo ...

(golpea la frente)


Desde Angular 6.1 puede usar la tubería keyvalue :

<div *ngFor="let item of testObject | keyvalue"> Key: <b>{{item.key}}</b> and Value: <b>{{item.value}}</b> </div>

Pero tiene el inconveniente de que ordena la lista resultante por el valor clave. Si necesitas algo neutral:

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

No olvide especificar el atributo pure: false pipe. En este caso, la tubería se invoca en cada ciclo de detección de cambio, incluso si la referencia de entrada no ha cambiado (así es el caso cuando agrega propiedades a un objeto).


Elaboración de la respuesta de @ Thierry con ejemplo.

No hay una tubería o método incorporado para obtener la key and value del bucle * ngFor. entonces tenemos que crear una tubería personalizada para lo mismo. Como dijo Thierry, aquí está la respuesta con el código.

** La clase pipe implementa el método de transformación de la interfaz PipeTransform que toma un valor de entrada y una matriz opcional de cadenas de parámetros y devuelve el valor transformado.

** El método de transformación es esencial para una tubería. La interfaz PipeTransform define ese método y guía tanto las herramientas como el compilador. Es opcional; Angular busca y ejecuta el método de transformación independientemente. para más información sobre tuberías consulte aquí

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; } }

y la parte HTML es:

<ul> <li *ngFor=''#key of demo | keys''> Key: {{key.key}}, value: {{key.value}} </li> </ul>

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

actualizar a RC

según lo sugerido por user6123723 (gracias) en el comentario aquí está la actualización.

<ul> <li *ngFor=''let key of demo | keys''> Key: {{key.key}}, value: {{key.value}} </li> </ul>


Gracias por la tubería, pero tuve que hacer algunos cambios antes de poder usarla en angular 2 RC5. Cambió la línea de importación de Pipe y también agregó el tipo de any a la inicialización de la matriz de claves.

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; } }


Hay una biblioteca realmente agradable que hace esto entre otras buenas tuberías. Se llama ngx-pipes .

Por ejemplo, la tubería de claves devuelve las claves de un objeto, y la tubería de valores devuelve los valores de un objeto:

tubo de llaves

<div *ngFor="let key of {foo: 1, bar: 2} | keys">{{key}}</div> <!-- Output: ''foo'' and ''bar -->

tubería de valores

<div *ngFor="let value of {foo: 1, bar: 2} | values">{{value}}</div> <!-- Output: 1 and 2 -->

No es necesario crear su propia tubería personalizada :)


Ninguna de las respuestas aquí funcionó para mí fuera de la caja, esto es lo que funcionó para mí:

Crear pipes/keys.ts con contenido:

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; } }

Agregue a app.module.ts (su módulo principal):

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

y luego agregue al conjunto de declaraciones de su módulo algo como esto:

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

Luego, en su plantilla de vista, puede usar algo como esto:

<option *ngFor="let entry of (myData | keys)" value="{{ entry.key }}">{{ entry.value }}</option>

Aquí hay una buena referencia que encontré si quieres leer más.


Puede crear una tubería personalizada para devolver la lista de claves para cada elemento. Algo como eso:

<tr *ngFor="let c of content"> <td *ngFor="let key of c | keys">{{key}}: {{c[key]}}</td> </tr>

y úsalo así:

@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; } }

Editar

También puede devolver una entrada que contenga clave y valor:

<span *ngFor="let entry of content | keys"> Key: {{entry.key}}, value: {{entry.value}} </span>

y úsalo así:

<div *ngFor="let item of testObject | keyvalue"> Key: <b>{{item.key}}</b> and Value: <b>{{item.value}}</b> </div>


Si ya está usando Lodash, puede hacer este enfoque simple que incluye clave y valor:

<ul> <li *ngFor=''let key of _.keys(demo)''>{{key}}: {{demo[key]}}</li> </ul>

En el archivo mecanografiado, incluya:

import * as _ from ''lodash'';

y en el componente exportado, incluya:

_: any = _;


Tenga Object.keys accesibles en la plantilla y *ngFor en *ngFor .

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


Tienes que hacerlo así por ahora, sé que no es muy eficiente, ya que no quieres convertir el objeto que recibes de 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; });


cambiar el tipo de demostración a matriz o iterar sobre su objeto y pasar a otra matriz

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

y de html:

<div *ngFor="obj of details"> <p>{{obj.key}}</p> <p>{{obj.value}}</p> <p></p> </div>


puede obtener la clave del objeto dinámico al intentar esto

{{key}} -> {{value}}