如何在Angular中使用ngFor循环对象属性

Posted

技术标签:

【中文标题】如何在Angular中使用ngFor循环对象属性【英文标题】:How to loop over object properties with ngFor in Angular 【发布时间】:2018-01-30 19:52:15 【问题描述】:

这篇文章是关于我在工作中发现的一个有趣的问题。

如果你还不知道。我说的是 Angular 2+

问题

所以你想显示一个列表的标记,这个列表的值来自后端,由于某种原因,你收到的不是一个很好的旧对象数组。

     
  "car" : 
     
       "color" : "red",
       "model" : "2013"
    ,
   "motorcycle": 
     
       "color" : "red",
       "model" : "2016"
    ,
   "bicycle": 
     
       "color" : "red",
       "model" : "2011"
    

然后你尝试使用 *ngFor 但出现了一条错误消息:

Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.

你可以在后端修复它,这样你就得到了一个对象数组,但不是没有人有时间去做。别担心,孩子,我有我们。

【问题讨论】:

【参考方案1】:

在 Angular 6.1 中引入了 KeyValuePipe,它允许您迭代对象属性:

<div *ngFor="let item of object | keyvalue">
  item.key:item.value
</div>

文档:https://angular.io/api/common/KeyValuePipe

【讨论】:

很好,但在我的情况下,我得到的第二个项目在 UI 中呈现为第一个。有什么建议吗? 是的,我也遇到过这个问题 - 在这里提出了一个问题,看看是否有人有答案 - ***.com/questions/52793944/… 在上述评论的链接中查看@ConnorsFan 的回答【参考方案2】:

我不知道这是否安全,但对于这些简单的情况,我不喜欢管道解决方案,所以我通常使用:

<div *ngFor="let k of objectKeys(yourObject)">
    yourObject[k].color
</div>

在控制器中:

objectKeys(obj) 
    return Object.keys(obj);

这是一个很常见的情况,我不明白为什么没有像 Angular.js 1.x 这样的标准实现

【讨论】:

这是最好的! 不要在模板中使用函数(事件除外)。它会减慢您的应用程序,而是创建一个管道。角度变化检测会经常调用这个函数,因为如果想知道值是否发生变化,它必须调用它,它会被变化检测循环调用,这会导致应用程序运行缓慢。【参考方案3】:

更好的解决方案是使用这样的管道:

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

/**
 * Convert Object to array of keys.
 */
@Pipe(
  name: 'appProperties'
)
export class PropertiesPipe implements PipeTransform 

  transform(value: ): string[] 

    if (!value) 
      return [];
    

    return Object.keys(value);
  

然后在你的模板中:

<div *ngFor="let property of response | appProperties">
    <div *ngFor="let item of response[property]">
         item.something
    </div>
</div>

【讨论】:

你是对的,如果项目在多个实例中需要它,你的解决方案似乎更具可扩展性。【参考方案4】:
    <div *ngFor="let item of donation_list | keyvalue">
        <div class="donation-box">
             <Label class="donation-label">Date : item.value.PaymentDate</Label>
             <Label class="donation-label">Time : item.value.PaymentTime</Label>

        </div>
   </div>

如果对象内部有更多属性,可以这样使用。

【讨论】:

【参考方案5】:

使用 Object.values 从您的对象中获取常规数组。 Object.keys 似乎有很多不必要的工作。

参考: https://developer.mozilla.org/en-US/docs/Web/javascript/Reference/Global_objects/Object/values

【讨论】:

【参考方案6】:

解决方案

在一个完美的世界里,你会得到一个对象数组,因为这个世界并不总是完美的。您想要做的是将所有这些对象存储在一个数组中。这是一个使用普通旧 JavaScript 的过度简化的解决方案。

第 1 步。 获取所有对象键。使用 Object.keys。此方法返回给定对象自己的可枚举属性的数组。

第 2 步。 创建一个空数组。这是所有属性都将存在的地方,因为您的新 ngFor 循环将指向该数组,我们必须将它们全部捕获。

第 3 步。 迭代抛出所有键,并将每个键推入您创建的数组中。

这是代码中的样子。

// Evil response in a variable. Here are all my vehicles.
let evilResponse =  
  "car" : 
     
       "color" : "red",
       "model" : "2013"
    ,
   "motorcycle": 
     
       "color" : "red",
       "model" : "2016"
    ,
   "bicycle": 
     
       "color" : "red",
       "model" : "2011"
    

// Step 1. Get all the object keys.
let evilResponseProps = Object.keys(evilResponse);
// Step 2. Create an empty array.
let goodResponse = [];
// Step 3. Iterate throw all keys.
for (prop of evilResponseProps)  
    goodResponse.push(evilResponseProps[prop]);

然后您可以将 goodResponse 分配给您一开始尝试迭代的类属性。

这就是所有人。

【讨论】:

这种没有显示如何在 ngFor 中迭代属性,这是 aked。这就是你在 javascript 中的做法。 evilResponseProps[prop] 应该是 evilResponse[prop]。 你也可以这样做: Object.keys(evilResponse).forEach(function (key) goodResponse.push(evilResponse[key]; 这根本不是所提问题的答案。【参考方案7】:

你可以试试这个:

<div *ngFor="let item of object | keyvalue">
  item.key:item.value
</div>

欲了解更多信息,请访问:https://angular.io/api/common/KeyValuePipe

【讨论】:

以上是关于如何在Angular中使用ngFor循环对象属性的主要内容,如果未能解决你的问题,请参考以下文章

*ngFor 在 angular2 中运行无限循环

如何用管道翻译 Ionic/Angular 中 *ngFor 循环的返回

Angular 4 ngFor使用HTML循环遍历对象数组

Angular2 ngFor如何计算循环值的数量?

Angular - 如何将 ngFor 过滤到特定的对象属性数据

如何使用angular4在ngFor循环中显示嵌套的@component?