【问题标题】:How to loop over object properties with ngFor in Angular如何在Angular中使用ngFor循环对象属性
【发布时间】: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.

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

【问题讨论】:

    标签: javascript angular typescript ecmascript-6


    【解决方案1】:

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

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

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

    【讨论】:

    • 很好,但在我的情况下,我得到的第二个项目在 UI 中呈现为第一个。有什么建议吗?
    • 是的,我也遇到过这个问题 - 在这里提出了一个问题,看看是否有人有答案 - stackoverflow.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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-05-11
          • 2021-06-04
          • 2018-08-26
          • 2018-07-02
          • 2016-07-10
          相关资源
          最近更新 更多