在Angular中迭代对象

Ric*_*aaf 110 angular

我正在尝试在Angular 2 Alpha 28中做一些事情,并且我遇到了字典和NgFor的问题.

我有一个TypeScript接口,如下所示:

interface Dictionary {
    [ index: string ]: string
}
Run Code Online (Sandbox Code Playgroud)

在JavaScript中,这将转换为数据可能如下所示的对象:

myDict={'key1':'value1','key2':'value2'}
Run Code Online (Sandbox Code Playgroud)

我想迭代这个并尝试这个:

<div *ngFor="(#key, #value) of myDict">{{key}}:{{value}}</div>
Run Code Online (Sandbox Code Playgroud)

但无济于事,以下都没有:

<div *ngFor="#value of myDict">{{value}}</div>
<div *ngFor="#value of myDict #key=index">{{key}}:{{value}}</div>
Run Code Online (Sandbox Code Playgroud)

在所有情况下,我都会收到"意外令牌"或"无法找到'iterableDiff'管道支持对象"之类的错误

我在这里错过了什么?这不可能了吗?(第一种语法适用于Angular 1.x)或者是迭代对象的语法是不同的?

ber*_*ing 118

Angular 6.1.0+答案

像这样使用内置keyvalue管道:

<div *ngFor="let item of myObject | keyvalue">
    Key: <b>{{item.key}}</b> and Value: <b>{{item.value}}</b>
</div>
Run Code Online (Sandbox Code Playgroud)

或者像这样:

<div *ngFor="let item of myObject | keyvalue:mySortingFunction">
    Key: <b>{{item.key}}</b> and Value: <b>{{item.value}}</b>
</div>
Run Code Online (Sandbox Code Playgroud)

这里mySortingFunction是你的.ts文件,例如:

mySortingFunction = (a, b) => {
  return a.key > b.key ? -1 : 1;
}
Run Code Online (Sandbox Code Playgroud)

Stackblitz:https://stackblitz.com/edit/angular-iterate-key-value

您不需要在任何模块中注册它,因为Angular管道在任何模板中都是开箱即用的.

它也适用于Javascript-Maps.


前角6答案

正如其他答案所提到的那样,ngx不支持它,所以这里有一个关键值对的解决方法:

管道:

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
  name: 'mapToIterable'
})
export class MapToIterable implements PipeTransform {
  transform(dict: Object) {
    var a = [];
    for (var key in dict) {
      if (dict.hasOwnProperty(key)) {
        a.push({key: key, val: dict[key]});
      }
    }
    return a;
  }
}
Run Code Online (Sandbox Code Playgroud)

用法:

<div *ngFor="let keyValuePair of someObject | mapToIterable">
  This is the key {{keyValuePair.key}} and this is the value {{keyValuePair.val}}.
</div>
Run Code Online (Sandbox Code Playgroud)

Stackblitz示例:https://stackblitz.com/edit/map-to-iterable-pipe


Jes*_*ood 80

看起来他们不想支持ng1的语法.

根据MiškoHevery(参考):

地图在密钥中没有订单,因此它们的迭代是不可预测的.这在ng1中受到支持,但我们认为这是一个错误,并且在NG2中不受支持

计划是有一个mapToIterable管道

<div *ngFor"var item of map | mapToIterable">

因此,为了迭代您的对象,您将需要使用"管道".目前没有实现这样做的管道.

作为一种解决方法,这是一个迭代密钥的小例子:

零件:

import {Component} from 'angular2/core';

@Component({
  selector: 'component',
  templateUrl: `
       <ul>
       <li *ngFor="#key of keys();">{{key}}:{{myDict[key]}}</li>
       </ul>
  `
})
export class Home {
  myDict : Dictionary;
  constructor() {
    this.myDict = {'key1':'value1','key2':'value2'};
  }

  keys() : Array<string> {
    return Object.keys(this.myDict);
  }
}

interface Dictionary {
    [ index: string ]: string
}
Run Code Online (Sandbox Code Playgroud)


小智 71

尝试使用这个管道

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({ name: 'values',  pure: false })
export class ValuesPipe implements PipeTransform {
  transform(value: any, args: any[] = null): any {
    return Object.keys(value).map(key => value[key]);
  }
}

<div *ngFor="#value of object | values"> </div>
Run Code Online (Sandbox Code Playgroud)

  • 很棒,如果我想保留对键的引用,我将只用键和值映射一个对象.我希望我可以将几个答案标记为已接受的答案,因为这是我问题的解决方案,而明确的答案是我的问题的答案. (5认同)

Sim*_*ome 19

除了@ obscur的回答,这里有一个如何访问@View keyvalue来自@View的示例.

管:

@Pipe({
   name: 'keyValueFilter'
})

export class keyValueFilterPipe {
    transform(value: any, args: any[] = null): any {

        return Object.keys(value).map(function(key) {
            let pair = {};
            let k = 'key';
            let v = 'value'


            pair[k] = key;
            pair[v] = value[key];

            return pair;
        });
    }

}
Run Code Online (Sandbox Code Playgroud)

视图:

<li *ngFor="let u of myObject | 
keyValueFilter">First Name: {{u.key}} <br> Last Name: {{u.value}}</li>
Run Code Online (Sandbox Code Playgroud)

所以,如果对象看起来像:

myObject = {
    Daario: Naharis,
    Victarion: Greyjoy,
    Quentyn: Ball
}
Run Code Online (Sandbox Code Playgroud)

产生的结果将是:

名:Daario
姓:Naharis

名字:Victarion
姓:葛雷乔伊

名:Quentyn
姓:Ball

  • 只需提及一件事,您需要更改视图:as`&lt;li * ngFor =“ myObject的u | keyValueFilter”&gt;名字:{{u.key}} &lt;br&gt;姓氏:{{u.value} } &lt;/ li&gt;`。向我+1。 (2认同)

Fre*_*und 13

添加到SimonHawesome的优秀答案.我做了一个简洁的版本,利用了一些新的打字稿功能.我意识到SimonHawesome的版本是故意冗长的,以解释潜在的细节.我还添加了一个早期检查,以便管道适用于虚假值.例如,如果地图是null.

请注意,使用迭代器转换(如此处所示)可以更高效,因为我们不需要为临时数组分配内存(如在其他一些答案中所做的那样).

import {Pipe, PipeTransform} from '@angular/core';

@Pipe({
    name: 'mapToIterable'
})
export class MapToIterable implements PipeTransform {
    transform(map: { [key: string]: any }, ...parameters: any[]) {
        if (!map)
            return undefined;
        return Object.keys(map)
            .map((key) => ({ 'key': key, 'value': map[key] }));
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 喜欢这个主题,一个评论建立在另一个上面!当我看到你的代码时,我正打算写同样的东西 (3认同)
  • 这个解决方案中唯一的东西:它应该实现`PipeTransform` (3认同)

t.8*_*888 9

以下是一些支持多种转换(keyval,key,value)的上述答案的变体:

import { Pipe, PipeTransform } from '@angular/core';

type Args = 'keyval'|'key'|'value';

@Pipe({
  name: 'mapToIterable',
  pure: false
})
export class MapToIterablePipe implements PipeTransform {
  transform(obj: {}, arg: Args = 'keyval') {
    return arg === 'keyval' ?
        Object.keys(obj).map(key => ({key: key, value: obj[key]})) :
      arg === 'key' ?
        Object.keys(obj) :
      arg === 'value' ?
        Object.keys(obj).map(key => obj[key]) :
      null;
  }
}
Run Code Online (Sandbox Code Playgroud)

用法

map = {
    'a': 'aee',
    'b': 'bee',
    'c': 'see'
}

<div *ngFor="let o of map | mapToIterable">{{o.key}}: {{o.value}}</div>
  <div>a: aee</div>
  <div>b: bee</div>
  <div>c: see</div>

<div *ngFor="let o of map | mapToIterable:'keyval'">{{o.key}}: {{o.value}}</div>
  <div>a: aee</div>
  <div>b: bee</div>
  <div>c: see</div>

<div *ngFor="let k of map | mapToIterable:'key'">{{k}}</div>
  <div>a</div>
  <div>b</div>
  <div>c</div>

<div *ngFor="let v of map | mapToIterable:'value'">{{v}}</div>
  <div>aee</div>
  <div>bee</div>
  <div>see</div>
Run Code Online (Sandbox Code Playgroud)


Viv*_*shi 9

更新:Angular现在通过以下方式提供通过json对象的管道keyvalue:

<div *ngFor="let item of myDict | keyvalue">
  {{item.key}}:{{item.value}}
</div>
Run Code Online (Sandbox Code Playgroud)

工作演示,以及更多细节阅读


以前(旧版本):到目前为止我找到的最佳/最短答案是(没有任何管道过滤器或组件侧的自定义功能)

组件方面:

objectKeys = Object.keys;
Run Code Online (Sandbox Code Playgroud)

模板方面:

<div *ngFor='let key of objectKeys(jsonObj)'>
   Key: {{key}}

    <div *ngFor='let obj of jsonObj[key]'>
        {{ obj.title }}
        {{ obj.desc }}
    </div>

</div>
Run Code Online (Sandbox Code Playgroud)

工作演示